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:
David S. Miller
2016-11-27 20:26:59 -05:00
189 changed files with 1607 additions and 1152 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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" : "");
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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));

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}