Merge tag 'wireless-drivers-next-for-davem-2016-11-25' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== wireless-drivers-next patches for 4.10 Major changes: iwlwifi * finalize and enable dynamic queue allocation * use dev_coredumpmsg() to prevent locking the driver * small fix to pass the AID to the FW * use FW PS decisions with multi-queue ath9k * add device tree bindings * switch to use mac80211 intermediate software queues to reduce latency and fix bufferbloat wl18xx * allow scanning in AP mode ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "hif.h"
|
||||
#include "core.h"
|
||||
@@ -3179,7 +3180,8 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif,
|
||||
ath10k_mac_vif_tx_unlock(arvif, pause_id);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"received unknown tx pause action %d on vdev %i, ignoring\n",
|
||||
action, arvif->vdev_id);
|
||||
break;
|
||||
}
|
||||
@@ -3255,8 +3257,6 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
|
||||
if (ar->htt.target_version_major < 3 &&
|
||||
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
ar->running_fw->fw_file.fw_features) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return ATH10K_HW_TXRX_MGMT;
|
||||
|
||||
@@ -4929,7 +4929,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_add(&arvif->list, &ar->arvifs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* It makes no sense to have firmware do keepalives. mac80211 already
|
||||
* takes care of this with idle connection polling.
|
||||
@@ -5080,7 +5082,9 @@ err_peer_delete:
|
||||
err_vdev_delete:
|
||||
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
ar->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_del(&arvif->list);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
err:
|
||||
if (arvif->beacon_buf) {
|
||||
@@ -5126,7 +5130,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
ar->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_del(&arvif->list);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
|
||||
@@ -5410,6 +5416,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
/* This function should never be called if setting the coverage class
|
||||
* is not supported on this hardware.
|
||||
*/
|
||||
if (!ar->hw_params.hw_ops->set_coverage_class) {
|
||||
WARN_ON_ONCE(1);
|
||||
return;
|
||||
}
|
||||
ar->hw_params.hw_ops->set_coverage_class(ar, value);
|
||||
}
|
||||
|
||||
static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *hw_req)
|
||||
@@ -7435,6 +7455,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||
.remove_interface = ath10k_remove_interface,
|
||||
.configure_filter = ath10k_configure_filter,
|
||||
.bss_info_changed = ath10k_bss_info_changed,
|
||||
.set_coverage_class = ath10k_mac_op_set_coverage_class,
|
||||
.hw_scan = ath10k_hw_scan,
|
||||
.cancel_hw_scan = ath10k_cancel_hw_scan,
|
||||
.set_key = ath10k_set_key,
|
||||
@@ -7789,6 +7810,109 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id)
|
||||
return arvif_iter.arvif;
|
||||
}
|
||||
|
||||
#define WRD_METHOD "WRDD"
|
||||
#define WRDD_WIFI (0x07)
|
||||
|
||||
static u32 ath10k_mac_wrdd_get_mcc(struct ath10k *ar, union acpi_object *wrdd)
|
||||
{
|
||||
union acpi_object *mcc_pkg;
|
||||
union acpi_object *domain_type;
|
||||
union acpi_object *mcc_value;
|
||||
u32 i;
|
||||
|
||||
if (wrdd->type != ACPI_TYPE_PACKAGE ||
|
||||
wrdd->package.count < 2 ||
|
||||
wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
wrdd->package.elements[0].integer.value != 0) {
|
||||
ath10k_warn(ar, "ignoring malformed/unsupported wrdd structure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < wrdd->package.count; ++i) {
|
||||
mcc_pkg = &wrdd->package.elements[i];
|
||||
|
||||
if (mcc_pkg->type != ACPI_TYPE_PACKAGE)
|
||||
continue;
|
||||
if (mcc_pkg->package.count < 2)
|
||||
continue;
|
||||
if (mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
domain_type = &mcc_pkg->package.elements[0];
|
||||
if (domain_type->integer.value != WRDD_WIFI)
|
||||
continue;
|
||||
|
||||
mcc_value = &mcc_pkg->package.elements[1];
|
||||
return mcc_value->integer.value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_mac_get_wrdd_regulatory(struct ath10k *ar, u16 *rd)
|
||||
{
|
||||
struct pci_dev __maybe_unused *pdev = to_pci_dev(ar->dev);
|
||||
acpi_handle root_handle;
|
||||
acpi_handle handle;
|
||||
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_status status;
|
||||
u32 alpha2_code;
|
||||
char alpha2[3];
|
||||
|
||||
root_handle = ACPI_HANDLE(&pdev->dev);
|
||||
if (!root_handle)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"failed to get wrd method %d\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"failed to call wrdc %d\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
alpha2_code = ath10k_mac_wrdd_get_mcc(ar, wrdd.pointer);
|
||||
kfree(wrdd.pointer);
|
||||
if (!alpha2_code)
|
||||
return -EIO;
|
||||
|
||||
alpha2[0] = (alpha2_code >> 8) & 0xff;
|
||||
alpha2[1] = (alpha2_code >> 0) & 0xff;
|
||||
alpha2[2] = '\0';
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"regulatory hint from WRDD (alpha2-code): %s\n", alpha2);
|
||||
|
||||
*rd = ath_regd_find_country_by_name(alpha2);
|
||||
if (*rd == 0xffff)
|
||||
return -EIO;
|
||||
|
||||
*rd |= COUNTRY_ERD_FLAG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_mac_init_rd(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
u16 rd;
|
||||
|
||||
ret = ath10k_mac_get_wrdd_regulatory(ar, &rd);
|
||||
if (ret) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"fallback to eeprom programmed regulatory settings\n");
|
||||
rd = ar->hw_eeprom_rd;
|
||||
}
|
||||
|
||||
ar->ath_common.regulatory.current_rd = rd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_mac_register(struct ath10k *ar)
|
||||
{
|
||||
static const u32 cipher_suites[] = {
|
||||
@@ -8013,6 +8137,16 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
ar->ops->wake_tx_queue = NULL;
|
||||
|
||||
ret = ath10k_mac_init_rd(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to derive regdom: %d\n", ret);
|
||||
goto err_dfs_detector_exit;
|
||||
}
|
||||
|
||||
/* Disable set_coverage_class for chipsets that do not support it. */
|
||||
if (!ar->hw_params.hw_ops->set_coverage_class)
|
||||
ar->ops->set_coverage_class = NULL;
|
||||
|
||||
ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
|
||||
ath10k_reg_notifier);
|
||||
if (ret) {
|
||||
|
||||
Reference in New Issue
Block a user