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:
@@ -180,6 +180,29 @@ regrdwr
|
||||
echo "1 0xa060 0x12" > regrdwr : Write the MAC register
|
||||
echo "1 0xa794 0x80000000" > regrdwr
|
||||
: Write 0x80000000 to MAC register
|
||||
|
||||
memrw
|
||||
This command is used to read/write the firmware memory.
|
||||
|
||||
Usage:
|
||||
1) For reading firmware memory location.
|
||||
echo r <address> 0 > /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
cat /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
2) For writing value to firmware memory location.
|
||||
echo w <address> [value] > /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
|
||||
where the parameters are,
|
||||
<address>: memory address
|
||||
[value]: value to be written
|
||||
|
||||
Examples:
|
||||
echo r 0x4cf70 0 > /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
cat /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
: Read memory address 0x4cf70
|
||||
iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000
|
||||
echo w 0x8000a000 0xc0000000 > /sys/kernel/debug/mwifiex/mlan0/memrw
|
||||
: Write 0xc0000000 to memory address 0x8000a000
|
||||
|
||||
rdeeprom
|
||||
This command is used to read the EEPROM contents of the card.
|
||||
|
||||
|
@@ -1203,6 +1203,12 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
|
||||
priv->adapter->curr_iface_comb.p2p_intf--;
|
||||
priv->adapter->curr_iface_comb.sta_intf++;
|
||||
dev->ieee80211_ptr->iftype = type;
|
||||
if (mwifiex_deinit_priv_params(priv))
|
||||
return -1;
|
||||
if (mwifiex_init_new_priv_params(priv, dev, type))
|
||||
return -1;
|
||||
if (mwifiex_sta_init_cmd(priv, false, false))
|
||||
return -1;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (mwifiex_cfg80211_deinit_p2p(priv))
|
||||
@@ -3016,6 +3022,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
||||
priv->netdev = NULL;
|
||||
memset(&priv->wdev, 0, sizeof(priv->wdev));
|
||||
priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
|
||||
destroy_workqueue(priv->dfs_cac_workqueue);
|
||||
priv->dfs_cac_workqueue = NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@@ -3070,8 +3078,10 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
|
||||
|
||||
skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
|
||||
skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
|
||||
skb_unlink(skb, &priv->bypass_txq);
|
||||
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
|
||||
}
|
||||
|
||||
if (netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_off(priv->netdev);
|
||||
|
@@ -1118,13 +1118,14 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
||||
void
|
||||
mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
if (!adapter->cmd_sent &&
|
||||
if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) &&
|
||||
!adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
|
||||
mwifiex_dnld_sleep_confirm_cmd(adapter);
|
||||
else
|
||||
mwifiex_dbg(adapter, CMD,
|
||||
"cmd: Delay Sleep Confirm (%s%s%s)\n",
|
||||
"cmd: Delay Sleep Confirm (%s%s%s%s)\n",
|
||||
(adapter->cmd_sent) ? "D" : "",
|
||||
atomic_read(&adapter->tx_hw_pending) ? "T" : "",
|
||||
(adapter->curr_cmd) ? "C" : "",
|
||||
(IS_CARD_RX_RCVD(adapter)) ? "R" : "");
|
||||
}
|
||||
|
@@ -181,6 +181,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
||||
#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154)
|
||||
#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156)
|
||||
#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 176)
|
||||
#define TLV_TYPE_PS_PARAMS_IN_HS (PROPRIETARY_TLV_BASE_ID + 181)
|
||||
#define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183)
|
||||
#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184)
|
||||
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
|
||||
@@ -986,6 +987,15 @@ struct mwifiex_ps_param {
|
||||
__le16 delay_to_ps;
|
||||
};
|
||||
|
||||
#define HS_DEF_WAKE_INTERVAL 100
|
||||
#define HS_DEF_INACTIVITY_TIMEOUT 50
|
||||
|
||||
struct mwifiex_ps_param_in_hs {
|
||||
struct mwifiex_ie_types_header header;
|
||||
__le32 hs_wake_int;
|
||||
__le32 hs_inact_timeout;
|
||||
};
|
||||
|
||||
#define BITMAP_AUTO_DS 0x01
|
||||
#define BITMAP_STA_PS 0x10
|
||||
|
||||
|
@@ -270,6 +270,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
|
||||
adapter->adhoc_11n_enabled = false;
|
||||
|
||||
mwifiex_wmm_init(adapter);
|
||||
atomic_set(&adapter->tx_hw_pending, 0);
|
||||
|
||||
sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
|
||||
adapter->sleep_cfm->data;
|
||||
|
@@ -308,6 +308,9 @@ process_start:
|
||||
/* We have tried to wakeup the card already */
|
||||
if (adapter->pm_wakeup_fw_try)
|
||||
break;
|
||||
if (adapter->ps_state == PS_STATE_PRE_SLEEP)
|
||||
mwifiex_check_ps_cond(adapter);
|
||||
|
||||
if (adapter->ps_state != PS_STATE_AWAKE)
|
||||
break;
|
||||
if (adapter->tx_lock_flag) {
|
||||
@@ -355,10 +358,8 @@ process_start:
|
||||
|
||||
/* Check if we need to confirm Sleep Request
|
||||
received previously */
|
||||
if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
|
||||
if (!adapter->cmd_sent && !adapter->curr_cmd)
|
||||
mwifiex_check_ps_cond(adapter);
|
||||
}
|
||||
if (adapter->ps_state == PS_STATE_PRE_SLEEP)
|
||||
mwifiex_check_ps_cond(adapter);
|
||||
|
||||
/* * The ps_state may have been changed during processing of
|
||||
* Sleep Request event.
|
||||
@@ -520,9 +521,9 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
||||
struct mwifiex_private *priv;
|
||||
struct mwifiex_adapter *adapter = context;
|
||||
struct mwifiex_fw_image fw;
|
||||
struct semaphore *sem = adapter->card_sem;
|
||||
bool init_failed = false;
|
||||
struct wireless_dev *wdev;
|
||||
struct completion *fw_done = adapter->fw_done;
|
||||
|
||||
if (!firmware) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@@ -669,7 +670,8 @@ done:
|
||||
}
|
||||
if (init_failed)
|
||||
mwifiex_free_adapter(adapter);
|
||||
up(sem);
|
||||
/* Tell all current and future waiters we're finished */
|
||||
complete_all(fw_done);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1364,7 +1366,7 @@ static void mwifiex_main_work_queue(struct work_struct *work)
|
||||
* code is extracted from mwifiex_remove_card()
|
||||
*/
|
||||
static int
|
||||
mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
||||
mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct mwifiex_private *priv;
|
||||
int i;
|
||||
@@ -1372,8 +1374,9 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
||||
if (!adapter)
|
||||
goto exit_return;
|
||||
|
||||
if (down_interruptible(sem))
|
||||
goto exit_sem_err;
|
||||
wait_for_completion(adapter->fw_done);
|
||||
/* Caller should ensure we aren't suspending while this happens */
|
||||
reinit_completion(adapter->fw_done);
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
mwifiex_deauthenticate(priv, NULL);
|
||||
@@ -1430,8 +1433,6 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
up(sem);
|
||||
exit_sem_err:
|
||||
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
|
||||
exit_return:
|
||||
return 0;
|
||||
@@ -1441,21 +1442,18 @@ exit_return:
|
||||
* code is extracted from mwifiex_add_card()
|
||||
*/
|
||||
static int
|
||||
mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
|
||||
mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct completion *fw_done,
|
||||
struct mwifiex_if_ops *if_ops, u8 iface_type)
|
||||
{
|
||||
char fw_name[32];
|
||||
struct pcie_service_card *card = adapter->card;
|
||||
|
||||
if (down_interruptible(sem))
|
||||
goto exit_sem_err;
|
||||
|
||||
mwifiex_init_lock_list(adapter);
|
||||
if (adapter->if_ops.up_dev)
|
||||
adapter->if_ops.up_dev(adapter);
|
||||
|
||||
adapter->iface_type = iface_type;
|
||||
adapter->card_sem = sem;
|
||||
adapter->fw_done = fw_done;
|
||||
|
||||
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
|
||||
adapter->surprise_removed = false;
|
||||
@@ -1506,7 +1504,8 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
|
||||
}
|
||||
strcpy(adapter->fw_name, fw_name);
|
||||
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
|
||||
up(sem);
|
||||
|
||||
complete_all(adapter->fw_done);
|
||||
return 0;
|
||||
|
||||
err_init_fw:
|
||||
@@ -1526,8 +1525,7 @@ err_init_fw:
|
||||
err_kmalloc:
|
||||
mwifiex_terminate_workqueue(adapter);
|
||||
adapter->surprise_removed = true;
|
||||
up(sem);
|
||||
exit_sem_err:
|
||||
complete_all(adapter->fw_done);
|
||||
mwifiex_dbg(adapter, INFO, "%s, error\n", __func__);
|
||||
|
||||
return -1;
|
||||
@@ -1542,16 +1540,67 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
|
||||
struct mwifiex_if_ops if_ops;
|
||||
|
||||
if (!prepare) {
|
||||
mwifiex_reinit_sw(adapter, adapter->card_sem, &if_ops,
|
||||
mwifiex_reinit_sw(adapter, adapter->fw_done, &if_ops,
|
||||
adapter->iface_type);
|
||||
} else {
|
||||
memcpy(&if_ops, &adapter->if_ops,
|
||||
sizeof(struct mwifiex_if_ops));
|
||||
mwifiex_shutdown_sw(adapter, adapter->card_sem);
|
||||
mwifiex_shutdown_sw(adapter);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
|
||||
|
||||
static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv;
|
||||
|
||||
if (adapter->irq_wakeup >= 0) {
|
||||
dev_dbg(adapter->dev, "%s: wake by wifi", __func__);
|
||||
adapter->wake_by_wifi = true;
|
||||
disable_irq_nosync(irq);
|
||||
}
|
||||
|
||||
/* Notify PM core we are wakeup source */
|
||||
pm_wakeup_event(adapter->dev, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = adapter->dev;
|
||||
|
||||
if (!dev->of_node)
|
||||
return;
|
||||
|
||||
adapter->dt_node = dev->of_node;
|
||||
adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0);
|
||||
if (!adapter->irq_wakeup) {
|
||||
dev_info(dev, "fail to parse irq_wakeup from device tree\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, adapter->irq_wakeup,
|
||||
mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
|
||||
"wifi_wake", adapter);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
|
||||
adapter->irq_wakeup, ret);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
disable_irq(adapter->irq_wakeup);
|
||||
if (device_init_wakeup(dev, true)) {
|
||||
dev_err(dev, "fail to init wakeup for mwifiex\n");
|
||||
goto err_exit;
|
||||
}
|
||||
return;
|
||||
|
||||
err_exit:
|
||||
adapter->irq_wakeup = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adds the card.
|
||||
*
|
||||
@@ -1566,21 +1615,22 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
|
||||
* - Add logical interfaces
|
||||
*/
|
||||
int
|
||||
mwifiex_add_card(void *card, struct semaphore *sem,
|
||||
struct mwifiex_if_ops *if_ops, u8 iface_type)
|
||||
mwifiex_add_card(void *card, struct completion *fw_done,
|
||||
struct mwifiex_if_ops *if_ops, u8 iface_type,
|
||||
struct device *dev)
|
||||
{
|
||||
struct mwifiex_adapter *adapter;
|
||||
|
||||
if (down_interruptible(sem))
|
||||
goto exit_sem_err;
|
||||
|
||||
if (mwifiex_register(card, if_ops, (void **)&adapter)) {
|
||||
pr_err("%s: software init failed\n", __func__);
|
||||
goto err_init_sw;
|
||||
}
|
||||
|
||||
adapter->dev = dev;
|
||||
mwifiex_probe_of(adapter);
|
||||
|
||||
adapter->iface_type = iface_type;
|
||||
adapter->card_sem = sem;
|
||||
adapter->fw_done = fw_done;
|
||||
|
||||
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
|
||||
adapter->surprise_removed = false;
|
||||
@@ -1649,9 +1699,7 @@ err_kmalloc:
|
||||
mwifiex_free_adapter(adapter);
|
||||
|
||||
err_init_sw:
|
||||
up(sem);
|
||||
|
||||
exit_sem_err:
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_add_card);
|
||||
@@ -1667,14 +1715,11 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card);
|
||||
* - Unregister the device
|
||||
* - Free the adapter structure
|
||||
*/
|
||||
int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
||||
int mwifiex_remove_card(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct mwifiex_private *priv = NULL;
|
||||
int i;
|
||||
|
||||
if (down_trylock(sem))
|
||||
goto exit_sem_err;
|
||||
|
||||
if (!adapter)
|
||||
goto exit_remove;
|
||||
|
||||
@@ -1744,8 +1789,6 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
||||
mwifiex_free_adapter(adapter);
|
||||
|
||||
exit_remove:
|
||||
up(sem);
|
||||
exit_sem_err:
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_remove_card);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#ifndef _MWIFIEX_MAIN_H_
|
||||
#define _MWIFIEX_MAIN_H_
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
@@ -315,6 +316,7 @@ struct mwifiex_tid_tbl {
|
||||
#define WMM_HIGHEST_PRIORITY 7
|
||||
#define HIGH_PRIO_TID 7
|
||||
#define LOW_PRIO_TID 0
|
||||
#define NO_PKT_PRIO_TID -1
|
||||
#define MWIFIEX_WMM_DRV_DELAY_MAX 510
|
||||
|
||||
struct mwifiex_wmm_desc {
|
||||
@@ -856,6 +858,7 @@ struct mwifiex_adapter {
|
||||
atomic_t rx_pending;
|
||||
atomic_t tx_pending;
|
||||
atomic_t cmd_pending;
|
||||
atomic_t tx_hw_pending;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct main_work;
|
||||
struct workqueue_struct *rx_workqueue;
|
||||
@@ -983,7 +986,10 @@ struct mwifiex_adapter {
|
||||
u32 usr_dot_11ac_mcs_support;
|
||||
|
||||
atomic_t pending_bridged_pkts;
|
||||
struct semaphore *card_sem;
|
||||
|
||||
/* For synchronizing FW initialization with device lifecycle. */
|
||||
struct completion *fw_done;
|
||||
|
||||
bool ext_scan;
|
||||
u8 fw_api_ver;
|
||||
u8 key_api_major_ver, key_api_minor_ver;
|
||||
@@ -1010,6 +1016,10 @@ struct mwifiex_adapter {
|
||||
bool usb_mc_setup;
|
||||
struct cfg80211_wowlan_nd_info *nd_info;
|
||||
struct ieee80211_regdomain *regd;
|
||||
|
||||
/* Wake-on-WLAN (WoWLAN) */
|
||||
int irq_wakeup;
|
||||
bool wake_by_wifi;
|
||||
};
|
||||
|
||||
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
|
||||
@@ -1409,10 +1419,34 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Disable platform specific wakeup interrupt */
|
||||
static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
if (adapter->irq_wakeup >= 0) {
|
||||
disable_irq_wake(adapter->irq_wakeup);
|
||||
if (!adapter->wake_by_wifi)
|
||||
disable_irq(adapter->irq_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable platform specific wakeup interrupt */
|
||||
static inline void mwifiex_enable_wake(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
/* Enable platform specific wakeup interrupt */
|
||||
if (adapter->irq_wakeup >= 0) {
|
||||
adapter->wake_by_wifi = false;
|
||||
enable_irq(adapter->irq_wakeup);
|
||||
enable_irq_wake(adapter->irq_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
|
||||
u32 func_init_shutdown);
|
||||
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
|
||||
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
|
||||
|
||||
int mwifiex_add_card(void *card, struct completion *fw_done,
|
||||
struct mwifiex_if_ops *if_ops, u8 iface_type,
|
||||
struct device *dev);
|
||||
int mwifiex_remove_card(struct mwifiex_adapter *adapter);
|
||||
|
||||
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
|
||||
int maxlen);
|
||||
|
@@ -35,7 +35,21 @@ static u8 user_rmmod;
|
||||
|
||||
static struct mwifiex_if_ops pcie_ops;
|
||||
|
||||
static struct semaphore add_remove_card_sem;
|
||||
static const struct of_device_id mwifiex_pcie_of_match_table[] = {
|
||||
{ .compatible = "pci11ab,2b42" },
|
||||
{ .compatible = "pci1b4b,2b42" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int mwifiex_pcie_probe_of(struct device *dev)
|
||||
{
|
||||
if (!of_match_node(mwifiex_pcie_of_match_table, dev->of_node)) {
|
||||
dev_err(dev, "required compatible string missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
|
||||
@@ -101,23 +115,30 @@ static int mwifiex_pcie_suspend(struct device *dev)
|
||||
{
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct pcie_service_card *card;
|
||||
int hs_actived;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (pdev) {
|
||||
card = pci_get_drvdata(pdev);
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("Card or adapter structure is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pr_err("PCIE device is not specified\n");
|
||||
card = pci_get_drvdata(pdev);
|
||||
|
||||
/* Might still be loading firmware */
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
adapter = card->adapter;
|
||||
if (!adapter) {
|
||||
dev_err(dev, "adapter is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
adapter = card->adapter;
|
||||
mwifiex_enable_wake(adapter);
|
||||
|
||||
hs_actived = mwifiex_enable_hs(adapter);
|
||||
/* Enable the Host Sleep */
|
||||
if (!mwifiex_enable_hs(adapter)) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"cmd: failed to suspend\n");
|
||||
adapter->hs_enabling = false;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
flush_workqueue(adapter->workqueue);
|
||||
|
||||
/* Indicate device suspended */
|
||||
adapter->is_suspended = true;
|
||||
@@ -140,14 +161,10 @@ static int mwifiex_pcie_resume(struct device *dev)
|
||||
struct pcie_service_card *card;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (pdev) {
|
||||
card = pci_get_drvdata(pdev);
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("Card or adapter structure is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pr_err("PCIE device is not specified\n");
|
||||
card = pci_get_drvdata(pdev);
|
||||
|
||||
if (!card->adapter) {
|
||||
dev_err(dev, "adapter structure is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -163,6 +180,7 @@ static int mwifiex_pcie_resume(struct device *dev)
|
||||
|
||||
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
|
||||
MWIFIEX_ASYNC_CMD);
|
||||
mwifiex_disable_wake(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -178,14 +196,17 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct pcie_service_card *card;
|
||||
int ret;
|
||||
|
||||
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
|
||||
pdev->vendor, pdev->device, pdev->revision);
|
||||
|
||||
card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
|
||||
card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&card->fw_done);
|
||||
|
||||
card->dev = pdev;
|
||||
|
||||
if (ent->driver_data) {
|
||||
@@ -199,8 +220,15 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
|
||||
card->pcie.can_ext_scan = data->can_ext_scan;
|
||||
}
|
||||
|
||||
if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
|
||||
MWIFIEX_PCIE)) {
|
||||
/* device tree node parsing and platform specific configuration*/
|
||||
if (pdev->dev.of_node) {
|
||||
ret = mwifiex_pcie_probe_of(&pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
|
||||
MWIFIEX_PCIE, &pdev->dev)) {
|
||||
pr_err("%s failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
@@ -218,19 +246,14 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
|
||||
struct mwifiex_private *priv;
|
||||
|
||||
card = pci_get_drvdata(pdev);
|
||||
if (!card)
|
||||
return;
|
||||
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
adapter = card->adapter;
|
||||
if (!adapter || !adapter->priv_num)
|
||||
return;
|
||||
|
||||
if (user_rmmod && !adapter->mfg_mode) {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (adapter->is_suspended)
|
||||
mwifiex_pcie_resume(&pdev->dev);
|
||||
#endif
|
||||
|
||||
mwifiex_deauthenticate_all(adapter);
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
@@ -240,7 +263,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
|
||||
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
|
||||
}
|
||||
|
||||
mwifiex_remove_card(card->adapter, &add_remove_card_sem);
|
||||
mwifiex_remove_card(adapter);
|
||||
}
|
||||
|
||||
static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
|
||||
@@ -483,6 +506,7 @@ static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&adapter->tx_hw_pending, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -682,6 +706,7 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
|
||||
card->tx_buf_list[i] = NULL;
|
||||
}
|
||||
|
||||
atomic_set(&adapter->tx_hw_pending, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1119,6 +1144,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
|
||||
-1);
|
||||
else
|
||||
mwifiex_write_data_complete(adapter, skb, 0, 0);
|
||||
atomic_dec(&adapter->tx_hw_pending);
|
||||
}
|
||||
|
||||
card->tx_buf_list[wrdoneidx] = NULL;
|
||||
@@ -1211,6 +1237,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
|
||||
wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
|
||||
buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
|
||||
card->tx_buf_list[wrindx] = skb;
|
||||
atomic_inc(&adapter->tx_hw_pending);
|
||||
|
||||
if (reg->pfu_enabled) {
|
||||
desc2 = card->txbd_ring[wrindx];
|
||||
@@ -1288,6 +1315,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
|
||||
done_unmap:
|
||||
mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
|
||||
card->tx_buf_list[wrindx] = NULL;
|
||||
atomic_dec(&adapter->tx_hw_pending);
|
||||
if (reg->pfu_enabled)
|
||||
memset(desc2, 0, sizeof(*desc2));
|
||||
else
|
||||
@@ -1669,9 +1697,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
|
||||
|
||||
if (!adapter->curr_cmd) {
|
||||
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
|
||||
mwifiex_process_sleep_confirm_resp(adapter, skb->data,
|
||||
skb->len);
|
||||
mwifiex_pcie_enable_host_int(adapter);
|
||||
if (mwifiex_write_reg(adapter,
|
||||
PCIE_CPU_INT_EVENT,
|
||||
CPU_INTR_SLEEP_CFM_DONE)) {
|
||||
@@ -1684,6 +1709,9 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
|
||||
while (reg->sleep_cookie && (count++ < 10) &&
|
||||
mwifiex_pcie_ok_to_access_hw(adapter))
|
||||
usleep_range(50, 60);
|
||||
mwifiex_pcie_enable_host_int(adapter);
|
||||
mwifiex_process_sleep_confirm_resp(adapter, skb->data,
|
||||
skb->len);
|
||||
} else {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"There is no command but got cmdrsp\n");
|
||||
@@ -2210,7 +2238,8 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
|
||||
}
|
||||
|
||||
card = pci_get_drvdata(pdev);
|
||||
if (!card || !card->adapter) {
|
||||
|
||||
if (!card->adapter) {
|
||||
pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
|
||||
card ? card->adapter : NULL);
|
||||
goto exit;
|
||||
@@ -2322,6 +2351,8 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
|
||||
ret = mwifiex_pcie_process_cmd_complete(adapter);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (adapter->hs_activated)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (card->msi_enable) {
|
||||
@@ -2806,7 +2837,6 @@ err_req_region0:
|
||||
err_set_dma_mask:
|
||||
pci_disable_device(pdev);
|
||||
err_enable_dev:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2840,9 +2870,7 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
|
||||
pci_disable_device(pdev);
|
||||
pci_release_region(pdev, 2);
|
||||
pci_release_region(pdev, 0);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
|
||||
@@ -2962,11 +2990,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
|
||||
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct pcie_service_card *card = adapter->card;
|
||||
struct pci_dev *pdev = card->dev;
|
||||
|
||||
/* save adapter pointer in card */
|
||||
card->adapter = adapter;
|
||||
adapter->dev = &pdev->dev;
|
||||
|
||||
if (mwifiex_pcie_request_irq(adapter))
|
||||
return -1;
|
||||
@@ -2989,30 +3015,28 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
|
||||
static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct pcie_service_card *card = adapter->card;
|
||||
struct pci_dev *pdev;
|
||||
struct pci_dev *pdev = card->dev;
|
||||
int i;
|
||||
|
||||
if (card) {
|
||||
pdev = card->dev;
|
||||
if (card->msix_enable) {
|
||||
for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
|
||||
synchronize_irq(card->msix_entries[i].vector);
|
||||
if (card->msix_enable) {
|
||||
for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
|
||||
synchronize_irq(card->msix_entries[i].vector);
|
||||
|
||||
for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
|
||||
free_irq(card->msix_entries[i].vector,
|
||||
&card->msix_ctx[i]);
|
||||
for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
|
||||
free_irq(card->msix_entries[i].vector,
|
||||
&card->msix_ctx[i]);
|
||||
|
||||
card->msix_enable = 0;
|
||||
pci_disable_msix(pdev);
|
||||
} else {
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"%s(): calling free_irq()\n", __func__);
|
||||
free_irq(card->dev->irq, &card->share_irq_ctx);
|
||||
card->msix_enable = 0;
|
||||
pci_disable_msix(pdev);
|
||||
} else {
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"%s(): calling free_irq()\n", __func__);
|
||||
free_irq(card->dev->irq, &card->share_irq_ctx);
|
||||
|
||||
if (card->msi_enable)
|
||||
pci_disable_msi(pdev);
|
||||
}
|
||||
if (card->msi_enable)
|
||||
pci_disable_msi(pdev);
|
||||
}
|
||||
card->adapter = NULL;
|
||||
}
|
||||
|
||||
/* This function initializes the PCI-E host memory space, WCB rings, etc.
|
||||
@@ -3095,18 +3119,14 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
|
||||
adapter->seq_num = 0;
|
||||
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
|
||||
|
||||
if (card) {
|
||||
if (reg->sleep_cookie)
|
||||
mwifiex_pcie_delete_sleep_cookie_buf(adapter);
|
||||
if (reg->sleep_cookie)
|
||||
mwifiex_pcie_delete_sleep_cookie_buf(adapter);
|
||||
|
||||
mwifiex_pcie_delete_cmdrsp_buf(adapter);
|
||||
mwifiex_pcie_delete_evtbd_ring(adapter);
|
||||
mwifiex_pcie_delete_rxbd_ring(adapter);
|
||||
mwifiex_pcie_delete_txbd_ring(adapter);
|
||||
card->cmdrsp_buf = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
mwifiex_pcie_delete_cmdrsp_buf(adapter);
|
||||
mwifiex_pcie_delete_evtbd_ring(adapter);
|
||||
mwifiex_pcie_delete_rxbd_ring(adapter);
|
||||
mwifiex_pcie_delete_txbd_ring(adapter);
|
||||
card->cmdrsp_buf = NULL;
|
||||
}
|
||||
|
||||
static struct mwifiex_if_ops pcie_ops = {
|
||||
@@ -3140,8 +3160,7 @@ static struct mwifiex_if_ops pcie_ops = {
|
||||
/*
|
||||
* This function initializes the PCIE driver module.
|
||||
*
|
||||
* This initiates the semaphore and registers the device with
|
||||
* PCIE bus.
|
||||
* This registers the device with PCIE bus.
|
||||
*/
|
||||
static int mwifiex_pcie_init_module(void)
|
||||
{
|
||||
@@ -3149,8 +3168,6 @@ static int mwifiex_pcie_init_module(void)
|
||||
|
||||
pr_debug("Marvell PCIe Driver\n");
|
||||
|
||||
sema_init(&add_remove_card_sem, 1);
|
||||
|
||||
/* Clear the flag in case user removes the card. */
|
||||
user_rmmod = 0;
|
||||
|
||||
@@ -3174,9 +3191,6 @@ static int mwifiex_pcie_init_module(void)
|
||||
*/
|
||||
static void mwifiex_pcie_cleanup_module(void)
|
||||
{
|
||||
if (!down_interruptible(&add_remove_card_sem))
|
||||
up(&add_remove_card_sem);
|
||||
|
||||
/* Set the flag as user is removing this module. */
|
||||
user_rmmod = 1;
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#ifndef _MWIFIEX_PCIE_H
|
||||
#define _MWIFIEX_PCIE_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
@@ -345,6 +346,7 @@ struct pcie_service_card {
|
||||
struct pci_dev *dev;
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct mwifiex_pcie_device pcie;
|
||||
struct completion fw_done;
|
||||
|
||||
u8 txbd_flush;
|
||||
u32 txbd_wrptr;
|
||||
|
@@ -1671,6 +1671,10 @@ static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
|
||||
}
|
||||
|
||||
done:
|
||||
/* beacon_ie buffer was allocated in function
|
||||
* mwifiex_fill_new_bss_desc(). Free it now.
|
||||
*/
|
||||
kfree(bss_desc->beacon_buf);
|
||||
kfree(bss_desc);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -49,8 +49,6 @@ static u8 user_rmmod;
|
||||
static struct mwifiex_if_ops sdio_ops;
|
||||
static unsigned long iface_work_flags;
|
||||
|
||||
static struct semaphore add_remove_card_sem;
|
||||
|
||||
static struct memory_type_mapping generic_mem_type_map[] = {
|
||||
{"DUMP", NULL, 0, 0xDD},
|
||||
};
|
||||
@@ -79,59 +77,18 @@ static const struct of_device_id mwifiex_sdio_of_match_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
|
||||
{
|
||||
struct mwifiex_plt_wake_cfg *cfg = priv;
|
||||
|
||||
if (cfg->irq_wifi >= 0) {
|
||||
pr_info("%s: wake by wifi", __func__);
|
||||
cfg->wake_by_wifi = true;
|
||||
disable_irq_nosync(irq);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* This function parse device tree node using mmc subnode devicetree API.
|
||||
* The device node is saved in card->plt_of_node.
|
||||
* if the device tree node exist and include interrupts attributes, this
|
||||
* function will also request platform specific wakeup interrupt.
|
||||
*/
|
||||
static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
|
||||
static int mwifiex_sdio_probe_of(struct device *dev)
|
||||
{
|
||||
struct mwifiex_plt_wake_cfg *cfg;
|
||||
int ret;
|
||||
|
||||
if (!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
|
||||
dev_err(dev, "required compatible string missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
card->plt_of_node = dev->of_node;
|
||||
card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
|
||||
GFP_KERNEL);
|
||||
cfg = card->plt_wake_cfg;
|
||||
if (cfg && card->plt_of_node) {
|
||||
cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
|
||||
if (!cfg->irq_wifi) {
|
||||
dev_dbg(dev,
|
||||
"fail to parse irq_wifi from device tree\n");
|
||||
} else {
|
||||
ret = devm_request_irq(dev, cfg->irq_wifi,
|
||||
mwifiex_wake_irq_wifi,
|
||||
IRQF_TRIGGER_LOW,
|
||||
"wifi_wake", cfg);
|
||||
if (ret) {
|
||||
dev_dbg(dev,
|
||||
"Failed to request irq_wifi %d (%d)\n",
|
||||
cfg->irq_wifi, ret);
|
||||
card->plt_wake_cfg = NULL;
|
||||
return 0;
|
||||
}
|
||||
disable_irq(cfg->irq_wifi);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -152,10 +109,12 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
|
||||
func->vendor, func->device, func->class, func->num);
|
||||
|
||||
card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
|
||||
card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&card->fw_done);
|
||||
|
||||
card->func = func;
|
||||
card->device_id = id;
|
||||
|
||||
@@ -185,20 +144,18 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
|
||||
if (ret) {
|
||||
dev_err(&func->dev, "failed to enable function\n");
|
||||
goto err_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* device tree node parsing and platform specific configuration*/
|
||||
if (func->dev.of_node) {
|
||||
ret = mwifiex_sdio_probe_of(&func->dev, card);
|
||||
if (ret) {
|
||||
dev_err(&func->dev, "SDIO dt node parse failed\n");
|
||||
ret = mwifiex_sdio_probe_of(&func->dev);
|
||||
if (ret)
|
||||
goto err_disable;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
|
||||
MWIFIEX_SDIO);
|
||||
ret = mwifiex_add_card(card, &card->fw_done, &sdio_ops,
|
||||
MWIFIEX_SDIO, &func->dev);
|
||||
if (ret) {
|
||||
dev_err(&func->dev, "add card failed\n");
|
||||
goto err_disable;
|
||||
@@ -210,8 +167,6 @@ err_disable:
|
||||
sdio_claim_host(func);
|
||||
sdio_disable_func(func);
|
||||
sdio_release_host(func);
|
||||
err_free:
|
||||
kfree(card);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -233,15 +188,10 @@ static int mwifiex_sdio_resume(struct device *dev)
|
||||
struct mwifiex_adapter *adapter;
|
||||
mmc_pm_flag_t pm_flag = 0;
|
||||
|
||||
if (func) {
|
||||
pm_flag = sdio_get_host_pm_caps(func);
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("resume: invalid card or adapter\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pr_err("resume: sdio_func is not specified\n");
|
||||
pm_flag = sdio_get_host_pm_caps(func);
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->adapter) {
|
||||
dev_err(dev, "resume: invalid card or adapter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -259,12 +209,7 @@ static int mwifiex_sdio_resume(struct device *dev)
|
||||
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
|
||||
MWIFIEX_SYNC_CMD);
|
||||
|
||||
/* Disable platform specific wakeup interrupt */
|
||||
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
||||
disable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
||||
if (!card->plt_wake_cfg->wake_by_wifi)
|
||||
disable_irq(card->plt_wake_cfg->irq_wifi);
|
||||
}
|
||||
mwifiex_disable_wake(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -285,6 +230,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
|
||||
if (!card)
|
||||
return;
|
||||
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
adapter = card->adapter;
|
||||
if (!adapter || !adapter->priv_num)
|
||||
return;
|
||||
@@ -292,9 +239,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
|
||||
mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
|
||||
|
||||
if (user_rmmod && !adapter->mfg_mode) {
|
||||
if (adapter->is_suspended)
|
||||
mwifiex_sdio_resume(adapter->dev);
|
||||
|
||||
mwifiex_deauthenticate_all(adapter);
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
@@ -302,7 +246,7 @@ mwifiex_sdio_remove(struct sdio_func *func)
|
||||
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
|
||||
}
|
||||
|
||||
mwifiex_remove_card(card->adapter, &add_remove_card_sem);
|
||||
mwifiex_remove_card(adapter);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -323,35 +267,32 @@ static int mwifiex_sdio_suspend(struct device *dev)
|
||||
mmc_pm_flag_t pm_flag = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (func) {
|
||||
pm_flag = sdio_get_host_pm_caps(func);
|
||||
pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
|
||||
sdio_func_id(func), pm_flag);
|
||||
if (!(pm_flag & MMC_PM_KEEP_POWER)) {
|
||||
pr_err("%s: cannot remain alive while host is"
|
||||
" suspended\n", sdio_func_id(func));
|
||||
return -ENOSYS;
|
||||
}
|
||||
pm_flag = sdio_get_host_pm_caps(func);
|
||||
pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
|
||||
sdio_func_id(func), pm_flag);
|
||||
if (!(pm_flag & MMC_PM_KEEP_POWER)) {
|
||||
dev_err(dev, "%s: cannot remain alive while host is"
|
||||
" suspended\n", sdio_func_id(func));
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("suspend: invalid card or adapter\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pr_err("suspend: sdio_func is not specified\n");
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card) {
|
||||
dev_err(dev, "suspend: invalid card\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
adapter = card->adapter;
|
||||
/* Might still be loading firmware */
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
/* Enable platform specific wakeup interrupt */
|
||||
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
||||
card->plt_wake_cfg->wake_by_wifi = false;
|
||||
enable_irq(card->plt_wake_cfg->irq_wifi);
|
||||
enable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
||||
adapter = card->adapter;
|
||||
if (!adapter) {
|
||||
dev_err(dev, "adapter is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mwifiex_enable_wake(adapter);
|
||||
|
||||
/* Enable the Host Sleep */
|
||||
if (!mwifiex_enable_hs(adapter)) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@@ -2066,6 +2007,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
|
||||
struct sdio_mmc_card *card = adapter->card;
|
||||
|
||||
if (adapter->card) {
|
||||
card->adapter = NULL;
|
||||
sdio_claim_host(card->func);
|
||||
sdio_disable_func(card->func);
|
||||
sdio_release_host(card->func);
|
||||
@@ -2098,9 +2040,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
adapter->dev = &func->dev;
|
||||
|
||||
strcpy(adapter->fw_name, card->firmware);
|
||||
if (card->fw_dump_enh) {
|
||||
adapter->mem_type_mapping_tbl = generic_mem_type_map;
|
||||
@@ -2240,8 +2179,6 @@ static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter)
|
||||
kfree(card->mpa_rx.len_arr);
|
||||
kfree(card->mpa_tx.buf);
|
||||
kfree(card->mpa_rx.buf);
|
||||
sdio_set_drvdata(card->func, NULL);
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2291,6 +2228,14 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
|
||||
|
||||
mwifiex_sdio_remove(func);
|
||||
|
||||
/*
|
||||
* Normally, we would let the driver core take care of releasing these.
|
||||
* But we're not letting the driver core handle this one. See above
|
||||
* TODO.
|
||||
*/
|
||||
sdio_set_drvdata(func, NULL);
|
||||
devm_kfree(&func->dev, card);
|
||||
|
||||
/* power cycle the adapter */
|
||||
sdio_claim_host(func);
|
||||
mmc_hw_reset(func->card->host);
|
||||
@@ -2767,14 +2712,11 @@ static struct mwifiex_if_ops sdio_ops = {
|
||||
/*
|
||||
* This function initializes the SDIO driver.
|
||||
*
|
||||
* This initiates the semaphore and registers the device with
|
||||
* SDIO bus.
|
||||
* This registers the device with SDIO bus.
|
||||
*/
|
||||
static int
|
||||
mwifiex_sdio_init_module(void)
|
||||
{
|
||||
sema_init(&add_remove_card_sem, 1);
|
||||
|
||||
/* Clear the flag in case user removes the card. */
|
||||
user_rmmod = 0;
|
||||
|
||||
@@ -2793,9 +2735,6 @@ mwifiex_sdio_init_module(void)
|
||||
static void
|
||||
mwifiex_sdio_cleanup_module(void)
|
||||
{
|
||||
if (!down_interruptible(&add_remove_card_sem))
|
||||
up(&add_remove_card_sem);
|
||||
|
||||
/* Set the flag as user is removing this module. */
|
||||
user_rmmod = 1;
|
||||
cancel_work_sync(&sdio_work);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define _MWIFIEX_SDIO_H
|
||||
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
@@ -154,11 +155,6 @@
|
||||
a->mpa_rx.start_port = 0; \
|
||||
} while (0)
|
||||
|
||||
struct mwifiex_plt_wake_cfg {
|
||||
int irq_wifi;
|
||||
bool wake_by_wifi;
|
||||
};
|
||||
|
||||
/* data structure for SDIO MPA TX */
|
||||
struct mwifiex_sdio_mpa_tx {
|
||||
/* multiport tx aggregation buffer pointer */
|
||||
@@ -242,9 +238,8 @@ struct mwifiex_sdio_card_reg {
|
||||
struct sdio_mmc_card {
|
||||
struct sdio_func *func;
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct device_node *plt_of_node;
|
||||
struct mwifiex_plt_wake_cfg *plt_wake_cfg;
|
||||
|
||||
struct completion fw_done;
|
||||
const char *firmware;
|
||||
const struct mwifiex_sdio_card_reg *reg;
|
||||
u8 max_ports;
|
||||
|
@@ -368,7 +368,10 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
|
||||
u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
|
||||
struct mwifiex_ps_param_in_hs *psparam_tlv = NULL;
|
||||
bool hs_activate = false;
|
||||
u16 size;
|
||||
|
||||
if (!hscfg_param)
|
||||
/* New Activate command */
|
||||
@@ -385,13 +388,14 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
|
||||
memcpy(((u8 *) hs_cfg) +
|
||||
sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
|
||||
adapter->arp_filter, adapter->arp_filter_size);
|
||||
cmd->size = cpu_to_le16
|
||||
(adapter->arp_filter_size +
|
||||
sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
|
||||
+ S_DS_GEN);
|
||||
size = adapter->arp_filter_size +
|
||||
sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
|
||||
+ S_DS_GEN;
|
||||
tlv = (u8 *)hs_cfg
|
||||
+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
|
||||
+ adapter->arp_filter_size;
|
||||
} else {
|
||||
cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct
|
||||
host_cmd_ds_802_11_hs_cfg_enh));
|
||||
size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
|
||||
}
|
||||
if (hs_activate) {
|
||||
hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
|
||||
@@ -401,12 +405,25 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
|
||||
hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
|
||||
hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
|
||||
hs_cfg->params.hs_config.gap = hscfg_param->gap;
|
||||
|
||||
size += sizeof(struct mwifiex_ps_param_in_hs);
|
||||
psparam_tlv = (struct mwifiex_ps_param_in_hs *)tlv;
|
||||
psparam_tlv->header.type =
|
||||
cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS);
|
||||
psparam_tlv->header.len =
|
||||
cpu_to_le16(sizeof(struct mwifiex_ps_param_in_hs)
|
||||
- sizeof(struct mwifiex_ie_types_header));
|
||||
psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL);
|
||||
psparam_tlv->hs_inact_timeout =
|
||||
cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT);
|
||||
|
||||
mwifiex_dbg(adapter, CMD,
|
||||
"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
|
||||
hs_cfg->params.hs_config.conditions,
|
||||
hs_cfg->params.hs_config.gpio,
|
||||
hs_cfg->params.hs_config.gap);
|
||||
}
|
||||
cmd->size = cpu_to_le16(size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2218,9 +2235,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
|
||||
* The cal-data can be read from device tree and/or
|
||||
* a configuration file and downloaded to firmware.
|
||||
*/
|
||||
if (priv->adapter->iface_type == MWIFIEX_SDIO &&
|
||||
adapter->dev->of_node) {
|
||||
adapter->dt_node = adapter->dev->of_node;
|
||||
if (adapter->dt_node) {
|
||||
if (of_property_read_u32(adapter->dt_node,
|
||||
"marvell,wakeup-pin",
|
||||
&data) == 0) {
|
||||
@@ -2228,19 +2243,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
|
||||
adapter->hs_cfg.gpio = data;
|
||||
}
|
||||
|
||||
ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
|
||||
"marvell,caldata");
|
||||
if (ret)
|
||||
return -1;
|
||||
mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
|
||||
"marvell,caldata");
|
||||
}
|
||||
|
||||
if (adapter->cal_data) {
|
||||
ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL,
|
||||
true);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
if (adapter->cal_data)
|
||||
mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL, true);
|
||||
|
||||
/* Read MAC address from HW */
|
||||
ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
|
||||
|
@@ -404,7 +404,7 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
const u8 *vendor_ie;
|
||||
struct ieee_types_header *wmm_ie;
|
||||
const u8 *wmm_ie;
|
||||
u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
|
||||
|
||||
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
|
||||
@@ -412,9 +412,9 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
||||
params->beacon.tail,
|
||||
params->beacon.tail_len);
|
||||
if (vendor_ie) {
|
||||
wmm_ie = (struct ieee_types_header *)vendor_ie;
|
||||
memcpy(&bss_cfg->wmm_info, wmm_ie + 1,
|
||||
sizeof(bss_cfg->wmm_info));
|
||||
wmm_ie = vendor_ie;
|
||||
memcpy(&bss_cfg->wmm_info, wmm_ie +
|
||||
sizeof(struct ieee_types_header), *(wmm_ie + 1));
|
||||
priv->wmm_enabled = 1;
|
||||
} else {
|
||||
memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
|
||||
|
@@ -24,7 +24,6 @@
|
||||
|
||||
static u8 user_rmmod;
|
||||
static struct mwifiex_if_ops usb_ops;
|
||||
static struct semaphore add_remove_card_sem;
|
||||
|
||||
static struct usb_device_id mwifiex_usb_table[] = {
|
||||
/* 8766 */
|
||||
@@ -382,10 +381,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
|
||||
struct usb_card_rec *card;
|
||||
u16 id_vendor, id_product, bcd_device, bcd_usb;
|
||||
|
||||
card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
|
||||
card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&card->fw_done);
|
||||
|
||||
id_vendor = le16_to_cpu(udev->descriptor.idVendor);
|
||||
id_product = le16_to_cpu(udev->descriptor.idProduct);
|
||||
bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
|
||||
@@ -475,12 +476,11 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
|
||||
|
||||
usb_set_intfdata(intf, card);
|
||||
|
||||
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
|
||||
MWIFIEX_USB);
|
||||
ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
|
||||
MWIFIEX_USB, &card->udev->dev);
|
||||
if (ret) {
|
||||
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
|
||||
usb_reset_device(udev);
|
||||
kfree(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -503,17 +503,27 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
struct usb_tx_data_port *port;
|
||||
int i, j;
|
||||
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("%s: card or card->adapter is NULL\n", __func__);
|
||||
/* Might still be loading firmware */
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
adapter = card->adapter;
|
||||
if (!adapter) {
|
||||
dev_err(&intf->dev, "card is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
adapter = card->adapter;
|
||||
|
||||
if (unlikely(adapter->is_suspended))
|
||||
mwifiex_dbg(adapter, WARN,
|
||||
"Device already suspended\n");
|
||||
|
||||
mwifiex_enable_hs(adapter);
|
||||
/* Enable the Host Sleep */
|
||||
if (!mwifiex_enable_hs(adapter)) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"cmd: failed to suspend\n");
|
||||
adapter->hs_enabling = false;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
/* 'is_suspended' flag indicates device is suspended.
|
||||
* It must be set here before the usb_kill_urb() calls. Reason
|
||||
@@ -559,8 +569,9 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
|
||||
struct mwifiex_adapter *adapter;
|
||||
int i;
|
||||
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("%s: card or card->adapter is NULL\n", __func__);
|
||||
if (!card->adapter) {
|
||||
dev_err(&intf->dev, "%s: card->adapter is NULL\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
adapter = card->adapter;
|
||||
@@ -602,21 +613,13 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
|
||||
struct usb_card_rec *card = usb_get_intfdata(intf);
|
||||
struct mwifiex_adapter *adapter;
|
||||
|
||||
if (!card || !card->adapter) {
|
||||
pr_err("%s: card or card->adapter is NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
wait_for_completion(&card->fw_done);
|
||||
|
||||
adapter = card->adapter;
|
||||
if (!adapter->priv_num)
|
||||
if (!adapter || !adapter->priv_num)
|
||||
return;
|
||||
|
||||
if (user_rmmod && !adapter->mfg_mode) {
|
||||
#ifdef CONFIG_PM
|
||||
if (adapter->is_suspended)
|
||||
mwifiex_usb_resume(intf);
|
||||
#endif
|
||||
|
||||
mwifiex_deauthenticate_all(adapter);
|
||||
|
||||
mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
|
||||
@@ -628,13 +631,9 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
|
||||
|
||||
mwifiex_dbg(adapter, FATAL,
|
||||
"%s: removing card\n", __func__);
|
||||
mwifiex_remove_card(adapter, &add_remove_card_sem);
|
||||
mwifiex_remove_card(adapter);
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(intf));
|
||||
kfree(card);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct usb_driver mwifiex_usb_driver = {
|
||||
@@ -932,7 +931,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
|
||||
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
|
||||
|
||||
card->adapter = adapter;
|
||||
adapter->dev = &card->udev->dev;
|
||||
|
||||
switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
|
||||
case USB8997_PID_1:
|
||||
@@ -1206,8 +1204,7 @@ static struct mwifiex_if_ops usb_ops = {
|
||||
|
||||
/* This function initializes the USB driver module.
|
||||
*
|
||||
* This initiates the semaphore and registers the device with
|
||||
* USB bus.
|
||||
* This registers the device with USB bus.
|
||||
*/
|
||||
static int mwifiex_usb_init_module(void)
|
||||
{
|
||||
@@ -1215,8 +1212,6 @@ static int mwifiex_usb_init_module(void)
|
||||
|
||||
pr_debug("Marvell USB8797 Driver\n");
|
||||
|
||||
sema_init(&add_remove_card_sem, 1);
|
||||
|
||||
ret = usb_register(&mwifiex_usb_driver);
|
||||
if (ret)
|
||||
pr_err("Driver register failed!\n");
|
||||
@@ -1236,9 +1231,6 @@ static int mwifiex_usb_init_module(void)
|
||||
*/
|
||||
static void mwifiex_usb_cleanup_module(void)
|
||||
{
|
||||
if (!down_interruptible(&add_remove_card_sem))
|
||||
up(&add_remove_card_sem);
|
||||
|
||||
/* set the flag as user is removing this module */
|
||||
user_rmmod = 1;
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#ifndef _MWIFIEX_USB_H
|
||||
#define _MWIFIEX_USB_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define USB8XXX_VID 0x1286
|
||||
@@ -75,6 +76,7 @@ struct usb_card_rec {
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *intf;
|
||||
struct completion fw_done;
|
||||
u8 rx_cmd_ep;
|
||||
struct urb_context rx_cmd;
|
||||
atomic_t rx_cmd_urb_pending;
|
||||
|
@@ -503,8 +503,10 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct sk_buff *skb, *tmp;
|
||||
|
||||
skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
|
||||
skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
|
||||
skb_unlink(skb, &ra_list->skb_head);
|
||||
mwifiex_write_data_complete(adapter, skb, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -600,11 +602,15 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
|
||||
priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
|
||||
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
|
||||
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
|
||||
skb_unlink(skb, &priv->tdls_txq);
|
||||
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
|
||||
}
|
||||
|
||||
skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
|
||||
skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
|
||||
skb_unlink(skb, &priv->bypass_txq);
|
||||
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
|
||||
}
|
||||
atomic_set(&priv->adapter->bypass_tx_pending, 0);
|
||||
|
||||
idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
|
||||
@@ -1099,6 +1105,7 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
|
||||
&adapter->bss_prio_tbl[j].bss_prio_head,
|
||||
list) {
|
||||
|
||||
try_again:
|
||||
priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
|
||||
|
||||
if (((priv_tmp->bss_mode != NL80211_IFTYPE_ADHOC) &&
|
||||
@@ -1134,8 +1141,18 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
|
||||
ra_list_spinlock,
|
||||
flags_ra);
|
||||
}
|
||||
}
|
||||
|
||||
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) != 0) {
|
||||
atomic_set(&priv_tmp->wmm.highest_queued_prio,
|
||||
HIGH_PRIO_TID);
|
||||
/* Iterate current private once more, since
|
||||
* there still exist packets in data queue
|
||||
*/
|
||||
goto try_again;
|
||||
} else
|
||||
atomic_set(&priv_tmp->wmm.highest_queued_prio,
|
||||
NO_PKT_PRIO_TID);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1328,9 +1345,11 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
||||
skb = skb_dequeue(&ptr->skb_head);
|
||||
|
||||
if (adapter->data_sent || adapter->tx_lock_flag) {
|
||||
ptr->total_pkt_count--;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
skb_queue_tail(&adapter->tx_data_q, skb);
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
atomic_inc(&adapter->tx_queued);
|
||||
return;
|
||||
}
|
||||
@@ -1388,6 +1407,10 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
||||
if (ret != -EBUSY) {
|
||||
mwifiex_rotate_priolists(priv, ptr, ptr_index);
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
ptr->total_pkt_count--;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user