forked from Minki/linux
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.14. Major changes: wil6210 * support FW RSSI reporting (by mistake this was accidentally mentioned already in the previous pull request, but now it's really included) * make debugfs optional, adds new Kconfig option CONFIG_WIL6210_DEBUGFS
This commit is contained in:
commit
eb464d4a8d
@ -519,7 +519,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
|
||||
dir = ".";
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s", dir, file);
|
||||
ret = request_firmware_direct(&fw, filename, ar->dev);
|
||||
ret = request_firmware(&fw, filename, ar->dev);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
|
||||
filename, ret);
|
||||
|
||||
@ -2057,6 +2057,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
goto err_wmi_detach;
|
||||
}
|
||||
|
||||
/* If firmware indicates Full Rx Reorder support it must be used in a
|
||||
* slightly different manner. Let HTT code know.
|
||||
*/
|
||||
ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
|
||||
ar->wmi.svc_map));
|
||||
|
||||
status = ath10k_htt_rx_alloc(&ar->htt);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
|
||||
@ -2177,12 +2183,6 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
}
|
||||
}
|
||||
|
||||
/* If firmware indicates Full Rx Reorder support it must be used in a
|
||||
* slightly different manner. Let HTT code know.
|
||||
*/
|
||||
ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
|
||||
ar->wmi.svc_map));
|
||||
|
||||
status = ath10k_htt_rx_ring_refill(ar);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);
|
||||
|
@ -462,7 +462,7 @@ struct ath10k_ce_crash_hdr {
|
||||
struct ath10k_fw_crash_data {
|
||||
bool crashed_since_read;
|
||||
|
||||
uuid_le uuid;
|
||||
guid_t guid;
|
||||
struct timespec timestamp;
|
||||
__le32 registers[REG_DUMP_COUNT_QCA988X];
|
||||
struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX];
|
||||
|
@ -70,7 +70,7 @@ struct ath10k_dump_file_data {
|
||||
|
||||
/* some info we can get from ath10k struct that might help */
|
||||
|
||||
u8 uuid[16];
|
||||
guid_t guid;
|
||||
|
||||
__le32 chip_id;
|
||||
|
||||
@ -719,7 +719,7 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
crash_data->crashed_since_read = true;
|
||||
uuid_le_gen(&crash_data->uuid);
|
||||
guid_gen(&crash_data->guid);
|
||||
getnstimeofday(&crash_data->timestamp);
|
||||
|
||||
return crash_data;
|
||||
@ -766,7 +766,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
|
||||
|
||||
dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
|
||||
|
||||
memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
|
||||
guid_copy(&dump_data->guid, &crash_data->guid);
|
||||
dump_data->chip_id = cpu_to_le32(ar->chip_id);
|
||||
dump_data->bus_type = cpu_to_le32(0);
|
||||
dump_data->target_version = cpu_to_le32(ar->target_version);
|
||||
|
@ -1524,7 +1524,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
|
||||
*/
|
||||
|
||||
if (!rx_status->freq) {
|
||||
ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1745,7 +1745,8 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
struct sk_buff_head *amsdu)
|
||||
struct sk_buff_head *amsdu,
|
||||
int budget_left)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct htt_rx_desc *rxd;
|
||||
@ -1756,8 +1757,9 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
if (WARN_ON(!skb_queue_empty(amsdu)))
|
||||
return -EINVAL;
|
||||
|
||||
while ((msdu = __skb_dequeue(list))) {
|
||||
while ((msdu = __skb_dequeue(list)) && budget_left) {
|
||||
__skb_queue_tail(amsdu, msdu);
|
||||
budget_left--;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (rxd->msdu_end.common.info0 &
|
||||
@ -1848,7 +1850,8 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
|
||||
return num_msdu;
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
|
||||
int budget_left)
|
||||
{
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct htt_resp *resp = (void *)skb->data;
|
||||
@ -1905,9 +1908,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
if (offload)
|
||||
num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
while (!skb_queue_empty(&list) && budget_left) {
|
||||
__skb_queue_head_init(&amsdu);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu, budget_left);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Note: The in-order indication may report interleaved
|
||||
@ -1917,6 +1920,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
* should still give an idea about rx rate to the user.
|
||||
*/
|
||||
num_msdus += skb_queue_len(&amsdu);
|
||||
budget_left -= skb_queue_len(&amsdu);
|
||||
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
|
||||
ath10k_htt_rx_h_filter(ar, &amsdu, status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
|
||||
@ -2559,7 +2563,8 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb,
|
||||
(budget - quota));
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
if (num_rx_msdus < 0) {
|
||||
resched_napi = true;
|
||||
|
@ -7644,6 +7644,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ath10k_wow_op_suspend,
|
||||
.resume = ath10k_wow_op_resume,
|
||||
.set_wakeup = ath10k_wow_op_set_wakeup,
|
||||
#endif
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
.sta_add_debugfs = ath10k_sta_add_debugfs,
|
||||
|
@ -1463,7 +1463,7 @@ static void ath10k_pci_dump_registers(struct ath10k *ar,
|
||||
static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_crash_data *crash_data;
|
||||
char uuid[50];
|
||||
char guid[UUID_STRING_LEN + 1];
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
@ -1472,11 +1472,11 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
|
||||
crash_data = ath10k_debug_get_new_fw_crash_data(ar);
|
||||
|
||||
if (crash_data)
|
||||
scnprintf(uuid, sizeof(uuid), "%pUl", &crash_data->uuid);
|
||||
scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
|
||||
else
|
||||
scnprintf(uuid, sizeof(uuid), "n/a");
|
||||
scnprintf(guid, sizeof(guid), "n/a");
|
||||
|
||||
ath10k_err(ar, "firmware crashed! (uuid %s)\n", uuid);
|
||||
ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
|
||||
ath10k_print_driver_info(ar);
|
||||
ath10k_pci_dump_registers(ar, crash_data);
|
||||
ath10k_ce_dump_registers(ar, crash_data);
|
||||
@ -3396,11 +3396,53 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ath10k_pci_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct ath10k *ar = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
ret = ath10k_hif_suspend(ar);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to suspend hif: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_pci_pm_resume(struct device *dev)
|
||||
{
|
||||
struct ath10k *ar = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
ret = ath10k_hif_resume(ar);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to resume hif: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ath10k_pci_pm_ops,
|
||||
ath10k_pci_pm_suspend,
|
||||
ath10k_pci_pm_resume);
|
||||
#endif
|
||||
|
||||
static struct pci_driver ath10k_pci_driver = {
|
||||
.name = "ath10k_pci",
|
||||
.id_table = ath10k_pci_id_table,
|
||||
.probe = ath10k_pci_probe,
|
||||
.remove = ath10k_pci_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.driver.pm = &ath10k_pci_pm_ops,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init ath10k_pci_init(void)
|
||||
|
@ -1344,8 +1344,6 @@ static void ath10k_sdio_irq_handler(struct sdio_func *func)
|
||||
|
||||
sdio_claim_host(ar_sdio->func);
|
||||
|
||||
wake_up(&ar_sdio->irq_wq);
|
||||
|
||||
if (ret && ret != -ECANCELED)
|
||||
ath10k_warn(ar, "failed to process pending SDIO interrupts: %d\n",
|
||||
ret);
|
||||
@ -2000,8 +1998,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
|
||||
goto err_free_bmi_buf;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&ar_sdio->irq_wq);
|
||||
|
||||
for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
|
||||
ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
|
||||
|
||||
|
@ -210,8 +210,6 @@ struct ath10k_sdio {
|
||||
/* temporary buffer for BMI requests */
|
||||
u8 *bmi_buf;
|
||||
|
||||
wait_queue_head_t irq_wq;
|
||||
|
||||
bool is_disabled;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
|
@ -277,6 +277,18 @@ exit:
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
|
||||
void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
device_set_wakeup_enable(ar->dev, enabled);
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
int ath10k_wow_op_resume(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
@ -336,5 +348,7 @@ int ath10k_wow_init(struct ath10k *ar)
|
||||
ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
|
||||
ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
|
||||
|
||||
device_set_wakeup_capable(ar->dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ int ath10k_wow_init(struct ath10k *ar);
|
||||
int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
struct cfg80211_wowlan *wowlan);
|
||||
int ath10k_wow_op_resume(struct ieee80211_hw *hw);
|
||||
void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -1201,7 +1201,7 @@ static int ath6kl_usb_pm_resume(struct usb_interface *interface)
|
||||
#endif
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id ath6kl_usb_ids[] = {
|
||||
static const struct usb_device_id ath6kl_usb_ids[] = {
|
||||
{USB_DEVICE(0x0cf3, 0x9375)},
|
||||
{USB_DEVICE(0x0cf3, 0x9374)},
|
||||
{ /* Terminating entry */ },
|
||||
|
@ -20,7 +20,7 @@
|
||||
MODULE_FIRMWARE(HTC_7010_MODULE_FW);
|
||||
MODULE_FIRMWARE(HTC_9271_MODULE_FW);
|
||||
|
||||
static struct usb_device_id ath9k_hif_usb_ids[] = {
|
||||
static const struct usb_device_id ath9k_hif_usb_ids[] = {
|
||||
{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
|
||||
{ USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
|
||||
{ USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
|
||||
|
@ -71,7 +71,7 @@ static void ath9k_htc_op_ps_restore(struct ath_common *common)
|
||||
ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv);
|
||||
}
|
||||
|
||||
static struct ath_ps_ops ath9k_htc_ps_ops = {
|
||||
static const struct ath_ps_ops ath9k_htc_ps_ops = {
|
||||
.wakeup = ath9k_htc_op_ps_wakeup,
|
||||
.restore = ath9k_htc_op_ps_restore,
|
||||
};
|
||||
|
@ -104,7 +104,7 @@ static void ath9k_op_ps_restore(struct ath_common *common)
|
||||
ath9k_ps_restore((struct ath_softc *) common->priv);
|
||||
}
|
||||
|
||||
static struct ath_ps_ops ath9k_ps_ops = {
|
||||
static const struct ath_ps_ops ath9k_ps_ops = {
|
||||
.wakeup = ath9k_op_ps_wakeup,
|
||||
.restore = ath9k_op_ps_restore,
|
||||
};
|
||||
|
@ -372,6 +372,8 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
int ch = WCN36XX_HW_CHANNEL(wcn);
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
|
||||
@ -382,6 +384,8 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -396,6 +400,8 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
*total &= FIF_ALLMULTI;
|
||||
|
||||
fp = (void *)(unsigned long)multicast;
|
||||
@ -408,6 +414,8 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
|
||||
else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
|
||||
wcn36xx_smd_set_mc_list(wcn, vif, fp);
|
||||
}
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
kfree(fp);
|
||||
}
|
||||
|
||||
@ -471,6 +479,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
key_conf->key,
|
||||
key_conf->keylen);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
switch (key_conf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
|
||||
@ -565,6 +575,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -725,6 +737,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
|
||||
vif, changed);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INFO) {
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||
"mac bss changed dtim period %d\n",
|
||||
@ -787,7 +801,13 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
bss_conf->aid);
|
||||
|
||||
vif_priv->sta_assoc = true;
|
||||
rcu_read_lock();
|
||||
|
||||
/*
|
||||
* Holding conf_mutex ensures mutal exclusion with
|
||||
* wcn36xx_sta_remove() and as such ensures that sta
|
||||
* won't be freed while we're operating on it. As such
|
||||
* we do not need to hold the rcu_read_lock().
|
||||
*/
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (!sta) {
|
||||
wcn36xx_err("sta %pM is not found\n",
|
||||
@ -811,7 +831,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
* place where AID is available.
|
||||
*/
|
||||
wcn36xx_smd_config_sta(wcn, vif, sta);
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||
"disassociated bss %pM vif %pM AID=%d\n",
|
||||
@ -873,6 +892,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -882,7 +904,10 @@ static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -893,8 +918,12 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
list_del(&vif_priv->list);
|
||||
wcn36xx_smd_delete_sta_self(wcn, vif->addr);
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
}
|
||||
|
||||
static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
||||
@ -915,9 +944,13 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
list_add(&vif_priv->list, &wcn->vif_list);
|
||||
wcn36xx_smd_add_sta_self(wcn, vif);
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -930,6 +963,8 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
|
||||
vif, sta->addr);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
spin_lock_init(&sta_priv->ampdu_lock);
|
||||
sta_priv->vif = vif_priv;
|
||||
/*
|
||||
@ -941,6 +976,9 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
sta_priv->aid = sta->aid;
|
||||
wcn36xx_smd_config_sta(wcn, vif, sta);
|
||||
}
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -954,8 +992,13 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
|
||||
vif, sta->addr, sta_priv->sta_index);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
|
||||
sta_priv->vif = NULL;
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -999,6 +1042,8 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
||||
action, tid);
|
||||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
sta_priv->tid = tid;
|
||||
@ -1038,6 +1083,8 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
wcn36xx_err("Unknown AMPDU action\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1216,6 +1263,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||
wcn = hw->priv;
|
||||
wcn->hw = hw;
|
||||
wcn->dev = &pdev->dev;
|
||||
mutex_init(&wcn->conf_mutex);
|
||||
mutex_init(&wcn->hal_mutex);
|
||||
mutex_init(&wcn->scan_lock);
|
||||
|
||||
|
@ -202,6 +202,9 @@ struct wcn36xx {
|
||||
struct qcom_smem_state *tx_rings_empty_state;
|
||||
unsigned tx_rings_empty_state_bit;
|
||||
|
||||
/* prevents concurrent FW reconfiguration */
|
||||
struct mutex conf_mutex;
|
||||
|
||||
/*
|
||||
* smd_buf must be protected with smd_mutex to garantee
|
||||
* that all messages are sent one after another
|
||||
|
@ -40,3 +40,15 @@ config WIL6210_TRACING
|
||||
option if you are interested in debugging the driver.
|
||||
|
||||
If unsure, say Y to make it easier to debug problems.
|
||||
|
||||
config WIL6210_DEBUGFS
|
||||
bool "wil6210 debugfs support"
|
||||
depends on WIL6210
|
||||
depends on DEBUG_FS
|
||||
default y
|
||||
---help---
|
||||
Say Y here to enable wil6210 debugfs support, using the
|
||||
kernel debugfs infrastructure. Select this
|
||||
option if you are interested in debugging the driver.
|
||||
|
||||
If unsure, say Y to make it easier to debug problems.
|
||||
|
@ -4,7 +4,7 @@ wil6210-y := main.o
|
||||
wil6210-y += netdev.o
|
||||
wil6210-y += cfg80211.o
|
||||
wil6210-y += pcie_bus.o
|
||||
wil6210-y += debugfs.o
|
||||
wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
|
||||
wil6210-y += wmi.o
|
||||
wil6210-y += interrupt.o
|
||||
wil6210-y += txrx.o
|
||||
|
@ -26,6 +26,12 @@ bool disable_ap_sme;
|
||||
module_param(disable_ap_sme, bool, 0444);
|
||||
MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static struct wiphy_wowlan_support wil_wowlan_support = {
|
||||
.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define CHAN60G(_channel, _flags) { \
|
||||
.band = NL80211_BAND_60GHZ, \
|
||||
.center_freq = 56160 + (2160 * (_channel)), \
|
||||
@ -273,12 +279,12 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
||||
|
||||
wil_dbg_wmi(wil, "Link status for CID %d: {\n"
|
||||
" MCS %d TSF 0x%016llx\n"
|
||||
" BF status 0x%08x SNR 0x%08x SQI %d%%\n"
|
||||
" BF status 0x%08x RSSI %d SQI %d%%\n"
|
||||
" Tx Tpt %d goodput %d Rx goodput %d\n"
|
||||
" Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
|
||||
cid, le16_to_cpu(reply.evt.bf_mcs),
|
||||
le64_to_cpu(reply.evt.tsf), reply.evt.status,
|
||||
le32_to_cpu(reply.evt.snr_val),
|
||||
reply.evt.rssi,
|
||||
reply.evt.sqi,
|
||||
le32_to_cpu(reply.evt.tx_tpt),
|
||||
le32_to_cpu(reply.evt.tx_goodput),
|
||||
@ -311,7 +317,11 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
||||
|
||||
if (test_bit(wil_status_fwconnected, wil->status)) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = reply.evt.sqi;
|
||||
if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING,
|
||||
wil->fw_capabilities))
|
||||
sinfo->signal = reply.evt.rssi;
|
||||
else
|
||||
sinfo->signal = reply.evt.sqi;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -372,6 +382,34 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
|
||||
wil_dbg_misc(wil, "start_p2p_device: entered\n");
|
||||
wil->p2p.p2p_dev_started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil_p2p_info *p2p = &wil->p2p;
|
||||
|
||||
if (!p2p->p2p_dev_started)
|
||||
return;
|
||||
|
||||
wil_dbg_misc(wil, "stop_p2p_device: entered\n");
|
||||
mutex_lock(&wil->mutex);
|
||||
mutex_lock(&wil->p2p_wdev_mutex);
|
||||
wil_p2p_stop_radio_operations(wil);
|
||||
p2p->p2p_dev_started = 0;
|
||||
mutex_unlock(&wil->p2p_wdev_mutex);
|
||||
mutex_unlock(&wil->mutex);
|
||||
}
|
||||
|
||||
static struct wireless_dev *
|
||||
wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
|
||||
unsigned char name_assign_type,
|
||||
@ -420,6 +458,7 @@ static int wil_cfg80211_del_iface(struct wiphy *wiphy,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_cfg80211_stop_p2p_device(wiphy, wdev);
|
||||
wil_p2p_wdev_free(wil);
|
||||
|
||||
return 0;
|
||||
@ -801,7 +840,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
|
||||
wil->bss = bss;
|
||||
/* Connect can take lots of time */
|
||||
mod_timer(&wil->connect_timer,
|
||||
jiffies + msecs_to_jiffies(2000));
|
||||
jiffies + msecs_to_jiffies(5000));
|
||||
} else {
|
||||
clear_bit(wil_status_fwconnecting, wil->status);
|
||||
}
|
||||
@ -884,6 +923,9 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
len, true);
|
||||
|
||||
if (len < sizeof(struct ieee80211_hdr_3addr))
|
||||
return -EINVAL;
|
||||
|
||||
cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
rc = -ENOMEM;
|
||||
@ -1648,34 +1690,6 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
|
||||
wil_dbg_misc(wil, "start_p2p_device: entered\n");
|
||||
wil->p2p.p2p_dev_started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil_p2p_info *p2p = &wil->p2p;
|
||||
|
||||
if (!p2p->p2p_dev_started)
|
||||
return;
|
||||
|
||||
wil_dbg_misc(wil, "stop_p2p_device: entered\n");
|
||||
mutex_lock(&wil->mutex);
|
||||
mutex_lock(&wil->p2p_wdev_mutex);
|
||||
wil_p2p_stop_radio_operations(wil);
|
||||
p2p->p2p_dev_started = 0;
|
||||
mutex_unlock(&wil->p2p_wdev_mutex);
|
||||
mutex_unlock(&wil->mutex);
|
||||
}
|
||||
|
||||
static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
bool enabled, int timeout)
|
||||
@ -1791,7 +1805,7 @@ static void wil_wiphy_init(struct wiphy *wiphy)
|
||||
|
||||
wiphy->bands[NL80211_BAND_60GHZ] = &wil_band_60ghz;
|
||||
|
||||
/* TODO: figure this out */
|
||||
/* may change after reading FW capabilities */
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
|
||||
|
||||
wiphy->cipher_suites = wil_cipher_suites;
|
||||
@ -1801,6 +1815,10 @@ static void wil_wiphy_init(struct wiphy *wiphy)
|
||||
|
||||
wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
|
||||
wiphy->vendor_commands = wil_nl80211_vendor_commands;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
wiphy->wowlan = &wil_wowlan_support;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct wireless_dev *wil_cfg80211_init(struct device *dev)
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#include "wil6210.h"
|
||||
#include "wmi.h"
|
||||
#include "txrx.h"
|
||||
@ -30,7 +29,6 @@
|
||||
static u32 mem_addr;
|
||||
static u32 dbg_txdesc_index;
|
||||
static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
|
||||
u32 vring_idle_trsh = 16; /* HW fetches up to 16 descriptors at once */
|
||||
|
||||
enum dbg_off_type {
|
||||
doff_u32 = 0,
|
||||
@ -801,6 +799,9 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
|
||||
int rc;
|
||||
void *frame;
|
||||
|
||||
if (!len)
|
||||
return -EINVAL;
|
||||
|
||||
frame = memdup_user(buf, len);
|
||||
if (IS_ERR(frame))
|
||||
return PTR_ERR(frame);
|
||||
@ -1013,6 +1014,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
|
||||
" TSF = 0x%016llx\n"
|
||||
" TxMCS = %2d TxTpt = %4d\n"
|
||||
" SQI = %4d\n"
|
||||
" RSSI = %4d\n"
|
||||
" Status = 0x%08x %s\n"
|
||||
" Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n"
|
||||
" Goodput(rx:tx) %4d:%4d\n"
|
||||
@ -1022,6 +1024,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
|
||||
le16_to_cpu(reply.evt.bf_mcs),
|
||||
le32_to_cpu(reply.evt.tx_tpt),
|
||||
reply.evt.sqi,
|
||||
reply.evt.rssi,
|
||||
status, wil_bfstatus_str(status),
|
||||
le16_to_cpu(reply.evt.my_rx_sector),
|
||||
le16_to_cpu(reply.evt.my_tx_sector),
|
||||
@ -1612,6 +1615,8 @@ static ssize_t wil_write_suspend_stats(struct file *file,
|
||||
struct wil6210_priv *wil = file->private_data;
|
||||
|
||||
memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
|
||||
wil->suspend_stats.min_suspend_time = ULONG_MAX;
|
||||
wil->suspend_stats.collection_start = ktime_get();
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -1623,18 +1628,27 @@ static ssize_t wil_read_suspend_stats(struct file *file,
|
||||
struct wil6210_priv *wil = file->private_data;
|
||||
static char text[400];
|
||||
int n;
|
||||
unsigned long long stats_collection_time =
|
||||
ktime_to_us(ktime_sub(ktime_get(),
|
||||
wil->suspend_stats.collection_start));
|
||||
|
||||
n = snprintf(text, sizeof(text),
|
||||
"Suspend statistics:\n"
|
||||
"successful suspends:%ld failed suspends:%ld\n"
|
||||
"successful resumes:%ld failed resumes:%ld\n"
|
||||
"rejected by host:%ld rejected by device:%ld\n",
|
||||
"rejected by host:%ld rejected by device:%ld\n"
|
||||
"total suspend time:%lld min suspend time:%lld\n"
|
||||
"max suspend time:%lld stats collection time: %lld\n",
|
||||
wil->suspend_stats.successful_suspends,
|
||||
wil->suspend_stats.failed_suspends,
|
||||
wil->suspend_stats.successful_resumes,
|
||||
wil->suspend_stats.failed_resumes,
|
||||
wil->suspend_stats.rejected_by_host,
|
||||
wil->suspend_stats.rejected_by_device);
|
||||
wil->suspend_stats.rejected_by_device,
|
||||
wil->suspend_stats.total_suspend_time,
|
||||
wil->suspend_stats.min_suspend_time,
|
||||
wil->suspend_stats.max_suspend_time,
|
||||
stats_collection_time);
|
||||
|
||||
n = min_t(int, n, sizeof(text));
|
||||
|
||||
@ -1747,6 +1761,7 @@ static const struct dbg_off dbg_wil_off[] = {
|
||||
WIL_FIELD(chip_revision, 0444, doff_u8),
|
||||
WIL_FIELD(abft_len, 0644, doff_u8),
|
||||
WIL_FIELD(wakeup_trigger, 0644, doff_u8),
|
||||
WIL_FIELD(vring_idle_trsh, 0644, doff_u32),
|
||||
{},
|
||||
};
|
||||
|
||||
@ -1762,8 +1777,6 @@ static const struct dbg_off dbg_statics[] = {
|
||||
{"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32},
|
||||
{"vring_index", 0644, (ulong)&dbg_vring_index, doff_u32},
|
||||
{"mem_addr", 0644, (ulong)&mem_addr, doff_u32},
|
||||
{"vring_idle_trsh", 0644, (ulong)&vring_idle_trsh,
|
||||
doff_u32},
|
||||
{"led_polarity", 0644, (ulong)&led_polarity, doff_u8},
|
||||
{},
|
||||
};
|
||||
@ -1790,6 +1803,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
|
||||
|
||||
wil6210_debugfs_create_ITR_CNT(wil, dbg);
|
||||
|
||||
wil->suspend_stats.collection_start = ktime_get();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
||||
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
|
||||
|
||||
if (unlikely(!isr)) {
|
||||
wil_err(wil, "spurious IRQ: RX\n");
|
||||
wil_err_ratelimited(wil, "spurious IRQ: RX\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -269,11 +269,12 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
||||
need_unmask = false;
|
||||
napi_schedule(&wil->napi_rx);
|
||||
} else {
|
||||
wil_err(wil,
|
||||
wil_err_ratelimited(
|
||||
wil,
|
||||
"Got Rx interrupt while stopping interface\n");
|
||||
}
|
||||
} else {
|
||||
wil_err(wil, "Got Rx interrupt while in reset\n");
|
||||
wil_err_ratelimited(wil, "Got Rx interrupt while in reset\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +303,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
|
||||
|
||||
if (unlikely(!isr)) {
|
||||
wil_err(wil, "spurious IRQ: TX\n");
|
||||
wil_err_ratelimited(wil, "spurious IRQ: TX\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -318,12 +319,13 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
need_unmask = false;
|
||||
napi_schedule(&wil->napi_tx);
|
||||
} else {
|
||||
wil_err(wil, "Got Tx interrupt while in reset\n");
|
||||
wil_err_ratelimited(wil, "Got Tx interrupt while in reset\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(isr))
|
||||
wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
|
||||
wil_err_ratelimited(wil, "un-handled TX ISR bits 0x%08x\n",
|
||||
isr);
|
||||
|
||||
/* Tx IRQ will be enabled when NAPI processing finished */
|
||||
|
||||
|
@ -394,10 +394,11 @@ static void wil_fw_error_worker(struct work_struct *work)
|
||||
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
|
||||
fw_error_worker);
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg_misc(wil, "fw error worker\n");
|
||||
|
||||
if (!netif_running(wil_to_ndev(wil))) {
|
||||
if (!(ndev->flags & IFF_UP)) {
|
||||
wil_info(wil, "No recovery - interface is down\n");
|
||||
return;
|
||||
}
|
||||
@ -578,6 +579,9 @@ int wil_priv_init(struct wil6210_priv *wil)
|
||||
|
||||
wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
|
||||
WMI_WAKEUP_TRIGGER_BCAST;
|
||||
memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
|
||||
wil->suspend_stats.min_suspend_time = ULONG_MAX;
|
||||
wil->vring_idle_trsh = 16;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -926,6 +930,29 @@ int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void wil_pre_fw_config(struct wil6210_priv *wil)
|
||||
{
|
||||
/* Mark FW as loaded from host */
|
||||
wil_s(wil, RGF_USER_USAGE_6, 1);
|
||||
|
||||
/* clear any interrupts which on-card-firmware
|
||||
* may have set
|
||||
*/
|
||||
wil6210_clear_irq(wil);
|
||||
/* CAF_ICR - clear and mask */
|
||||
/* it is W1C, clear by writing back same value */
|
||||
wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
|
||||
wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
|
||||
/* clear PAL_UNIT_ICR (potential D0->D3 leftover) */
|
||||
wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR), 0);
|
||||
|
||||
if (wil->fw_calib_result > 0) {
|
||||
__le32 val = cpu_to_le32(wil->fw_calib_result |
|
||||
(CALIB_RESULT_SIGNATURE << 8));
|
||||
wil_w(wil, RGF_USER_FW_CALIB_RESULT, (u32 __force)val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We reset all the structures, and we reset the UMAC.
|
||||
* After calling this routine, you're expected to reload
|
||||
@ -1019,18 +1046,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Mark FW as loaded from host */
|
||||
wil_s(wil, RGF_USER_USAGE_6, 1);
|
||||
|
||||
/* clear any interrupts which on-card-firmware
|
||||
* may have set
|
||||
*/
|
||||
wil6210_clear_irq(wil);
|
||||
/* CAF_ICR - clear and mask */
|
||||
/* it is W1C, clear by writing back same value */
|
||||
wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
|
||||
wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
|
||||
|
||||
wil_pre_fw_config(wil);
|
||||
wil_release_cpu(wil);
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,9 @@ void wil_set_capabilities(struct wil6210_priv *wil)
|
||||
|
||||
/* extract FW capabilities from file without loading the FW */
|
||||
wil_request_firmware(wil, wil->wil_fw_name, false);
|
||||
|
||||
if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
|
||||
wil_to_wiphy(wil)->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
}
|
||||
|
||||
void wil_disable_irq(struct wil6210_priv *wil)
|
||||
|
@ -21,10 +21,11 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
|
||||
{
|
||||
int rc = 0;
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system");
|
||||
|
||||
if (!netif_running(wil_to_ndev(wil))) {
|
||||
if (!(ndev->flags & IFF_UP)) {
|
||||
/* can always sleep when down */
|
||||
wil_dbg_pm(wil, "Interface is down\n");
|
||||
goto out;
|
||||
@ -85,7 +86,9 @@ static int wil_resume_keep_radio_on(struct wil6210_priv *wil)
|
||||
/* Send WMI resume request to the device */
|
||||
rc = wmi_resume(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "device failed to resume (%d), resetting\n", rc);
|
||||
wil_err(wil, "device failed to resume (%d)\n", rc);
|
||||
if (no_fw_recovery)
|
||||
goto out;
|
||||
rc = wil_down(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "wil_down failed (%d)\n", rc);
|
||||
@ -298,6 +301,9 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
|
||||
wil_dbg_pm(wil, "suspend: %s => %d\n",
|
||||
is_runtime ? "runtime" : "system", rc);
|
||||
|
||||
if (!rc)
|
||||
wil->suspend_stats.suspend_start_time = ktime_get();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -307,6 +313,7 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime)
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
bool keep_radio_on = ndev->flags & IFF_UP &&
|
||||
wil->keep_radio_on_during_sleep;
|
||||
unsigned long long suspend_time_usec = 0;
|
||||
|
||||
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
|
||||
|
||||
@ -324,8 +331,20 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime)
|
||||
else
|
||||
rc = wil_resume_radio_off(wil);
|
||||
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
suspend_time_usec =
|
||||
ktime_to_us(ktime_sub(ktime_get(),
|
||||
wil->suspend_stats.suspend_start_time));
|
||||
wil->suspend_stats.total_suspend_time += suspend_time_usec;
|
||||
if (suspend_time_usec < wil->suspend_stats.min_suspend_time)
|
||||
wil->suspend_stats.min_suspend_time = suspend_time_usec;
|
||||
if (suspend_time_usec > wil->suspend_stats.max_suspend_time)
|
||||
wil->suspend_stats.max_suspend_time = suspend_time_usec;
|
||||
|
||||
out:
|
||||
wil_dbg_pm(wil, "resume: %s => %d\n",
|
||||
is_runtime ? "runtime" : "system", rc);
|
||||
wil_dbg_pm(wil, "resume: %s => %d, suspend time %lld usec\n",
|
||||
is_runtime ? "runtime" : "system", rc, suspend_time_usec);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1666,7 +1666,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
|
||||
/* performance monitoring */
|
||||
used = wil_vring_used_tx(vring);
|
||||
if (wil_val_in_range(vring_idle_trsh,
|
||||
if (wil_val_in_range(wil->vring_idle_trsh,
|
||||
used, used + descs_used)) {
|
||||
txdata->idle += get_cycles() - txdata->last_idle;
|
||||
wil_dbg_txrx(wil, "Ring[%2d] not idle %d -> %d\n",
|
||||
@ -1813,7 +1813,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
|
||||
/* performance monitoring */
|
||||
used = wil_vring_used_tx(vring);
|
||||
if (wil_val_in_range(vring_idle_trsh,
|
||||
if (wil_val_in_range(wil->vring_idle_trsh,
|
||||
used, used + nr_frags + 1)) {
|
||||
txdata->idle += get_cycles() - txdata->last_idle;
|
||||
wil_dbg_txrx(wil, "Ring[%2d] not idle %d -> %d\n",
|
||||
@ -2175,7 +2175,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
|
||||
/* performance monitoring */
|
||||
used_new = wil_vring_used_tx(vring);
|
||||
if (wil_val_in_range(vring_idle_trsh,
|
||||
if (wil_val_in_range(wil->vring_idle_trsh,
|
||||
used_new, used_before_complete)) {
|
||||
wil_dbg_txrx(wil, "Ring[%2d] idle %d -> %d\n",
|
||||
ringid, used_before_complete, used_new);
|
||||
|
@ -30,7 +30,6 @@ extern bool no_fw_recovery;
|
||||
extern unsigned int mtu_max;
|
||||
extern unsigned short rx_ring_overflow_thrsh;
|
||||
extern int agg_wsize;
|
||||
extern u32 vring_idle_trsh;
|
||||
extern bool rx_align_2;
|
||||
extern bool rx_large_buf;
|
||||
extern bool debug_fw;
|
||||
@ -90,6 +89,11 @@ struct wil_suspend_stats {
|
||||
unsigned long failed_resumes;
|
||||
unsigned long rejected_by_device;
|
||||
unsigned long rejected_by_host;
|
||||
unsigned long long total_suspend_time;
|
||||
unsigned long long min_suspend_time;
|
||||
unsigned long long max_suspend_time;
|
||||
ktime_t collection_start;
|
||||
ktime_t suspend_start_time;
|
||||
};
|
||||
|
||||
/* Calculate MAC buffer size for the firmware. It includes all overhead,
|
||||
@ -166,6 +170,10 @@ struct RGF_ICR {
|
||||
#define RGF_USER_USER_SCRATCH_PAD (0x8802bc)
|
||||
#define RGF_USER_BL (0x880A3C) /* Boot Loader */
|
||||
#define RGF_USER_FW_REV_ID (0x880a8c) /* chip revision */
|
||||
#define RGF_USER_FW_CALIB_RESULT (0x880a90) /* b0-7:result
|
||||
* b8-15:signature
|
||||
*/
|
||||
#define CALIB_RESULT_SIGNATURE (0x11)
|
||||
#define RGF_USER_CLKS_CTL_0 (0x880abc)
|
||||
#define BIT_USER_CLKS_CAR_AHB_SW_SEL BIT(1) /* ref clk/PLL */
|
||||
#define BIT_USER_CLKS_RST_PWGD BIT(11) /* reset on "power good" */
|
||||
@ -260,6 +268,7 @@ struct RGF_ICR {
|
||||
#define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
|
||||
|
||||
#define RGF_HP_CTRL (0x88265c)
|
||||
#define RGF_PAL_UNIT_ICR (0x88266c) /* struct RGF_ICR */
|
||||
#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
|
||||
|
||||
/* MAC timer, usec, for packet lifetime */
|
||||
@ -684,6 +693,7 @@ struct wil6210_priv {
|
||||
u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
|
||||
struct wil_sta_info sta[WIL6210_MAX_CID];
|
||||
int bcast_vring;
|
||||
u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */
|
||||
bool use_extended_dma_addr; /* indicates whether we are using 48 bits */
|
||||
/* scan */
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
@ -719,6 +729,8 @@ struct wil6210_priv {
|
||||
|
||||
enum wmi_ps_profile_type ps_profile;
|
||||
|
||||
int fw_calib_result;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct notifier_block pm_notify;
|
||||
@ -929,8 +941,14 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct cfg80211_mgmt_tx_params *params,
|
||||
u64 *cookie);
|
||||
|
||||
#if defined(CONFIG_WIL6210_DEBUGFS)
|
||||
int wil6210_debugfs_init(struct wil6210_priv *wil);
|
||||
void wil6210_debugfs_remove(struct wil6210_priv *wil);
|
||||
#else
|
||||
static inline int wil6210_debugfs_init(struct wil6210_priv *wil) { return 0; }
|
||||
static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {}
|
||||
#endif
|
||||
|
||||
int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
||||
struct station_info *sinfo);
|
||||
|
||||
|
@ -344,6 +344,11 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
strlcpy(wdev->wiphy->fw_version, wil->fw_version,
|
||||
sizeof(wdev->wiphy->fw_version));
|
||||
|
||||
if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
|
||||
wil_dbg_wmi(wil, "rfc calibration result %d\n",
|
||||
evt->rfc_read_calib_result);
|
||||
wil->fw_calib_result = evt->rfc_read_calib_result;
|
||||
}
|
||||
wil_set_recovery_state(wil, fw_recovery_idle);
|
||||
set_bit(wil_status_fwready, wil->status);
|
||||
/* let the reset sequence continue */
|
||||
@ -381,12 +386,15 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
ch_no = data->info.channel + 1;
|
||||
freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
|
||||
channel = ieee80211_get_channel(wiphy, freq);
|
||||
signal = data->info.sqi;
|
||||
if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities))
|
||||
signal = 100 * data->info.rssi;
|
||||
else
|
||||
signal = data->info.sqi;
|
||||
d_status = le16_to_cpu(data->info.status);
|
||||
fc = rx_mgmt_frame->frame_control;
|
||||
|
||||
wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d SNR %d SQI %d%%\n",
|
||||
data->info.channel, data->info.mcs, data->info.snr,
|
||||
wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n",
|
||||
data->info.channel, data->info.mcs, data->info.rssi,
|
||||
data->info.sqi);
|
||||
wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
|
||||
le16_to_cpu(fc));
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user