From 8fa7425c6394117a541de82826d128d6c3d9161b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 1 Jul 2008 10:44:48 +0300 Subject: iwlwifi: fix error path of iwl_rfkill_init This patch cleans rfkill error path. The problem was result of removing the input device Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index aa9f31eadab..eebaf43f66b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -101,17 +101,13 @@ int iwl_rfkill_init(struct iwl_priv *priv) ret = rfkill_register(priv->rfkill_mngr.rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); - goto unregister_rfkill; + goto free_rfkill; } IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; -unregister_rfkill: - rfkill_unregister(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; - -freed_rfkill: +free_rfkill: if (priv->rfkill_mngr.rfkill != NULL) rfkill_free(priv->rfkill_mngr.rfkill); priv->rfkill_mngr.rfkill = NULL; -- cgit v1.2.3 From 3235427ecb092e4ff86528edd775e759dbeeecff Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 1 Jul 2008 10:44:51 +0300 Subject: iwlwifi: request Tx of block ack request if necessary This patch sets the block ack request flag if needed Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8c93f8d56a7..04365b39279 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2285,9 +2285,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { - /* TODO: send BAR */ - } + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; if (txq->q.read_ptr != (scd_ssn & 0xff)) { int freed, ampdu_q; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cc73e9a711..717db0d5ffb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1278,9 +1278,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { - /* TODO: send BAR */ - } + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; if (txq->q.read_ptr != (scd_ssn & 0xff)) { int freed, ampdu_q; -- cgit v1.2.3 From 80fcc9e28cf3a209fbfb39a7bbddc313c59c7424 Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Tue, 1 Jul 2008 17:49:50 +0200 Subject: iwlwifi: remove input device and fix rfkill state This patch fixes the iwlwifi rfkill. It removes the input device from iwl3945, adds support for RFKILL_STATE_HARD_BLOCKED and calls rfkill_force_state() to update the state rather than accessing it directly. The calls to iwl|iwl3945_rfkill_set_hw_state() had to be moved because rfkill_force_state() cannot be called from an atomic context. Tested on iwl3945 and seems to work fine. Cc: Randy Dunlap Cc: Ivo van Doorn Cc: Fabien Crespel Cc: Zhu Yi Cc: Henrique de Moraes Holschuh Signed-off-by: Adel Gadllah Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 5 ++ drivers/net/wireless/iwlwifi/iwl-3945.h | 11 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 13 +++- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 57 +++++++------- drivers/net/wireless/iwlwifi/iwl-rfkill.h | 3 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 117 ++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 +- 8 files changed, 105 insertions(+), 111 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b628a44057f..82b66a3d3a5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -104,6 +104,7 @@ config IWL3945 select IWLWIFI select MAC80211_LEDS if IWL3945_LEDS select LEDS_CLASS if IWL3945_LEDS + select RFKILL if IWL3945_RFKILL ---help--- Select to build the driver supporting the: @@ -126,6 +127,10 @@ config IWL3945 say M here and read . The module will be called iwl3945.ko. +config IWL3945_RFKILL + bool "Enable RF kill support in iwl3945 drivers" + depends on IWL3945 + config IWL3945_SPECTRUM_MEASUREMENT bool "Enable Spectrum Measurement in iwl3945 drivers" depends on IWL3945 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a77497809d9..9c0a09eaca6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -690,14 +690,9 @@ enum { #endif -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWL3945_RFKILL struct iwl3945_priv; -struct iwl3945_rfkill_mngr { - struct rfkill *rfkill; - struct input_dev *input_dev; -}; - void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); int iwl3945_rfkill_init(struct iwl3945_priv *priv); @@ -800,8 +795,8 @@ struct iwl3945_priv { struct iwl3945_init_alive_resp card_alive_init; struct iwl3945_alive_resp card_alive; -#ifdef CONFIG_IWLWIFI_RFKILL - struct iwl3945_rfkill_mngr rfkill_mngr; +#ifdef CONFIG_IWL3945_RFKILL + struct rfkill *rfkill; #endif #ifdef CONFIG_IWL3945_LEDS diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index eb4abe1ebbd..dafd62c7dfd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -356,10 +356,19 @@ static inline int iwl_is_init(struct iwl_priv *priv) return test_bit(STATUS_INIT, &priv->status); } +static inline int iwl_is_rfkill_sw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + static inline int iwl_is_rfkill(struct iwl_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); + return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv); } static inline int iwl_is_ready_rf(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1289cfc213..70e10ea35a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -929,7 +929,7 @@ struct iwl_priv { struct iwl_init_alive_resp card_alive_init; struct iwl_alive_resp card_alive; #ifdef CONFIG_IWLWIFI_RFKILL - struct iwl_rfkill_mngr rfkill_mngr; + struct rfkill *rfkill; #endif #ifdef CONFIG_IWLWIFI_LEDS diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index eebaf43f66b..e5e5846e9f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -44,7 +44,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) struct iwl_priv *priv = data; int err = 0; - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -55,20 +55,20 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_UNBLOCKED: - iwl_radio_kill_sw_enable_radio(priv); - /* if HW rf-kill is set dont allow ON state */ - if (iwl_is_rfkill(priv)) + if (iwl_is_rfkill_hw(priv)) { err = -EBUSY; + goto out_unlock; + } + iwl_radio_kill_sw_enable_radio(priv); break; case RFKILL_STATE_SOFT_BLOCKED: iwl_radio_kill_sw_disable_radio(priv); - if (!iwl_is_rfkill(priv)) - err = -EBUSY; break; default: IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); break; } +out_unlock: mutex_unlock(&priv->mutex); return err; @@ -82,23 +82,23 @@ int iwl_rfkill_init(struct iwl_priv *priv) BUG_ON(device == NULL); IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); - priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill_mngr.rfkill) { + priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill) { IWL_ERROR("Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } - priv->rfkill_mngr.rfkill->name = priv->cfg->name; - priv->rfkill_mngr.rfkill->data = priv; - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; - priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; - priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; + priv->rfkill->name = priv->cfg->name; + priv->rfkill->data = priv; + priv->rfkill->state = RFKILL_STATE_UNBLOCKED; + priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; + priv->rfkill->user_claim_unsupported = 1; - priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; - priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + priv->rfkill->dev.class->suspend = NULL; + priv->rfkill->dev.class->resume = NULL; - ret = rfkill_register(priv->rfkill_mngr.rfkill); + ret = rfkill_register(priv->rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); goto free_rfkill; @@ -108,9 +108,9 @@ int iwl_rfkill_init(struct iwl_priv *priv) return ret; free_rfkill: - if (priv->rfkill_mngr.rfkill != NULL) - rfkill_free(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; + if (priv->rfkill != NULL) + rfkill_free(priv->rfkill); + priv->rfkill = NULL; error: IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); @@ -121,22 +121,27 @@ EXPORT_SYMBOL(iwl_rfkill_init); void iwl_rfkill_unregister(struct iwl_priv *priv) { - if (priv->rfkill_mngr.rfkill) - rfkill_unregister(priv->rfkill_mngr.rfkill); + if (priv->rfkill) + rfkill_unregister(priv->rfkill); - priv->rfkill_mngr.rfkill = NULL; + priv->rfkill = NULL; } EXPORT_SYMBOL(iwl_rfkill_unregister); /* set rf-kill to the right state. */ void iwl_rfkill_set_hw_state(struct iwl_priv *priv) { - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return; - if (!iwl_is_rfkill(priv)) - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + if (iwl_is_rfkill_hw(priv)) { + rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); + return; + } + + if (!iwl_is_rfkill_sw(priv)) + rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); else - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; + rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); } EXPORT_SYMBOL(iwl_rfkill_set_hw_state); diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index 00692d2e9bd..402fd4c781d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -33,9 +33,6 @@ struct iwl_priv; #include #ifdef CONFIG_IWLWIFI_RFKILL -struct iwl_rfkill_mngr { - struct rfkill *rfkill; -}; void iwl_rfkill_set_hw_state(struct iwl_priv *priv); void iwl_rfkill_unregister(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index baa1abd5a14..1a7d18fea89 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -537,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv) return test_bit(STATUS_INIT, &priv->status); } +static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) +{ + return test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); + return iwl3945_is_rfkill_hw(priv) || + iwl3945_is_rfkill_sw(priv); } static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) @@ -6013,12 +6023,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv) else { set_bit(STATUS_RF_KILL_HW, &priv->status); if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { - iwl3945_rfkill_set_hw_state(priv); IWL_WARNING("Radio disabled by HW RF Kill switch\n"); return -ENODEV; } } - iwl3945_rfkill_set_hw_state(priv); + iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); rc = iwl3945_hw_nic_init(priv); @@ -6143,8 +6152,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) "wireless networking to work.\n"); } - iwl3945_rfkill_set_hw_state(priv); mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); } static void iwl3945_bg_set_monitor(struct work_struct *work) @@ -6398,6 +6407,7 @@ static void iwl3945_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl3945_up(priv); mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); } static void iwl3945_bg_restart(struct work_struct *data) @@ -6618,6 +6628,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); + if (ret) goto out_release_irq; @@ -8276,14 +8288,14 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ /*************** RFKILL FUNCTIONS **********/ -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWL3945_RFKILL /* software rf-kill from user */ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) { struct iwl3945_priv *priv = data; int err = 0; - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -8294,20 +8306,20 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_UNBLOCKED: - iwl3945_radio_kill_sw(priv, 0); - /* if HW rf-kill is set dont allow ON state */ - if (iwl3945_is_rfkill(priv)) + if (iwl3945_is_rfkill_hw(priv)) { err = -EBUSY; + goto out_unlock; + } + iwl3945_radio_kill_sw(priv, 0); break; case RFKILL_STATE_SOFT_BLOCKED: iwl3945_radio_kill_sw(priv, 1); - if (!iwl3945_is_rfkill(priv)) - err = -EBUSY; break; default: IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); break; } +out_unlock: mutex_unlock(&priv->mutex); return err; @@ -8321,64 +8333,35 @@ int iwl3945_rfkill_init(struct iwl3945_priv *priv) BUG_ON(device == NULL); IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); - priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill_mngr.rfkill) { + priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill) { IWL_ERROR("Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } - priv->rfkill_mngr.rfkill->name = priv->cfg->name; - priv->rfkill_mngr.rfkill->data = priv; - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; - priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; - priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; - - priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; - priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + priv->rfkill->name = priv->cfg->name; + priv->rfkill->data = priv; + priv->rfkill->state = RFKILL_STATE_UNBLOCKED; + priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; + priv->rfkill->user_claim_unsupported = 1; - priv->rfkill_mngr.input_dev = input_allocate_device(); - if (!priv->rfkill_mngr.input_dev) { - IWL_ERROR("Unable to allocate rfkill input device.\n"); - ret = -ENOMEM; - goto freed_rfkill; - } + priv->rfkill->dev.class->suspend = NULL; + priv->rfkill->dev.class->resume = NULL; - priv->rfkill_mngr.input_dev->name = priv->cfg->name; - priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); - priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; - priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; - priv->rfkill_mngr.input_dev->dev.parent = device; - priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); - - ret = rfkill_register(priv->rfkill_mngr.rfkill); + ret = rfkill_register(priv->rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); - goto free_input_dev; - } - - ret = input_register_device(priv->rfkill_mngr.input_dev); - if (ret) { - IWL_ERROR("Unable to register rfkill input device: %d\n", ret); - goto unregister_rfkill; + goto freed_rfkill; } IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; -unregister_rfkill: - rfkill_unregister(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; - -free_input_dev: - input_free_device(priv->rfkill_mngr.input_dev); - priv->rfkill_mngr.input_dev = NULL; - freed_rfkill: - if (priv->rfkill_mngr.rfkill != NULL) - rfkill_free(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; + if (priv->rfkill != NULL) + rfkill_free(priv->rfkill); + priv->rfkill = NULL; error: IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); @@ -8387,28 +8370,28 @@ error: void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) { + if (priv->rfkill) + rfkill_unregister(priv->rfkill); - if (priv->rfkill_mngr.input_dev) - input_unregister_device(priv->rfkill_mngr.input_dev); - - if (priv->rfkill_mngr.rfkill) - rfkill_unregister(priv->rfkill_mngr.rfkill); - - priv->rfkill_mngr.input_dev = NULL; - priv->rfkill_mngr.rfkill = NULL; + priv->rfkill = NULL; } /* set rf-kill to the right state. */ void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) { - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) + return; + + if (iwl3945_is_rfkill_hw(priv)) { + rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); return; + } - if (!iwl3945_is_rfkill(priv)) - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + if (!iwl3945_is_rfkill_sw(priv)) + rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); else - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; + rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 60b7a6498fe..7f65d9123b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2187,13 +2187,11 @@ static int __iwl4965_up(struct iwl_priv *priv) if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && iwl_is_rfkill(priv)) { - iwl_rfkill_set_hw_state(priv); IWL_WARNING("Radio disabled by %s RF Kill switch\n", test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); return -ENODEV; } - iwl_rfkill_set_hw_state(priv); iwl_write32(priv, CSR_INT, 0xFFFFFFFF); ret = priv->cfg->ops->lib->alloc_shared_mem(priv); @@ -2330,9 +2328,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) "Kill switch must be turned off for " "wireless networking to work.\n"); } - iwl_rfkill_set_hw_state(priv); - mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); } static void iwl4965_bg_set_monitor(struct work_struct *work) @@ -2390,6 +2387,7 @@ static void iwl4965_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl4965_up(priv); mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); } static void iwl4965_bg_restart(struct work_struct *data) @@ -2604,6 +2602,8 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); + if (ret) goto out_release_irq; -- cgit v1.2.3 From 994d31f7430c3639b73c6ee038bd437c926b1227 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 2 Jul 2008 12:17:06 +0200 Subject: iwlwifi: fix typo which caused iwl_get_tx_fail_reason to ever return an empty string Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 70e10ea35a5..c8d3d97cf48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1103,7 +1103,7 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) clear_bit(txq_id, &priv->txq_ctx_active_msk); } -#ifdef CONFIG_IWLWIF_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_get_tx_fail_reason(u32 status); #else static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 032641d4c7d..0be2a71990b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1493,7 +1493,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); -#ifdef CONFIG_IWLWIF_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x const char *iwl_get_tx_fail_reason(u32 status) -- cgit v1.2.3 From f2cae6c5e41a979f85463aff60877b31fa3a383d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 4 Jul 2008 04:30:49 +0100 Subject: zd1211rw: beacon config error checking Add some error checking to the new beacon configuration code. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 62 ++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 317c5e24f80..665f76af2fe 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -405,43 +405,66 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, /* FIXME: Management frame? */ } -void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) +static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) { struct zd_mac *mac = zd_hw_mac(hw); + int r; u32 tmp, j = 0; /* 4 more bytes for tail CRC */ u32 full_len = beacon->len + 4; - zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); - zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); + if (r < 0) + return r; + r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + if (r < 0) + return r; + while (tmp & 0x2) { - zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + if (r < 0) + return r; if ((++j % 100) == 0) { printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); if (j >= 500) { printk(KERN_ERR "Giving up beacon config.\n"); - return; + return -ETIMEDOUT; } } msleep(1); } - zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); - if (zd_chip_is_zd1211b(&mac->chip)) - zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); + if (r < 0) + return r; + if (zd_chip_is_zd1211b(&mac->chip)) { + r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); + if (r < 0) + return r; + } - for (j = 0 ; j < beacon->len; j++) - zd_iowrite32(&mac->chip, CR_BCN_FIFO, + for (j = 0 ; j < beacon->len; j++) { + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, *((u8 *)(beacon->data + j))); + if (r < 0) + return r; + } - for (j = 0; j < 4; j++) - zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); + for (j = 0; j < 4; j++) { + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); + if (r < 0) + return r; + } + + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); + if (r < 0) + return r; - zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); /* 802.11b/g 2.4G CCK 1Mb * 802.11a, not yet implemented, uses different values (see GPL vendor * driver) */ - zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | + return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | (full_len << 19)); } @@ -699,15 +722,20 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, { struct zd_mac *mac = zd_hw_mac(hw); int associated; + int r; if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || mac->type == IEEE80211_IF_TYPE_IBSS) { associated = true; if (conf->beacon) { - zd_mac_config_beacon(hw, conf->beacon); - kfree_skb(conf->beacon); - zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | + r = zd_mac_config_beacon(hw, conf->beacon); + if (r < 0) + return r; + r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | hw->conf.beacon_int); + if (r < 0) + return r; + kfree_skb(conf->beacon); } } else associated = is_valid_ether_addr(conf->bssid); -- cgit v1.2.3 From 50db7875d9dcd89f7624b13535738612faf8db0c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 14:51:39 +0200 Subject: rt2x00: Remove input_polldev requirements for rfkill With the new rfkill interface there is no longer a need for the input_polldev. Create a delayed_work structure which we can put on the mac80211 workqueue and poll the hardware every 1000ms. v2: Decrease poll frequency from 100ms to 1000ms Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 8 +-- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 - drivers/net/wireless/rt2x00/rt2x00lib.h | 12 +--- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 107 +++++++++-------------------- 5 files changed, 38 insertions(+), 93 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 3a9b1d72caf..d485a86bba7 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -36,9 +36,7 @@ config RT2X00_LIB_FIRMWARE config RT2X00_LIB_RFKILL boolean depends on RT2X00_LIB - depends on INPUT select RFKILL - select INPUT_POLLDEV config RT2X00_LIB_LEDS boolean @@ -57,7 +55,7 @@ config RT2400PCI config RT2400PCI_RFKILL bool "Ralink rt2400 rfkill support" - depends on RT2400PCI && INPUT + depends on RT2400PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2400 hardware that features a @@ -85,7 +83,7 @@ config RT2500PCI config RT2500PCI_RFKILL bool "Ralink rt2500 rfkill support" - depends on RT2500PCI && INPUT + depends on RT2500PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2500 hardware that features a @@ -115,7 +113,7 @@ config RT61PCI config RT61PCI_RFKILL bool "Ralink rt2501/rt61 rfkill support" - depends on RT61PCI && INPUT + depends on RT61PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt61 hardware that features a diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6842464dcf3..1b28dad7f20 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -649,7 +649,7 @@ struct rt2x00_dev { #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 struct rfkill *rfkill; - struct input_polled_dev *poll_dev; + struct delayed_work rfkill_work; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index ae8ab71fe47..41b3289b828 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1179,7 +1179,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) * Suspend/disable extra components. */ rt2x00leds_suspend(rt2x00dev); - rt2x00rfkill_suspend(rt2x00dev); rt2x00debug_deregister(rt2x00dev); exit: @@ -1235,7 +1234,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) * Restore/enable extra components. */ rt2x00debug_register(rt2x00dev); - rt2x00rfkill_resume(rt2x00dev); rt2x00leds_resume(rt2x00dev); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 1d1f0749375..eae5ce1d4de 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,7 +33,7 @@ * Both the link tuner as the rfkill will be called once per second. */ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( 1000 ) +#define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) /* * rt2x00_rate: Per rate device information @@ -204,8 +204,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev); -void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev); -void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev); #else static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) { @@ -222,14 +220,6 @@ static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { } - -static inline void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) -{ -} #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 207281cfa8b..04b29716d35 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -23,7 +23,6 @@ Abstract: rt2x00 rfkill routines. */ -#include #include #include #include @@ -61,15 +60,35 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) return retval; } -static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) +static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) { - struct rt2x00_dev *rt2x00dev = poll_dev->private; - int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + struct rt2x00_dev *rt2x00dev = data; - if (rt2x00dev->rfkill->state != state) { - input_report_key(poll_dev->input, KEY_WLAN, 1); - input_report_key(poll_dev->input, KEY_WLAN, 0); - } + *state = rt2x00dev->rfkill->state; + + return 0; +} + +static void rt2x00rfkill_poll(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, rfkill_work.work); + int state; + + if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) + return; + + /* + * rfkill_poll reports 1 when the key has been pressed and the + * radio should be blocked. + */ + state = !rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + + rfkill_force_state(rt2x00dev->rfkill, state); + + queue_delayed_work(rt2x00dev->hw->workqueue, + &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); } void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -83,12 +102,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) return; } - if (input_register_polled_device(rt2x00dev->poll_dev)) { - ERROR(rt2x00dev, "Failed to register polled device.\n"); - rfkill_unregister(rt2x00dev->rfkill); - return; - } - __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); /* @@ -96,7 +109,7 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) * and correctly sends the signal to the rfkill layer about this * state. */ - rt2x00rfkill_poll(rt2x00dev->poll_dev); + rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); } void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) @@ -105,38 +118,13 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - input_unregister_polled_device(rt2x00dev->poll_dev); + cancel_delayed_work_sync(&rt2x00dev->rfkill_work); + rfkill_unregister(rt2x00dev->rfkill); __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); } -static struct input_polled_dev * -rt2x00rfkill_allocate_polldev(struct rt2x00_dev *rt2x00dev) -{ - struct input_polled_dev *poll_dev; - - poll_dev = input_allocate_polled_device(); - if (!poll_dev) - return NULL; - - poll_dev->private = rt2x00dev; - poll_dev->poll = rt2x00rfkill_poll; - poll_dev->poll_interval = RFKILL_POLL_INTERVAL; - - poll_dev->input->name = rt2x00dev->ops->name; - poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); - poll_dev->input->id.bustype = BUS_HOST; - poll_dev->input->id.vendor = 0x1814; - poll_dev->input->id.product = rt2x00dev->chip.rt; - poll_dev->input->id.version = rt2x00dev->chip.rev; - poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); - poll_dev->input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, poll_dev->input->keybit); - - return poll_dev; -} - void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) @@ -153,14 +141,9 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) rt2x00dev->rfkill->data = rt2x00dev; rt2x00dev->rfkill->state = -1; rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; + rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; - rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); - if (!rt2x00dev->poll_dev) { - ERROR(rt2x00dev, "Failed to allocate polled device.\n"); - rfkill_free(rt2x00dev->rfkill); - rt2x00dev->rfkill = NULL; - return; - } + INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); return; } @@ -171,32 +154,8 @@ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; - input_free_polled_device(rt2x00dev->poll_dev); - rt2x00dev->poll_dev = NULL; + cancel_delayed_work_sync(&rt2x00dev->rfkill_work); rfkill_free(rt2x00dev->rfkill); rt2x00dev->rfkill = NULL; } - -void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || - !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) - return; - - input_free_polled_device(rt2x00dev->poll_dev); - rt2x00dev->poll_dev = NULL; -} - -void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || - !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) - return; - - rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); - if (!rt2x00dev->poll_dev) { - ERROR(rt2x00dev, "Failed to allocate polled device.\n"); - return; - } -} -- cgit v1.2.3 From ff352391acfac1e183c8c8b2858f9393bd064a65 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 14:56:07 +0200 Subject: rt2x00: Decrease alignment headroom We only need 4 bytes of headroom for alignment purposes in the RX frame. It was previously higher for optimization purposes which are no longer possible due to DMA mappings. v2: Fix patch error Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 8e86611791f..3ddce538ef4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -45,10 +45,11 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, frame_size = entry->queue->data_size + entry->queue->desc_size; /* - * Reserve a few bytes extra headroom to allow drivers some moving - * space (e.g. for alignment), while keeping the skb aligned. + * The payload should be aligned to a 4-byte boundary, + * this means we need at least 3 bytes for moving the frame + * into the correct offset. */ - reserved_size = 8; + reserved_size = 4; /* * Allocate skbuffer. -- cgit v1.2.3 From 8e260c22238dd8b57aefb1f5e4bd114486a9c17d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 13:41:31 +0200 Subject: rt2x00: Use ieee80211_hw->workqueue again Remove the rt2x00 singlethreaded workqueue and move the link tuner and packet filter scheduled work to the ieee80211_hw->workqueue again. The only exception is the interface scheduled work handler which uses the mac80211 interface iterator under the RTNL lock. This work needs to be handled on the kernel workqueue to prevent lockdep issues. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 4 +++- drivers/net/wireless/rt2x00/rt2x00dev.c | 17 +++-------------- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 ++-- 3 files changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1b28dad7f20..c07d9ef383f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -787,8 +787,10 @@ struct rt2x00_dev { /* * Scheduled work. + * NOTE: intf_work will use ieee80211_iterate_active_interfaces() + * which means it cannot be placed on the hw->workqueue + * due to RTNL locking requirements. */ - struct workqueue_struct *workqueue; struct work_struct intf_work; struct work_struct filter_work; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 41b3289b828..8086263e5fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -74,7 +74,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) rt2x00lib_reset_link_tuner(rt2x00dev); - queue_delayed_work(rt2x00dev->workqueue, + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -392,7 +392,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; - queue_delayed_work(rt2x00dev->workqueue, + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -496,7 +496,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) rt2x00lib_beacondone_iter, rt2x00dev); - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + schedule_work(&rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1064,10 +1064,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); - if (!rt2x00dev->workqueue) - goto exit; - INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1127,13 +1123,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00rfkill_free(rt2x00dev); rt2x00leds_unregister(rt2x00dev); - /* - * Stop all queued work. Note that most tasks will already be halted - * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). - */ - flush_workqueue(rt2x00dev->workqueue); - destroy_workqueue(rt2x00dev->workqueue); - /* * Free ieee80211_hw memory. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 1253da89295..3a1fb6d47e5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); else - queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); @@ -512,7 +512,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); if (delayed) { intf->delayed_flags |= delayed; - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + schedule_work(&rt2x00dev->intf_work); } spin_unlock(&intf->lock); } -- cgit v1.2.3 From ae73e58ea64f121b26437a10937330e77ff48f33 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 16:14:59 +0200 Subject: rt2x00: Report RX end time for rt2400pci rt2400 is the only currently available rt2x00 driver which supports reporting of the RX end time for frames. Since mac80211 uses this information for IBSS syncing, it is important that it is being reported. v2: Complement 32 bits of RX timestamp with upper 32bits from TSF Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 23 +++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 1 + drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 3 files changed, 26 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index b3dffcfed83..ee953ca0c6a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1087,25 +1087,48 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2400pci_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; u32 word0; u32 word2; u32 word3; + u32 word4; + u64 tsf; + u32 rx_low; + u32 rx_high; rt2x00_desc_read(entry_priv->desc, 0, &word0); rt2x00_desc_read(entry_priv->desc, 2, &word2); rt2x00_desc_read(entry_priv->desc, 3, &word3); + rt2x00_desc_read(entry_priv->desc, 4, &word4); if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + /* + * We only get the lower 32bits from the timestamp, + * to get the full 64bits we must complement it with + * the timestamp from get_tsf(). + * Note that when a wraparound of the lower 32bits + * has occurred between the frame arrival and the get_tsf() + * call, we must decrease the higher 32bits with 1 to get + * to correct value. + */ + tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); + rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); + rx_high = upper_32_bits(tsf); + + if ((u32)tsf <= rx_low) + rx_high--; + /* * Obtain the status about this packet. * The signal is the PLCP value, and needs to be stripped * of the preamble bit (0x08). */ + rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 8086263e5fa..b48c04e80a3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -664,6 +664,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rt2x00dev->link.qual.rx_success++; + rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = idx; rx_status->qual = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 5dd9cca3c62..8945945c892 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -146,6 +146,7 @@ enum rxdone_entry_desc_flags { * * Summary of information that has been read from the RX frame descriptor. * + * @timestamp: RX Timestamp * @signal: Signal of the received frame. * @rssi: RSSI of the received frame. * @size: Data size of the received frame. @@ -154,6 +155,7 @@ enum rxdone_entry_desc_flags { */ struct rxdone_entry_desc { + u64 timestamp; int signal; int rssi; int size; -- cgit v1.2.3 From 70197ede33134725f3e2e606fcabc28b0a4549a3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 4 Jul 2008 08:39:01 -0500 Subject: b43legacy: Remove switch statement with 64-bit index The gcc 3.4 fork used to compile the MN10300 port emits unwanted __ucmpdi2() calls for switch statements that use a 64bit value. This patch removes such a switch from b43legacy, and makes the code more like that used in b43. Thanks to Adrian Bunk for reporting the problem. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/dma.c | 66 ++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index eb0243a2269..fb6819e40f3 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -859,6 +859,18 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev) return DMA_30BIT_MASK; } +static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask) +{ + if (dmamask == DMA_30BIT_MASK) + return B43legacy_DMA_30BIT; + if (dmamask == DMA_32BIT_MASK) + return B43legacy_DMA_32BIT; + if (dmamask == DMA_64BIT_MASK) + return B43legacy_DMA_64BIT; + B43legacy_WARN_ON(1); + return B43legacy_DMA_30BIT; +} + /* Main initialization function. */ static struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, @@ -1018,6 +1030,43 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) dma->tx_ring0 = NULL; } +static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) +{ + u64 orig_mask = mask; + bool fallback = 0; + int err; + + /* Try to set the DMA mask. If it fails, try falling back to a + * lower mask, as we can always also support a lower one. */ + while (1) { + err = ssb_dma_set_mask(dev->dev, mask); + if (!err) + break; + if (mask == DMA_64BIT_MASK) { + mask = DMA_32BIT_MASK; + fallback = 1; + continue; + } + if (mask == DMA_32BIT_MASK) { + mask = DMA_30BIT_MASK; + fallback = 1; + continue; + } + b43legacyerr(dev->wl, "The machine/kernel does not support " + "the required %u-bit DMA mask\n", + (unsigned int)dma_mask_to_engine_type(orig_mask)); + return -EOPNOTSUPP; + } + if (fallback) { + b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-" + "bit\n", + (unsigned int)dma_mask_to_engine_type(orig_mask), + (unsigned int)dma_mask_to_engine_type(mask)); + } + + return 0; +} + int b43legacy_dma_init(struct b43legacy_wldev *dev) { struct b43legacy_dma *dma = &dev->dma; @@ -1027,21 +1076,8 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) enum b43legacy_dmatype type; dmamask = supported_dma_mask(dev); - switch (dmamask) { - default: - B43legacy_WARN_ON(1); - case DMA_30BIT_MASK: - type = B43legacy_DMA_30BIT; - break; - case DMA_32BIT_MASK: - type = B43legacy_DMA_32BIT; - break; - case DMA_64BIT_MASK: - type = B43legacy_DMA_64BIT; - break; - } - - err = ssb_dma_set_mask(dev->dev, dmamask); + type = dma_mask_to_engine_type(dmamask); + err = b43legacy_dma_set_mask(dev, dmamask); if (err) { #ifdef CONFIG_B43LEGACY_PIO b43legacywarn(dev->wl, "DMA for this device not supported. " -- cgit v1.2.3 From 0ac2a00c1035c749b720c4d817beea1795f02d47 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sun, 6 Jul 2008 09:12:30 -0400 Subject: hostap: don't compile prism2_suspend() for hostap_pci without CONFIG_PM Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 6c158a56948..09004a632ae 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -3417,7 +3417,7 @@ static void prism2_free_local_data(struct net_device *dev) } -#ifndef PRISM2_PLX +#if (defined(PRISM2_PCI) && defined(CONFIG_PM)) || defined(PRISM2_PCCARD) static void prism2_suspend(struct net_device *dev) { struct hostap_interface *iface; @@ -3436,7 +3436,7 @@ static void prism2_suspend(struct net_device *dev) /* Disable hardware and firmware */ prism2_hw_shutdown(dev, 0); } -#endif /* PRISM2_PLX */ +#endif /* (PRISM2_PCI && CONFIG_PM) || PRISM2_PCCARD */ /* These might at some point be compiled separately and used as separate -- cgit v1.2.3 From 84263b0c94431e686552a322ae84678fddd22ebd Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 6 Jul 2008 17:09:48 +0200 Subject: rt2x00: Fix register comments Fix some register documentation in the register header files. This allows better parsing by userspace scripts which in turn helps debugging. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500pci.h | 4 ++-- drivers/net/wireless/rt2x00/rt2500usb.h | 40 ++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index cb648c30a5b..42f376929ea 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -751,7 +751,7 @@ #define LEDCSR_LED_DEFAULT FIELD32(0x00100000) /* - * AES control register. + * SECCSR3: AES control register. */ #define SECCSR3 0x00fc @@ -895,7 +895,7 @@ #define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000) /* - * SECCSR1_RT2509: WEP control register. + * SECCSR1: WEP control register. * KICK_ENCRYPT: Kick encryption engine, self-clear. * ONE_SHOT: 0: ring mode, 1: One shot only mode. * DESC_ADDRESS: Descriptor physical address of frame. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 3e21fdf2b00..4769ffeb4cc 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -209,7 +209,7 @@ #define MAC_CSR21_OFF_PERIOD FIELD16(0xff00) /* - * Collision window control register. + * MAC_CSR22: Collision window control register. */ #define MAC_CSR22 0x042c @@ -296,7 +296,7 @@ #define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000) /* - * TXRX_CSR5: OFDM TX BBP ID1. + * TXRX_CSR8: OFDM TX BBP ID1. */ #define TXRX_CSR8 0x0450 #define TXRX_CSR8_BBP_ID0 FIELD16(0x007f) @@ -370,7 +370,14 @@ */ /* - * SEC_CSR0-SEC_CSR7: Shared key 0, word 0-7 + * SEC_CSR0: Shared key 0, word 0 + * SEC_CSR1: Shared key 0, word 1 + * SEC_CSR2: Shared key 0, word 2 + * SEC_CSR3: Shared key 0, word 3 + * SEC_CSR4: Shared key 0, word 4 + * SEC_CSR5: Shared key 0, word 5 + * SEC_CSR6: Shared key 0, word 6 + * SEC_CSR7: Shared key 0, word 7 */ #define SEC_CSR0 0x0480 #define SEC_CSR1 0x0482 @@ -382,7 +389,14 @@ #define SEC_CSR7 0x048e /* - * SEC_CSR8-SEC_CSR15: Shared key 1, word 0-7 + * SEC_CSR8: Shared key 1, word 0 + * SEC_CSR9: Shared key 1, word 1 + * SEC_CSR10: Shared key 1, word 2 + * SEC_CSR11: Shared key 1, word 3 + * SEC_CSR12: Shared key 1, word 4 + * SEC_CSR13: Shared key 1, word 5 + * SEC_CSR14: Shared key 1, word 6 + * SEC_CSR15: Shared key 1, word 7 */ #define SEC_CSR8 0x0490 #define SEC_CSR9 0x0492 @@ -394,7 +408,14 @@ #define SEC_CSR15 0x049e /* - * SEC_CSR16-SEC_CSR23: Shared key 2, word 0-7 + * SEC_CSR16: Shared key 2, word 0 + * SEC_CSR17: Shared key 2, word 1 + * SEC_CSR18: Shared key 2, word 2 + * SEC_CSR19: Shared key 2, word 3 + * SEC_CSR20: Shared key 2, word 4 + * SEC_CSR21: Shared key 2, word 5 + * SEC_CSR22: Shared key 2, word 6 + * SEC_CSR23: Shared key 2, word 7 */ #define SEC_CSR16 0x04a0 #define SEC_CSR17 0x04a2 @@ -406,7 +427,14 @@ #define SEC_CSR23 0x04ae /* - * SEC_CSR24-SEC_CSR31: Shared key 3, word 0-7 + * SEC_CSR24: Shared key 3, word 0 + * SEC_CSR25: Shared key 3, word 1 + * SEC_CSR26: Shared key 3, word 2 + * SEC_CSR27: Shared key 3, word 3 + * SEC_CSR28: Shared key 3, word 4 + * SEC_CSR29: Shared key 3, word 5 + * SEC_CSR30: Shared key 3, word 6 + * SEC_CSR31: Shared key 3, word 7 */ #define SEC_CSR24 0x04b0 #define SEC_CSR25 0x04b2 -- cgit v1.2.3 From c44ac0b9855c62b5ec8af5935124cfbe6654a32d Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:27:54 +0100 Subject: rtl8187: updating rtl8187.h to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187.h | 113 +++++++++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index a0cfb666de0..3afb49f8866 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -44,17 +44,48 @@ struct rtl8187_rx_hdr { __le64 mac_time; } __attribute__((packed)); -struct rtl8187_tx_hdr { +struct rtl8187b_rx_hdr { __le32 flags; + __le64 mac_time; + u8 noise; + u8 signal; + u8 agc; + u8 reserved; + __le32 unused; +} __attribute__((packed)); + +/* {rtl8187,rtl8187b}_tx_info is in skb */ + +/* Tx flags are common between rtl8187 and rtl8187b */ #define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15) #define RTL8187_TX_FLAG_MORE_FRAG (1 << 17) #define RTL8187_TX_FLAG_CTS (1 << 18) #define RTL8187_TX_FLAG_RTS (1 << 23) + +struct rtl8187_tx_hdr { + __le32 flags; __le16 rts_duration; __le16 len; __le32 retry; } __attribute__((packed)); +struct rtl8187b_tx_hdr { + __le32 flags; + __le16 rts_duration; + __le16 len; + __le32 unused_1; + __le16 unused_2; + __le16 tx_duration; + __le32 unused_3; + __le32 retry; + __le32 unused_4[2]; +} __attribute__((packed)); + +enum { + DEVICE_RTL8187, + DEVICE_RTL8187B +}; + struct rtl8187_priv { /* common between rtl818x drivers */ struct rtl818x_csr *map; @@ -70,70 +101,120 @@ struct rtl8187_priv { u32 rx_conf; u16 txpwr_base; u8 asic_rev; + u8 is_rtl8187b; + enum { + RTL8187BvB, + RTL8187BvD, + RTL8187BvE + } hw_rev; struct sk_buff_head rx_queue; + u8 signal; + u8 quality; + u8 noise; }; void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); -static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 idx) { u8 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return val; } -static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +{ + return rtl818x_ioread8_idx(priv, addr, 0); +} + +static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, + __le16 *addr, u8 idx) { __le16 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return le16_to_cpu(val); } -static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +{ + return rtl818x_ioread16_idx(priv, addr, 0); +} + +static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, + __le32 *addr, u8 idx) { __le32 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return le32_to_cpu(val); } -static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, - u8 *addr, u8 val) +static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +{ + return rtl818x_ioread32_idx(priv, addr, 0); +} + +static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 val, u8 idx) { usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); +} + +static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) +{ + rtl818x_iowrite8_idx(priv, addr, val, 0); } -static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, - __le16 *addr, u16 val) +static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, + __le16 *addr, u16 val, u8 idx) { __le16 buf = cpu_to_le16(val); usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); + (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), + HZ / 2); } -static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, - __le32 *addr, u32 val) +static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, + u16 val) +{ + rtl818x_iowrite16_idx(priv, addr, val, 0); +} + +static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, + __le32 *addr, u32 val, u8 idx) { __le32 buf = cpu_to_le32(val); usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); + (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), + HZ / 2); +} + +static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, + u32 val) +{ + rtl818x_iowrite32_idx(priv, addr, val, 0); } #endif /* RTL8187_H */ -- cgit v1.2.3 From d1e11af51657d18222bef9cc15591f8c0f289186 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:30:02 +0100 Subject: rtl8187: updating rtl818x.h to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x.h | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 4f7d38f506e..85a6394e430 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -66,7 +66,10 @@ struct rtl818x_csr { #define RTL818X_TX_CONF_R8180_F (3 << 25) #define RTL818X_TX_CONF_R8185_ABC (4 << 25) #define RTL818X_TX_CONF_R8185_D (5 << 25) +#define RTL818X_TX_CONF_R8187vD_1 (5 << 25) +#define RTL818X_TX_CONF_R8187vD_2 (6 << 25) #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) +#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) #define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) #define RTL818X_TX_CONF_CW_MIN (1 << 31) @@ -106,8 +109,11 @@ struct rtl818x_csr { #define RTL818X_MSR_NO_LINK (0 << 2) #define RTL818X_MSR_ADHOC (1 << 2) #define RTL818X_MSR_INFRA (2 << 2) +#define RTL818X_MSR_MASTER (3 << 2) +#define RTL818X_MSR_ENEDCA (4 << 2) u8 CONFIG3; #define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) +#define RTL818X_CONFIG3_GNT_SELECT (1 << 7) u8 CONFIG4; #define RTL818X_CONFIG4_POWEROFF (1 << 6) #define RTL818X_CONFIG4_VCOOFF (1 << 7) @@ -133,7 +139,9 @@ struct rtl818x_csr { __le32 RF_TIMING; u8 GP_ENABLE; u8 GPIO; - u8 reserved_12[10]; + u8 reserved_12[2]; + __le32 HSSI_PARA; + u8 reserved_13[4]; u8 TX_AGC_CTL; #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) #define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) @@ -141,29 +149,39 @@ struct rtl818x_csr { u8 TX_GAIN_CCK; u8 TX_GAIN_OFDM; u8 TX_ANTENNA; - u8 reserved_13[16]; + u8 reserved_14[16]; u8 WPA_CONF; - u8 reserved_14[3]; + u8 reserved_15[3]; u8 SIFS; u8 DIFS; u8 SLOT; - u8 reserved_15[5]; + u8 reserved_16[5]; u8 CW_CONF; #define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) #define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) u8 CW_VAL; u8 RATE_FALLBACK; - u8 reserved_16[25]; +#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) + u8 ACM_CONTROL; + u8 reserved_17[24]; u8 CONFIG5; u8 TX_DMA_POLLING; - u8 reserved_17[2]; + u8 reserved_18[2]; __le16 CWR; u8 RETRY_CTR; - u8 reserved_18[5]; + u8 reserved_19[3]; + __le16 INT_MIG; +/* RTL818X_R8187B_*: magic numbers from ioregisters */ +#define RTL818X_R8187B_B 0 +#define RTL818X_R8187B_D 1 +#define RTL818X_R8187B_E 2 __le32 RDSAR; - u8 reserved_19[12]; - __le16 FEMR; + __le16 TID_AC_MAP; u8 reserved_20[4]; + u8 ANAPARAM3; + u8 reserved_21[5]; + __le16 FEMR; + u8 reserved_22[4]; __le16 TALLY_CNT; u8 TALLY_SEL; } __attribute__((packed)); -- cgit v1.2.3 From e7d414ff21a7e0b00295e838c004ff1de5fba6ce Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:31:57 +0100 Subject: rtl8187: updating rtl8187_rtl8225.c to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_rtl8225.c | 229 +++++++++++++++++++++++++++++++-- 1 file changed, 215 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index 9146387b4c5..1e059de9711 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -305,9 +305,11 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) /* anaparam2 on */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl8225_write_phy_ofdm(dev, 2, 0x42); @@ -471,12 +473,42 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); } +static const u8 rtl8225z2_agc[] = { + 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, + 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, + 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, + 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, + 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, + 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 +}; +static const u8 rtl8225z2_ofdm[] = { + 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, + 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, + 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, + 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, + 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, + 0x6d, 0x3c, 0xfb, 0x07 +}; + static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 }; static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }; static const u8 rtl8225z2_tx_power_ofdm[] = { @@ -526,9 +558,11 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) /* anaparam2 on */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl8225_write_phy_ofdm(dev, 2, 0x42); @@ -542,6 +576,85 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) msleep(1); } +static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; + + if (cck_power > 15) + cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; + else + cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; + cck_power += priv->txpwr_base & 0xF; + cck_power = min(cck_power, (u8)35); + + if (ofdm_power > 15) + ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; + else + ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; + ofdm_power += (priv->txpwr_base >> 4) & 0xF; + ofdm_power = min(ofdm_power, (u8)35); + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else + tmp = rtl8225z2_tx_power_cck; + + if (priv->hw_rev == RTL8187BvB) { + if (cck_power <= 6) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else + tmp += 16; + } else { + if (cck_power <= 5) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else if (cck_power <= 17) + tmp += 16; + else + tmp += 24; + } + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225z2_tx_gain_cck_ofdm[cck_power]); + msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); + if (priv->hw_rev == RTL8187BvB) { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x60); + rtl8225_write_phy_ofdm(dev, 0x89, 0x60); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } + } else { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } else if (ofdm_power <= 17) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x54); + rtl8225_write_phy_ofdm(dev, 0x89, 0x54); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x50); + rtl8225_write_phy_ofdm(dev, 0x89, 0x50); + } + } + msleep(1); +} + static const u16 rtl8225z2_rxgain[] = { 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, @@ -715,6 +828,81 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); } +static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x0B7); msleep(1); + rtl8225_write(dev, 0x1, 0xEE0); msleep(1); + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x3, 0x441); msleep(1); + rtl8225_write(dev, 0x4, 0x8C3); msleep(1); + rtl8225_write(dev, 0x5, 0xC72); msleep(1); + rtl8225_write(dev, 0x6, 0x0E6); msleep(1); + rtl8225_write(dev, 0x7, 0x82A); msleep(1); + rtl8225_write(dev, 0x8, 0x03F); msleep(1); + rtl8225_write(dev, 0x9, 0x335); msleep(1); + rtl8225_write(dev, 0xa, 0x9D4); msleep(1); + rtl8225_write(dev, 0xb, 0x7BB); msleep(1); + rtl8225_write(dev, 0xc, 0x850); msleep(1); + rtl8225_write(dev, 0xd, 0xCDF); msleep(1); + rtl8225_write(dev, 0xe, 0x02B); msleep(1); + rtl8225_write(dev, 0xf, 0x114); msleep(1); + + rtl8225_write(dev, 0x0, 0x1B7); msleep(1); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); msleep(1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1); + } + + rtl8225_write(dev, 0x3, 0x080); msleep(1); + rtl8225_write(dev, 0x5, 0x004); msleep(1); + rtl8225_write(dev, 0x0, 0x0B7); msleep(1); + msleep(3000); + + rtl8225_write(dev, 0x2, 0xC4D); msleep(1); + msleep(2000); + + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x0, 0x2BF); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + + rtl8225_write_phy_ofdm(dev, 0x80, 0x12); + for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); + rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); + rtl8225_write_phy_ofdm(dev, 0xE, 0); + } + rtl8225_write_phy_ofdm(dev, 0x80, 0x10); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) + rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); + + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + rtl818x_iowrite8(priv, &priv->map->SLOT, 9); + rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28); + rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B); + rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B); + rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); + + rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1); +} + static void rtl8225_rf_stop(struct ieee80211_hw *dev) { u8 reg; @@ -739,8 +927,10 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, if (priv->rf->init == rtl8225_rf_init) rtl8225_rf_set_tx_power(dev, chan); - else + else if (priv->rf->init == rtl8225z2_rf_init) rtl8225z2_rf_set_tx_power(dev, chan); + else + rtl8225z2_b_rf_set_tx_power(dev, chan); rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); @@ -760,19 +950,30 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = { .set_chan = rtl8225_rf_set_channel }; +static const struct rtl818x_rf_ops rtl8225z2_b_ops = { + .name = "rtl8225z2", + .init = rtl8225z2_b_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel +}; + const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) { u16 reg8, reg9; + struct rtl8187_priv *priv = dev->priv; - rtl8225_write(dev, 0, 0x1B7); + if (!priv->is_rtl8187b) { + rtl8225_write(dev, 0, 0x1B7); - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); + reg8 = rtl8225_read(dev, 8); + reg9 = rtl8225_read(dev, 9); - rtl8225_write(dev, 0, 0x0B7); + rtl8225_write(dev, 0, 0x0B7); - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; + if (reg8 != 0x588 || reg9 != 0x700) + return &rtl8225_ops; - return &rtl8225z2_ops; + return &rtl8225z2_ops; + } else + return &rtl8225z2_b_ops; } -- cgit v1.2.3 From f8a08c34265b59710a8fc049911f487477c19fab Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:33:34 +0100 Subject: rtl8187: change rtl8187_dev.c to support RTL8187B (part 1) Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 263 +++++++++++++++++++++++++++++++++---- 1 file changed, 234 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index bec96d762c6..b17f237c9e2 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -27,19 +27,21 @@ MODULE_AUTHOR("Michael Wu "); MODULE_AUTHOR("Andrea Merello "); -MODULE_DESCRIPTION("RTL8187 USB wireless driver"); +MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); static struct usb_device_id rtl8187_table[] __devinitdata = { /* Realtek */ - {USB_DEVICE(0x0bda, 0x8187)}, + {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, /* Netgear */ - {USB_DEVICE(0x0846, 0x6100)}, - {USB_DEVICE(0x0846, 0x6a00)}, + {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, /* HP */ - {USB_DEVICE(0x03f0, 0xca02)}, + {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ - {USB_DEVICE(0x0df6, 0x000d)}, + {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {} }; @@ -318,29 +320,12 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) return 0; } -static int rtl8187_init_hw(struct ieee80211_hw *dev) +static int rtl8187_cmd_reset(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; u8 reg; int i; - /* reset */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - msleep(200); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); - msleep(200); - reg = rtl818x_ioread8(priv, &priv->map->CMD); reg &= (1 << 1); reg |= RTL818X_CMD_RESET; @@ -376,12 +361,48 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) return -ETIMEDOUT; } + return 0; +} + +static int rtl8187_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u8 reg; + int res; + + /* reset */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | + RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & + ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + msleep(200); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); + msleep(200); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); /* setup card */ @@ -426,9 +447,11 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); msleep(100); @@ -445,16 +468,198 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) return 0; } +static const u8 rtl8187b_reg_table[][3] = { + {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, + {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, + {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, + {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, + + {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, + {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, + {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, + {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, + {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, + {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, + + {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, + {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, + {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, + {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, + {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, + {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, + {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, + {0x73, 0x9A, 2}, + + {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, + {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, + {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, + {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, + {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, + + {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, + {0x8E, 0x08, 0}, {0x8F, 0x00, 0} +}; + +static int rtl8187b_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int res, i; + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658); + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0); + + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); + reg = rtl818x_ioread8(priv, (u8 *)0xFF62); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + + rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | + RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); + reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK); + reg |= RTL818X_RATE_FALLBACK_ENABLE; + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg); + + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); + rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { + rtl818x_iowrite8_idx(priv, + (u8 *)(uintptr_t) + (rtl8187b_reg_table[i][0] | 0xFF00), + rtl8187b_reg_table[i][1], + rtl8187b_reg_table[i][2]); + } + + rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); + rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); + + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + msleep(1100); + + priv->rf->init(dev); + + reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + + rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + + reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); + rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); + rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); + + rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); + + return 0; +} + static int rtl8187_start(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; u32 reg; int ret; - ret = rtl8187_init_hw(dev); + ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : + rtl8187b_init_hw(dev); if (ret) return ret; + if (priv->is_rtl8187b) { + reg = RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_DATA | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_NICMAC | + RTL818X_RX_CONF_BSSID | + (7 << 13 /* RX FIFO threshold NONE */) | + (7 << 10 /* MAX RX DMA */) | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_MULTICAST; + priv->rx_conf = reg; + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + RTL818X_TX_CONF_HW_SEQNUM | + RTL818X_TX_CONF_DISREQQSIZE | + (7 << 8 /* short retry limit */) | + (7 << 0 /* long retry limit */) | + (7 << 21 /* MAX TX DMA */)); + rtl8187_init_urbs(dev); + return 0; + } + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); -- cgit v1.2.3 From 6f7853f3cbe457067e9fe05461f56c7ea4ac488c Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:36:04 +0100 Subject: rtl8187: change rtl8187_dev.c to support RTL8187B (part 2) Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 208 ++++++++++++++++++++++++++++++------- 1 file changed, 168 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index b17f237c9e2..3bc4a1c3925 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -155,9 +155,11 @@ static void rtl8187_tx_cb(struct urb *urb) struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = info->driver_data[0]; + struct rtl8187_priv *priv = hw->priv; usb_free_urb(info->driver_data[1]); - skb_pull(skb, sizeof(struct rtl8187_tx_hdr)); + skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : + sizeof(struct rtl8187_tx_hdr)); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); @@ -167,7 +169,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct rtl8187_priv *priv = dev->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl8187_tx_hdr *hdr; + unsigned int ep; + void *buf; struct urb *urb; __le16 rts_dur = 0; u32 flags; @@ -195,16 +198,47 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } - hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->len = 0; - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + if (!priv->is_rtl8187b) { + struct rtl8187_tx_hdr *hdr = + (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->len = 0; + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + buf = hdr; + + ep = 2; + } else { + /* fc needs to be calculated before skb_push() */ + unsigned int epmap[4] = { 6, 7, 5, 4 }; + struct ieee80211_hdr *tx_hdr = + (struct ieee80211_hdr *)(skb->data); + u16 fc = le16_to_cpu(tx_hdr->frame_control); + + struct rtl8187b_tx_hdr *hdr = + (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); + struct ieee80211_rate *txrate = + ieee80211_get_tx_rate(dev, info); + memset(hdr, 0, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->tx_duration = + ieee80211_generic_frame_duration(dev, priv->vif, + skb->len, txrate); + buf = hdr; + + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + ep = 12; + else + ep = epmap[skb_get_queue_mapping(skb)]; + } info->driver_data[0] = dev; info->driver_data[1] = urb; - usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), - hdr, skb->len, rtl8187_tx_cb, skb); + + usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), + buf, skb->len, rtl8187_tx_cb, skb); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc < 0) { usb_free_urb(urb); @@ -220,7 +254,6 @@ static void rtl8187_rx_cb(struct urb *urb) struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; struct ieee80211_hw *dev = info->dev; struct rtl8187_priv *priv = dev->priv; - struct rtl8187_rx_hdr *hdr; struct ieee80211_rx_status rx_status = { 0 }; int rate, signal; u32 flags; @@ -241,11 +274,33 @@ static void rtl8187_rx_cb(struct urb *urb) } skb_put(skb, urb->actual_length); - hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); - flags = le32_to_cpu(hdr->flags); - skb_trim(skb, flags & 0x0FFF); + if (!priv->is_rtl8187b) { + struct rtl8187_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + flags = le32_to_cpu(hdr->flags); + signal = hdr->signal & 0x7f; + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.signal = signal; + rx_status.noise = hdr->noise; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + priv->signal = signal; + priv->quality = signal; + priv->noise = hdr->noise; + } else { + struct rtl8187b_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + flags = le32_to_cpu(hdr->flags); + signal = hdr->agc >> 1; + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.signal = 64 - min(hdr->noise, (u8)64); + rx_status.noise = hdr->noise; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + priv->signal = hdr->signal; + priv->quality = hdr->agc >> 1; + priv->noise = hdr->noise; + } - signal = hdr->agc >> 1; + skb_trim(skb, flags & 0x0FFF); rate = (flags >> 20) & 0xF; if (rate > 3) { /* OFDM rate */ if (signal > 90) @@ -261,13 +316,11 @@ static void rtl8187_rx_cb(struct urb *urb) signal = 95 - signal; } - rx_status.antenna = (hdr->signal >> 7) & 1; - rx_status.qual = 64 - min(hdr->noise, (u8)64); + rx_status.qual = priv->quality; rx_status.signal = signal; rx_status.rate_idx = rate; rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; - rx_status.mactime = le64_to_cpu(hdr->mac_time); rx_status.flag |= RX_FLAG_TSFT; if (flags & (1 << 13)) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; @@ -307,7 +360,8 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) break; } usb_fill_bulk_urb(entry, priv->udev, - usb_rcvbulkpipe(priv->udev, 1), + usb_rcvbulkpipe(priv->udev, + priv->is_rtl8187b ? 3 : 1), skb_tail_pointer(skb), RTL8187_MAX_RX, rtl8187_rx_cb, skb); info = (struct rtl8187_rx_info *)skb->cb; @@ -786,18 +840,20 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) msleep(10); rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - - if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); - } else { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); + if (!priv->is_rtl8187b) { + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + + if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); + } else { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); + } } rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); @@ -813,14 +869,20 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, { struct rtl8187_priv *priv = dev->priv; int i; + u8 reg; for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - if (is_valid_ether_addr(conf->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); + if (is_valid_ether_addr(conf->bssid)) { + reg = RTL818X_MSR_INFRA; + if (priv->is_rtl8187b) + reg |= RTL818X_MSR_ENEDCA; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } else { + reg = RTL818X_MSR_NO_LINK; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } return 0; } @@ -907,6 +969,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, struct rtl8187_priv *priv; struct eeprom_93cx6 eeprom; struct ieee80211_channel *channel; + const char *chip_name; u16 txpwr, reg; int err, i; DECLARE_MAC_BUF(mac); @@ -918,6 +981,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } priv = dev->priv; + priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) || + !memcmp(udev->product, "RTL8187B", 8); SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -946,8 +1011,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; - dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); - dev->queues = 1; + dev->extra_tx_headroom = (!priv->is_rtl8187b) ? + sizeof(struct rtl8187_tx_hdr) : + sizeof(struct rtl8187b_tx_hdr); + if (!priv->is_rtl8187b) + dev->queues = 1; + else + dev->queues = 4; dev->max_signal = 65; eeprom.data = dev; @@ -982,10 +1052,24 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, + if (!priv->is_rtl8187b) { + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, + RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + } else { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, &txpwr); (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } @@ -1001,6 +1085,50 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + if (!priv->is_rtl8187b) { + u32 reg32; + reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); + reg32 &= RTL818X_TX_CONF_HWVER_MASK; + switch (reg32) { + case RTL818X_TX_CONF_R8187vD_1: + case RTL818X_TX_CONF_R8187vD_2: + chip_name = "RTL8187vD"; + break; + default: + chip_name = "RTL8187vB (default)"; + } + } else { + printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " + "is EXPERIMENTAL, and could damage your\n" + " hardware, use at your own risk\n"); + /* + * Force USB request to write radio registers for 8187B, Realtek + * only uses it in their sources + */ + /*if (priv->asic_rev == 0) { + printk(KERN_WARNING "rtl8187: Forcing use of USB " + "requests to write to radio registers\n"); + priv->asic_rev = 1; + }*/ + switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { + case RTL818X_R8187B_B: + chip_name = "RTL8187BvB"; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_R8187B_D: + chip_name = "RTL8187BvD"; + priv->hw_rev = RTL8187BvD; + break; + case RTL818X_R8187B_E: + chip_name = "RTL8187BvE"; + priv->hw_rev = RTL8187BvE; + break; + default: + chip_name = "RTL8187BvB (default)"; + priv->hw_rev = RTL8187BvB; + } + } + priv->rf = rtl8187_detect_rf(dev); err = ieee80211_register_hw(dev); @@ -1009,9 +1137,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, goto err_free_dev; } - printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", + printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), - priv->asic_rev, priv->rf->name); + chip_name, priv->asic_rev, priv->rf->name); return 0; -- cgit v1.2.3 From 5c036b217a1fe3ae0616e9c43c6bcd13b3c134b6 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:38:02 +0100 Subject: rtl8187: updating Kconfig to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 865f2980c27..d5b006f5b86 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -611,14 +611,20 @@ config RTL8180 Thanks to Realtek for their support! config RTL8187 - tristate "Realtek 8187 USB support" + tristate "Realtek 8187 and 8187B USB support" depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL select EEPROM_93CX6 ---help--- - This is a driver for RTL8187 based cards. - These are USB based chips found in cards such as: + This is a driver for RTL8187 and RTL8187B based cards. + These are USB based chips found in devices such as: Netgear WG111v2 + Level 1 WNC-0301USB + Micronet SP907GK V5 + Encore ENUWI-G2 + Trendnet TEW-424UB + ASUS P5B Deluxe + Toshiba Satellite Pro series of laptops Thanks to Realtek for their support! -- cgit v1.2.3 From 0e25b4ef220f6ef4eed120543182385b13005db9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 8 Jul 2008 09:43:43 -0500 Subject: rtl8187: Change detection of RTL8187B with USB ID of 8187 Some early versions of RTL8187B devices have a USB ID of 0x8187 rather than the 0x8189 of later models. In addition, it appears that these early units also must be programmed with lower power. Previous patches used the Product ID string to detect this situation, but did not address the low power question. This patch uses the hardware version and sets the power accordingly. Signed-off-by: Hin-Tak Leung Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 79 ++++++++++++++++++++++---------------- drivers/net/wireless/rtl818x.h | 4 +- 2 files changed, 47 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 3bc4a1c3925..33527e58256 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -981,8 +981,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } priv = dev->priv; - priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) || - !memcmp(udev->product, "RTL8187B", 8); + priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -1011,13 +1010,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; - dev->extra_tx_headroom = (!priv->is_rtl8187b) ? - sizeof(struct rtl8187_tx_hdr) : - sizeof(struct rtl8187b_tx_hdr); - if (!priv->is_rtl8187b) - dev->queues = 1; - else - dev->queues = 4; dev->max_signal = 65; eeprom.data = dev; @@ -1052,26 +1044,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } - if (!priv->is_rtl8187b) { - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, - RTL8187_EEPROM_TXPWR_CHAN_6 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - } else { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, &priv->txpwr_base); @@ -1090,17 +1062,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg32 &= RTL818X_TX_CONF_HWVER_MASK; switch (reg32) { - case RTL818X_TX_CONF_R8187vD_1: - case RTL818X_TX_CONF_R8187vD_2: + case RTL818X_TX_CONF_R8187vD_B: + /* Some RTL8187B devices have a USB ID of 0x8187 + * detect them here */ + chip_name = "RTL8187BvB(early)"; + priv->is_rtl8187b = 1; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_TX_CONF_R8187vD: chip_name = "RTL8187vD"; break; default: chip_name = "RTL8187vB (default)"; } } else { - printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " - "is EXPERIMENTAL, and could damage your\n" - " hardware, use at your own risk\n"); /* * Force USB request to write radio registers for 8187B, Realtek * only uses it in their sources @@ -1129,7 +1104,43 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } } + if (!priv->is_rtl8187b) { + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, + RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + } else { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + + if (priv->is_rtl8187b) + printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " + "is EXPERIMENTAL, and could damage your\n" + " hardware, use at your own risk\n"); + if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) + printk(KERN_INFO "rtl8187: inconsistency between id with OEM" + " info!\n"); + priv->rf = rtl8187_detect_rf(dev); + dev->extra_tx_headroom = (!priv->is_rtl8187b) ? + sizeof(struct rtl8187_tx_hdr) : + sizeof(struct rtl8187b_tx_hdr); + if (!priv->is_rtl8187b) + dev->queues = 1; + else + dev->queues = 4; err = ieee80211_register_hw(dev); if (err) { diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 85a6394e430..00900fe16fc 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -66,8 +66,8 @@ struct rtl818x_csr { #define RTL818X_TX_CONF_R8180_F (3 << 25) #define RTL818X_TX_CONF_R8185_ABC (4 << 25) #define RTL818X_TX_CONF_R8185_D (5 << 25) -#define RTL818X_TX_CONF_R8187vD_1 (5 << 25) -#define RTL818X_TX_CONF_R8187vD_2 (6 << 25) +#define RTL818X_TX_CONF_R8187vD (5 << 25) +#define RTL818X_TX_CONF_R8187vD_B (6 << 25) #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) #define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) -- cgit v1.2.3