* Re: question about ieee80211_tx.c (fwd)
From: Zhu Yi @ 2009-08-18 1:13 UTC (permalink / raw)
To: Gábor Stefanik
Cc: Julia Lawall, linux-wireless@vger.kernel.org, gregkh@suse.de
In-Reply-To: <69e28c910908170450l65d493dbnb1d2e8f14d29dadc@mail.gmail.com>
On Mon, 2009-08-17 at 19:50 +0800, Gábor Stefanik wrote:
> On Mon, Aug 17, 2009 at 10:03 AM, Julia Lawall<julia@diku.dk> wrote:
> > The files ieee80211_tx.c in the directories
> > drivers/staging/rtl8192su/ieee80211 and
> drivers/staging/rtl8192e/ieee80211
> > both contain the following code in the function
> > ieee80211_query_protectionmode:
> >
> > if (ieee->mode == IW_MODE_MASTER)
> > goto NO_PROTECTION;
> >
> > Elsewhere in these files when there is a comparison against an
> IW_MODE
> > value, the field that is compared is iw_mode. Should that be the
> case
> > here as well?
> >
> > thanks,
> > julia
>
> I don't know; rtl8192su & rtl8192e use a modified version of the
> libipw stack, rather than the mac80211 stack found behind non-staging
> drivers.
This is clearly a bug. The question is: who is maintaining this driver
and why it doesn't use/extend ieee80211/libipw?
Thanks,
-yi
^ permalink raw reply
* Re: [PATCH] cfg80211: report userspace SME connected event properly
From: Zhu Yi @ 2009-08-18 1:34 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1250504534.15103.0.camel@johannes.local>
On Mon, 2009-08-17 at 18:22 +0800, Johannes Berg wrote:
> Instead of hacking the event reporting into the
> __cfg80211_connect_result() function which is also
> invoked by others, set up things correctly and then
> invoke that function, so that it can do more sanity
> checking.
>
> Also, it is currently not possible to get a ROAMED
> event from the userspace SME anyway since we send
> out a DISCONNECTED event when it disassociates and
> then a new CONNECTED event on the next association.
>
> Thanks to Zhu Yi for pointing out that the code is
> somewhat convoluted and doesn't warn when it should.
>
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
This makes it clear cfg80211_connect_result() shouldn't be called in !
CFG80211_SME_CONNECTING state. Thanks!
-yi
^ permalink raw reply
* Re: question about ieee80211_tx.c (fwd)
From: Greg KH @ 2009-08-18 1:35 UTC (permalink / raw)
To: Zhu Yi; +Cc: Gábor Stefanik, Julia Lawall, linux-wireless@vger.kernel.org
In-Reply-To: <1250558021.9651.35.camel@debian>
On Tue, Aug 18, 2009 at 09:13:41AM +0800, Zhu Yi wrote:
> On Mon, 2009-08-17 at 19:50 +0800, Gábor Stefanik wrote:
> > On Mon, Aug 17, 2009 at 10:03 AM, Julia Lawall<julia@diku.dk> wrote:
> > > The files ieee80211_tx.c in the directories
> > > drivers/staging/rtl8192su/ieee80211 and
> > drivers/staging/rtl8192e/ieee80211
> > > both contain the following code in the function
> > > ieee80211_query_protectionmode:
> > >
> > > if (ieee->mode == IW_MODE_MASTER)
> > > goto NO_PROTECTION;
> > >
> > > Elsewhere in these files when there is a comparison against an
> > IW_MODE
> > > value, the field that is compared is iw_mode. Should that be the
> > case
> > > here as well?
> > >
> > > thanks,
> > > julia
> >
> > I don't know; rtl8192su & rtl8192e use a modified version of the
> > libipw stack, rather than the mac80211 stack found behind non-staging
> > drivers.
>
> This is clearly a bug. The question is: who is maintaining this driver
> and why it doesn't use/extend ieee80211/libipw?
I maintain it, and I am working to convert it to use the existing
ieee80211 stack that is in the kernel. Remember, these are drivers in
the staging tree, they are usually "crap" :)
thanks,
greg k-h
^ permalink raw reply
* [ANN] wireless-regdb: master-2009-08-17
From: wireless @ 2009-08-18 3:10 UTC (permalink / raw)
To: linux-wireless
A new release of wireless-regdb (master-2009-08-17) is available at:
http://wireless.kernel.org/download/wireless-regdb/wireless-regdb-2009.08.17.tar.bz2
SHA1 sum: ab87bfd0b2f26a8e1213da16ce2add47c831ac66
For your convenience the individual regulatory.bin file can be downloaded from:
http://wireless.kernel.org/download/wireless-regdb/regulatory.bins/2009.08.17-regulatory.bin
SHA1 sum fb30b37c3e838f8d71f66a435febfbbef692504f
Here is the short log of the changes included in this
release:
Kel Modderman - wireless-regdb: manual page section mismatch
^ permalink raw reply
* [PATCH] wl1251: halt the embedded CPU before loading firmware
From: Bob Copeland @ 2009-08-18 3:33 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
After initial power-up, the embedded cpu is usually halted. However,
if we down the interface and only do a soft reset before bringing
the interface back up, it will still be running and the firmware
loading code will bail out. This change halts the CPU before loading
the firmware, enabling a second call to wl1251_boot() to succeed
without a hard reset.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
---
Hi Kalle,
Thoughts on this? It fixes my remaining issue with warm card reset.
I think Android code does this in the firmware loader:
http://android.git.kernel.org/?p=platform/system/wlan/ti.git;a=blob;f=sta_dk_4_0_4_32/common/src/TNETW_Driver/FW_Transfer/HwInit/HwInit.c;h=e5cc2becdd2b9010903598fc56574776f6aeec8d;hb=HEAD#l291
drivers/net/wireless/wl12xx/wl1251_boot.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 592c3b5..452d748 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl)
int ret = 0, minor_minor_e2_ver;
u32 tmp, boot_data;
+ /* halt embedded ARM CPU while loading firmware */
+ wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
+
ret = wl1251_boot_soft_reset(wl);
if (ret < 0)
goto out;
--
1.6.2.5
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply related
* [PATCH 00/29] mwl8k update to version 0.10
From: Lennert Buytenhek @ 2009-08-18 3:49 UTC (permalink / raw)
To: linville, linux-wireless
In this series, various mwl8k coding style cleanups, removal of the
usage of radio_enabled, some minor bug fixes, optimisations, and
removal of most of the driver's workqueue use. (Against latest
wireless-testing.)
^ permalink raw reply
* [PATCH 01/29] mwl8k: remove various unused struct members and defines
From: Lennert Buytenhek @ 2009-08-18 3:50 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 73 ++++-------------------------------------
1 files changed, 8 insertions(+), 65 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 8a6d3af..6f78fae 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28
#define MWL8K_H2A_INT_DUMMY (1 << 20)
#define MWL8K_H2A_INT_RESET (1 << 15)
-#define MWL8K_H2A_INT_PS (1 << 2)
#define MWL8K_H2A_INT_DOORBELL (1 << 1)
#define MWL8K_H2A_INT_PPA_READY (1 << 0)
@@ -161,10 +160,8 @@ struct mwl8k_priv {
/* lock held over TX and TX reap */
spinlock_t tx_lock;
- u32 int_mask;
struct ieee80211_vif *vif;
- struct list_head vif_list;
struct ieee80211_channel *current_channel;
@@ -173,10 +170,8 @@ struct mwl8k_priv {
dma_addr_t cookie_dma;
u16 num_mcaddrs;
- u16 region_code;
u8 hw_rev;
__le32 fw_rev;
- u32 wep_enabled;
/*
* Running count of TX packets in flight, to avoid
@@ -226,8 +221,6 @@ struct mwl8k_priv {
/* Per interface specific private data */
struct mwl8k_vif {
- struct list_head node;
-
/* backpointer to parent config block */
struct mwl8k_priv *priv;
@@ -247,18 +240,11 @@ struct mwl8k_vif {
/* number of supported legacy rates */
u8 legacy_nrates;
- /* Number of supported MCS rates. Work in progress */
- u8 mcs_nrates;
-
/* Index into station database.Returned by update_sta_db call */
u8 peer_id;
/* Non AMPDU sequence number assigned by driver */
u16 seqno;
-
- /* Note:There is no channel info,
- * refer to the master channel info in priv
- */
};
#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
@@ -681,11 +667,9 @@ struct ewc_ht_info {
/* Peer Entry flags - used to define the type of the peer node */
#define MWL8K_PEER_TYPE_ACCESSPOINT 2
-#define MWL8K_PEER_TYPE_ADHOC_STATION 4
#define MWL8K_IEEE_LEGACY_DATA_RATES 12
#define MWL8K_MCS_BITMAP_SIZE 16
-#define pad_size 16
struct peer_capability_info {
/* Peer type - AP vs. STA. */
@@ -707,7 +691,7 @@ struct peer_capability_info {
/* HT rate table. Intersection of our rates and peer rates. */
__u8 ht_rates[MWL8K_MCS_BITMAP_SIZE];
- __u8 pad[pad_size];
+ __u8 pad[16];
/* If set, interoperability mode, no proprietary extensions. */
__u8 interop;
@@ -717,15 +701,6 @@ struct peer_capability_info {
} __attribute__((packed));
/* Inline functions to manipulate QoS field in data descriptor. */
-static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid)
-{
- u16 val_mask = 0x000f;
- u16 qos_mask = ~val_mask;
-
- /* TID bits 0-3 */
- return (qos & qos_mask) | (tid & val_mask);
-}
-
static inline u16 mwl8k_qos_setbit_eosp(u16 qos)
{
u16 val_mask = 1 << 4;
@@ -826,9 +801,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
/*
* Packet reception.
*/
-#define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30
#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02
-#define MWL8K_RX_CTRL_AMPDU 0x01
struct mwl8k_rx_desc {
__le16 pkt_len;
@@ -1073,8 +1046,6 @@ enum {
/* Transmit packet ACK policy */
#define MWL8K_TXD_ACK_POLICY_NORMAL 0
-#define MWL8K_TXD_ACK_POLICY_NONE 1
-#define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2
#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3
#define GET_TXQ(_ac) (\
@@ -1083,20 +1054,11 @@ enum {
((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \
MWL8K_WME_AC_BE)
-#define MWL8K_TXD_STATUS_IDLE 0x00000000
-#define MWL8K_TXD_STATUS_USED 0x00000001
#define MWL8K_TXD_STATUS_OK 0x00000001
#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008
-#define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010
-#define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020
-#define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040
-#define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080
-#define MWL8K_TXD_STATUS_HOST_CMD 0x40000000
#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000
-#define MWL8K_TXD_SOFTSTALE 0x80
-#define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01
struct mwl8k_tx_desc {
__le32 status;
@@ -1279,12 +1241,10 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
return 0;
}
-#define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \
- MWL8K_TXD_STATUS_OK_RETRY | \
- MWL8K_TXD_STATUS_OK_MORE_RETRY)
-#define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK)
-#define MWL8K_TXD_FAIL_RETRY(stat) \
- ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT))
+#define MWL8K_TXD_SUCCESS(status) \
+ ((status) & (MWL8K_TXD_STATUS_OK | \
+ MWL8K_TXD_STATUS_OK_RETRY | \
+ MWL8K_TXD_STATUS_OK_MORE_RETRY))
static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
{
@@ -1671,7 +1631,6 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
priv->fw_rev = le32_to_cpu(cmd->fw_rev);
priv->hw_rev = cmd->hw_rev;
- priv->region_code = le16_to_cpu(cmd->region_code);
}
kfree(cmd);
@@ -2150,7 +2109,6 @@ struct mwl8k_cmd_set_edca_params {
__u8 txq;
} __attribute__((packed));
-#define MWL8K_GET_EDCA_ALL 0
#define MWL8K_SET_EDCA_CW 0x01
#define MWL8K_SET_EDCA_TXOP 0x02
#define MWL8K_SET_EDCA_AIFS 0x04
@@ -2323,18 +2281,12 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
/*
* CMD_SET_AID.
*/
-#define IEEE80211_OPMODE_DISABLED 0x00
-#define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01
-#define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02
-#define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03
-
#define MWL8K_RATE_INDEX_MAX_ARRAY 14
#define MWL8K_FRAME_PROT_DISABLED 0x00
#define MWL8K_FRAME_PROT_11G 0x07
#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
-#define MWL8K_FRAME_PROT_MASK 0x07
struct mwl8k_cmd_update_set_aid {
struct mwl8k_cmd_pkt header;
@@ -2439,10 +2391,6 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw,
*/
#define MWL8K_RATE_TABLE_SIZE 8
#define MWL8K_UCAST_RATE 0
-#define MWL8K_MCAST_RATE 1
-#define MWL8K_BCAST_RATE 2
-
-#define MWL8K_USE_FIXED_RATE 0x0001
#define MWL8K_USE_AUTO_RATE 0x0002
struct mwl8k_rate_entry {
@@ -2535,7 +2483,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- status &= priv->int_mask;
if (!status)
return IRQ_NONE;
@@ -2873,7 +2820,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
}
/* Enable interrupts */
- iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (worker == NULL) {
@@ -3519,7 +3466,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv->hostcmd_wait = NULL;
priv->tx_wait = NULL;
priv->inconfig = false;
- priv->wep_enabled = 0;
priv->wmm_mode = false;
priv->pending_tx_pkts = 0;
strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
@@ -3601,8 +3547,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
}
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- priv->int_mask = 0;
- iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+ iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
@@ -3639,9 +3584,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
* commands use interrupts and avoids polling. Disable
* interrupts when done.
*/
- priv->int_mask |= MWL8K_A2H_EVENTS;
-
- iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
/* Get config data, mac addrs etc */
rc = mwl8k_cmd_get_hw_spec(hw);
--
1.5.6.4
^ permalink raw reply related
* [PATCH 02/29] mwl8k: s/IEEE80211_ADDR_LEN/ETH_ALEN/g
From: Lennert Buytenhek @ 2009-08-18 3:50 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 47 +++++++++++++++++++----------------------
1 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 6f78fae..55abf27 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -38,8 +38,6 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = {
};
MODULE_DEVICE_TABLE(pci, mwl8k_table);
-#define IEEE80211_ADDR_LEN ETH_ALEN
-
/* Register definitions */
#define MWL8K_HIU_GEN_PTR 0x00000c10
#define MWL8K_MODE_STA 0x0000005a
@@ -199,7 +197,7 @@ struct mwl8k_priv {
/* XXX need to convert this to handle multiple interfaces */
bool capture_beacon;
- u8 capture_bssid[IEEE80211_ADDR_LEN];
+ u8 capture_bssid[ETH_ALEN];
struct sk_buff *beacon_skb;
/*
@@ -228,8 +226,8 @@ struct mwl8k_vif {
struct ieee80211_bss_conf bss_info;
/* BSSID of AP or IBSS */
- u8 bssid[IEEE80211_ADDR_LEN];
- u8 mac_addr[IEEE80211_ADDR_LEN];
+ u8 bssid[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
/*
* Subset of supported legacy rates.
@@ -785,7 +783,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
memmove(&tr->wh, wh, hdrlen);
/* Clear addr4 */
- memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN);
+ memset(tr->wh.addr4, 0, ETH_ALEN);
/*
* Firmware length is the length of the fully formed "802.11
@@ -952,7 +950,7 @@ static inline void mwl8k_save_beacon(struct mwl8k_priv *priv,
struct sk_buff *skb)
{
priv->capture_beacon = false;
- memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN);
+ memset(priv->capture_bssid, 0, ETH_ALEN);
/*
* Use GFP_ATOMIC as rxq_process is called from
@@ -1067,7 +1065,7 @@ struct mwl8k_tx_desc {
__le16 qos_control;
__le32 pkt_phys_addr;
__le16 pkt_len;
- __u8 dest_MAC_addr[IEEE80211_ADDR_LEN];
+ __u8 dest_MAC_addr[ETH_ALEN];
__le32 next_tx_desc_phys_addr;
__le32 reserved;
__le16 rate_info;
@@ -1587,7 +1585,7 @@ struct mwl8k_cmd_get_hw_spec {
__u8 hw_rev;
__u8 host_interface;
__le16 num_mcaddrs;
- __u8 perm_addr[IEEE80211_ADDR_LEN];
+ __u8 perm_addr[ETH_ALEN];
__le16 region_code;
__le32 fw_rev;
__le32 ps_cookie;
@@ -1644,7 +1642,7 @@ struct mwl8k_cmd_mac_multicast_adr {
struct mwl8k_cmd_pkt header;
__le16 action;
__le16 numaddr;
- __u8 addr[1][IEEE80211_ADDR_LEN];
+ __u8 addr[1][ETH_ALEN];
};
#define MWL8K_ENABLE_RX_MULTICAST 0x000F
@@ -1655,7 +1653,7 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
struct mwl8k_cmd_mac_multicast_adr *cmd;
int index = 0;
int rc;
- int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN);
+ int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN);
cmd = kzalloc(size, GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
@@ -1665,11 +1663,11 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
cmd->numaddr = cpu_to_le16(mc_count);
while ((index < mc_count) && mclist) {
- if (mclist->da_addrlen != IEEE80211_ADDR_LEN) {
+ if (mclist->da_addrlen != ETH_ALEN) {
rc = -EINVAL;
goto mwl8k_cmd_mac_multicast_adr_exit;
}
- memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN);
+ memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN);
index++;
mclist = mclist->next;
}
@@ -1848,11 +1846,11 @@ static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
struct mwl8k_cmd_set_post_scan {
struct mwl8k_cmd_pkt header;
__le32 isibss;
- __u8 bssid[IEEE80211_ADDR_LEN];
+ __u8 bssid[ETH_ALEN];
} __attribute__((packed));
static int
-mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN])
+mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN])
{
struct mwl8k_cmd_set_post_scan *cmd;
int rc;
@@ -1864,7 +1862,7 @@ mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN])
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->isibss = 0;
- memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN);
+ memcpy(cmd->bssid, mac, ETH_ALEN);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2216,7 +2214,7 @@ struct mwl8k_cmd_update_sta_db {
__le32 action;
/* Peer MAC address */
- __u8 peer_addr[IEEE80211_ADDR_LEN];
+ __u8 peer_addr[ETH_ALEN];
__le32 reserved;
@@ -2244,7 +2242,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
cmd->action = cpu_to_le32(action);
peer_info = &cmd->peer_info;
- memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN);
+ memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN);
switch (action) {
case MWL8K_STA_DB_ADD_ENTRY:
@@ -2293,7 +2291,7 @@ struct mwl8k_cmd_update_set_aid {
__le16 aid;
/* AP's MAC address (BSSID) */
- __u8 bssid[IEEE80211_ADDR_LEN];
+ __u8 bssid[ETH_ALEN];
__le16 protection_mode;
__u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
} __attribute__((packed));
@@ -2317,7 +2315,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->aid = cpu_to_le16(info->aid);
- memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN);
+ memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN);
prot_mode = MWL8K_FRAME_PROT_DISABLED;
@@ -2934,7 +2932,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
/* Save the mac address */
- memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN);
+ memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN);
/* Back pointer to parent config block */
mwl8k_vif->priv = priv;
@@ -3098,14 +3096,13 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
* Finalize the join. Tell rx handler to process
* next beacon from our BSSID.
*/
- memcpy(priv->capture_bssid,
- mwl8k_vif->bssid, IEEE80211_ADDR_LEN);
+ memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN);
priv->capture_beacon = true;
} else {
mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY);
memset(&mwl8k_vif->bss_info, 0,
sizeof(struct ieee80211_bss_conf));
- memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN);
+ memset(mwl8k_vif->bssid, 0, ETH_ALEN);
}
mwl8k_bss_info_changed_exit:
@@ -3124,7 +3121,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
int rc;
if (changed & BSS_CHANGED_BSSID)
- memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN);
+ memcpy(mv_vif->bssid, info->bssid, ETH_ALEN);
if ((changed & BSS_CHANGED_ASSOC) == 0)
return;
--
1.5.6.4
^ permalink raw reply related
* [PATCH 03/29] mwl8k: sort firmware command list by opcode, and trim unused commands
From: Lennert Buytenhek @ 2009-08-18 3:51 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 42 +++++++++++++++++++-----------------------
1 files changed, 19 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 55abf27..9fab145 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -307,25 +307,23 @@ static const struct ieee80211_rate mwl8k_rates[] = {
#define MWL8K_CMD_GET_HW_SPEC 0x0003
#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010
#define MWL8K_CMD_GET_STAT 0x0014
-#define MWL8K_CMD_RADIO_CONTROL 0x001C
-#define MWL8K_CMD_RF_TX_POWER 0x001E
+#define MWL8K_CMD_RADIO_CONTROL 0x001c
+#define MWL8K_CMD_RF_TX_POWER 0x001e
#define MWL8K_CMD_SET_PRE_SCAN 0x0107
#define MWL8K_CMD_SET_POST_SCAN 0x0108
-#define MWL8K_CMD_SET_RF_CHANNEL 0x010A
+#define MWL8K_CMD_SET_RF_CHANNEL 0x010a
+#define MWL8K_CMD_SET_AID 0x010d
+#define MWL8K_CMD_SET_RATE 0x0110
+#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111
+#define MWL8K_CMD_RTS_THRESHOLD 0x0113
#define MWL8K_CMD_SET_SLOT 0x0114
+#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115
+#define MWL8K_CMD_SET_WMM_MODE 0x0123
#define MWL8K_CMD_MIMO_CONFIG 0x0125
+#define MWL8K_CMD_USE_FIXED_RATE 0x0126
#define MWL8K_CMD_ENABLE_SNIFFER 0x0150
-#define MWL8K_CMD_SET_WMM_MODE 0x0123
-#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115
-#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111
-#define MWL8K_CMD_UPDATE_STADB 0x1123
#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
-#define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129
-#define MWL8K_CMD_SET_AID 0x010d
-#define MWL8K_CMD_SET_RATE 0x0110
-#define MWL8K_CMD_USE_FIXED_RATE 0x0126
-#define MWL8K_CMD_RTS_THRESHOLD 0x0113
-#define MWL8K_CMD_ENCRYPTION 0x1122
+#define MWL8K_CMD_UPDATE_STADB 0x1123
static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
{
@@ -343,20 +341,18 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(SET_PRE_SCAN);
MWL8K_CMDNAME(SET_POST_SCAN);
MWL8K_CMDNAME(SET_RF_CHANNEL);
+ MWL8K_CMDNAME(SET_AID);
+ MWL8K_CMDNAME(SET_RATE);
+ MWL8K_CMDNAME(SET_FINALIZE_JOIN);
+ MWL8K_CMDNAME(RTS_THRESHOLD);
MWL8K_CMDNAME(SET_SLOT);
+ MWL8K_CMDNAME(SET_EDCA_PARAMS);
+ MWL8K_CMDNAME(SET_WMM_MODE);
MWL8K_CMDNAME(MIMO_CONFIG);
+ MWL8K_CMDNAME(USE_FIXED_RATE);
MWL8K_CMDNAME(ENABLE_SNIFFER);
- MWL8K_CMDNAME(SET_WMM_MODE);
- MWL8K_CMDNAME(SET_EDCA_PARAMS);
- MWL8K_CMDNAME(SET_FINALIZE_JOIN);
- MWL8K_CMDNAME(UPDATE_STADB);
MWL8K_CMDNAME(SET_RATEADAPT_MODE);
- MWL8K_CMDNAME(SET_LINKADAPT_MODE);
- MWL8K_CMDNAME(SET_AID);
- MWL8K_CMDNAME(SET_RATE);
- MWL8K_CMDNAME(USE_FIXED_RATE);
- MWL8K_CMDNAME(RTS_THRESHOLD);
- MWL8K_CMDNAME(ENCRYPTION);
+ MWL8K_CMDNAME(UPDATE_STADB);
default:
snprintf(buf, bufsize, "0x%x", cmd);
}
--
1.5.6.4
^ permalink raw reply related
* [PATCH 04/29] mwl8k: various coding style cleanups
From: Lennert Buytenhek @ 2009-08-18 3:51 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 130 ++++++++++++++++++-----------------------
1 files changed, 57 insertions(+), 73 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9fab145..a3b0e19 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1,5 +1,6 @@
/*
- * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards
+ * drivers/net/wireless/mwl8k.c
+ * Driver for Marvell TOPDOG 802.11 Wireless cards
*
* Copyright (C) 2008 Marvell Semiconductor Inc.
*
@@ -40,12 +41,12 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
/* Register definitions */
#define MWL8K_HIU_GEN_PTR 0x00000c10
-#define MWL8K_MODE_STA 0x0000005a
-#define MWL8K_MODE_AP 0x000000a5
+#define MWL8K_MODE_STA 0x0000005a
+#define MWL8K_MODE_AP 0x000000a5
#define MWL8K_HIU_INT_CODE 0x00000c14
-#define MWL8K_FWSTA_READY 0xf0f1f2f4
-#define MWL8K_FWAP_READY 0xf1f2f4a5
-#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005
+#define MWL8K_FWSTA_READY 0xf0f1f2f4
+#define MWL8K_FWAP_READY 0xf1f2f4a5
+#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005
#define MWL8K_HIU_SCRATCH 0x00000c40
/* Host->device communications */
@@ -54,10 +55,10 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20
#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24
#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28
-#define MWL8K_H2A_INT_DUMMY (1 << 20)
-#define MWL8K_H2A_INT_RESET (1 << 15)
-#define MWL8K_H2A_INT_DOORBELL (1 << 1)
-#define MWL8K_H2A_INT_PPA_READY (1 << 0)
+#define MWL8K_H2A_INT_DUMMY (1 << 20)
+#define MWL8K_H2A_INT_RESET (1 << 15)
+#define MWL8K_H2A_INT_DOORBELL (1 << 1)
+#define MWL8K_H2A_INT_PPA_READY (1 << 0)
/* Device->host communications */
#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c
@@ -65,16 +66,16 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34
#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38
#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c
-#define MWL8K_A2H_INT_DUMMY (1 << 20)
-#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11)
-#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10)
-#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7)
-#define MWL8K_A2H_INT_RADIO_ON (1 << 6)
-#define MWL8K_A2H_INT_RADIO_OFF (1 << 5)
-#define MWL8K_A2H_INT_MAC_EVENT (1 << 3)
-#define MWL8K_A2H_INT_OPC_DONE (1 << 2)
-#define MWL8K_A2H_INT_RX_READY (1 << 1)
-#define MWL8K_A2H_INT_TX_DONE (1 << 0)
+#define MWL8K_A2H_INT_DUMMY (1 << 20)
+#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11)
+#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10)
+#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7)
+#define MWL8K_A2H_INT_RADIO_ON (1 << 6)
+#define MWL8K_A2H_INT_RADIO_OFF (1 << 5)
+#define MWL8K_A2H_INT_MAC_EVENT (1 << 3)
+#define MWL8K_A2H_INT_OPC_DONE (1 << 2)
+#define MWL8K_A2H_INT_RX_READY (1 << 1)
+#define MWL8K_A2H_INT_TX_DONE (1 << 0)
#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \
MWL8K_A2H_INT_CHNL_SWITCHED | \
@@ -331,7 +332,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
snprintf(buf, bufsize, "%s", #x);\
return buf;\
} while (0)
- switch (cmd & (~0x8000)) {
+ switch (cmd & ~0x8000) {
MWL8K_CMDNAME(CODE_DNLD);
MWL8K_CMDNAME(GET_HW_SPEC);
MWL8K_CMDNAME(MAC_MULTICAST_ADR);
@@ -1078,8 +1079,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
int size;
int i;
- memset(&txq->tx_stats, 0,
- sizeof(struct ieee80211_tx_queue_stats));
+ memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats));
txq->tx_stats.limit = MWL8K_TX_DESCS;
txq->tx_head = 0;
txq->tx_tail = 0;
@@ -1181,10 +1181,10 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
{
- u32 count = 0;
- unsigned long timeout = 0;
struct mwl8k_priv *priv = hw->priv;
DECLARE_COMPLETION_ONSTACK(cmd_wait);
+ u32 count;
+ unsigned long timeout;
might_sleep();
@@ -1219,7 +1219,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
__func__, __LINE__, delay_ms, count, newcount);
mwl8k_scan_tx_ring(priv, txinfo, 4);
- for (index = 0 ; index < 4; index++)
+ for (index = 0; index < 4; index++)
printk(KERN_ERR
"TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
index,
@@ -1229,6 +1229,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
txinfo[index].fw_owned,
txinfo[index].drv_owned,
txinfo[index].unused);
+
return -ETIMEDOUT;
}
@@ -1251,7 +1252,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
int rc;
struct mwl8k_tx_desc *tx_desc;
unsigned long addr;
- size_t size;
+ int size;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
u32 status;
@@ -1275,7 +1276,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
priv->pending_tx_pkts--;
addr = le32_to_cpu(tx_desc->pkt_phys_addr);
- size = (u32)(le16_to_cpu(tx_desc->pkt_len));
+ size = le16_to_cpu(tx_desc->pkt_len);
skb = txq->tx_skb[tx].skb;
txq->tx_skb[tx].skb = NULL;
@@ -1312,12 +1313,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
-
- /* Convert firmware status stuff into tx_status */
- if (MWL8K_TXD_SUCCESS(status)) {
- /* Transmit OK */
+ if (MWL8K_TXD_SUCCESS(status))
info->flags |= IEEE80211_TX_STAT_ACK;
- }
ieee80211_tx_status_irqsafe(hw, skb);
@@ -1522,7 +1519,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
dma_addr_t dma_addr;
unsigned int dma_size;
int rc;
- u16 __iomem *result;
unsigned long timeout = 0;
u8 buf[32];
@@ -1551,7 +1547,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
pci_unmap_single(priv->pdev, dma_addr, dma_size,
PCI_DMA_BIDIRECTIONAL);
- result = &cmd->result;
if (!timeout) {
spin_lock_irq(&priv->fw_lock);
priv->hostcmd_wait = NULL;
@@ -1562,12 +1557,12 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
MWL8K_CMD_TIMEOUT_MS);
rc = -ETIMEDOUT;
} else {
- rc = *result ? -EINVAL : 0;
+ rc = cmd->result ? -EINVAL : 0;
if (rc)
printk(KERN_ERR "%s: Command %s error 0x%x\n",
priv->name,
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
- *result);
+ cmd->result);
}
return rc;
@@ -1638,10 +1633,11 @@ struct mwl8k_cmd_mac_multicast_adr {
struct mwl8k_cmd_pkt header;
__le16 action;
__le16 numaddr;
- __u8 addr[1][ETH_ALEN];
+ __u8 addr[0][ETH_ALEN];
};
#define MWL8K_ENABLE_RX_MULTICAST 0x000F
+
static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
int mc_count,
struct dev_addr_list *mclist)
@@ -1649,7 +1645,8 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
struct mwl8k_cmd_mac_multicast_adr *cmd;
int index = 0;
int rc;
- int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN);
+ int size = sizeof(*cmd) + mc_count * ETH_ALEN;
+
cmd = kzalloc(size, GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
@@ -1658,13 +1655,13 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
cmd->header.length = cpu_to_le16(size);
cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
cmd->numaddr = cpu_to_le16(mc_count);
- while ((index < mc_count) && mclist) {
+
+ while (index < mc_count && mclist) {
if (mclist->da_addrlen != ETH_ALEN) {
rc = -EINVAL;
goto mwl8k_cmd_mac_multicast_adr_exit;
}
- memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN);
- index++;
+ memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN);
mclist = mclist->next;
}
@@ -1846,7 +1843,7 @@ struct mwl8k_cmd_set_post_scan {
} __attribute__((packed));
static int
-mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN])
+mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac)
{
struct mwl8k_cmd_set_post_scan *cmd;
int rc;
@@ -1980,7 +1977,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0;
+ cmd->action = cpu_to_le32(!!enable);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -1989,7 +1986,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
}
/*
- * CMD_SET_RATE_ADAPT_MODE.
+ * CMD_SET_RATEADAPT_MODE.
*/
struct mwl8k_cmd_set_rate_adapt_mode {
struct mwl8k_cmd_pkt header;
@@ -2117,22 +2114,18 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
__u8 aifs, __u16 txop)
{
struct mwl8k_cmd_set_edca_params *cmd;
- u32 log_cw_min, log_cw_max;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
- log_cw_min = ilog2(cw_min+1);
- log_cw_max = ilog2(cw_max+1);
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
-
cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
cmd->txop = cpu_to_le16(txop);
- cmd->log_cw_max = (u8)log_cw_max;
- cmd->log_cw_min = (u8)log_cw_min;
+ cmd->log_cw_max = (u8)ilog2(cw_max + 1);
+ cmd->log_cw_min = (u8)ilog2(cw_min + 1);
cmd->aifs = aifs;
cmd->txq = qnum;
@@ -2173,11 +2166,7 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
-
- if (dtim)
- cmd->sleep_interval = cpu_to_le32(dtim);
- else
- cmd->sleep_interval = cpu_to_le32(1);
+ cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
hdrlen = ieee80211_hdrlen(payload->frame_control);
@@ -2189,8 +2178,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
"sent to firmware. Sz=%u MAX=%u\n", __func__,
payload_len, MWL8K_FJ_BEACON_MAXLEN);
- payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ?
- MWL8K_FJ_BEACON_MAXLEN : payload_len;
+ if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
+ payload_len = MWL8K_FJ_BEACON_MAXLEN;
if (payload && payload_len)
memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
@@ -2250,7 +2239,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
peer_info->amsdu_enabled = 0;
rates = peer_info->legacy_rates;
- for (count = 0 ; count < mv_vif->legacy_nrates; count++)
+ for (count = 0; count < mv_vif->legacy_nrates; count++)
rates[count] = bitrates[count].hw_value;
rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -2313,8 +2302,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN);
- prot_mode = MWL8K_FRAME_PROT_DISABLED;
-
if (info->use_cts_prot) {
prot_mode = MWL8K_FRAME_PROT_11G;
} else {
@@ -2331,7 +2318,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
break;
}
}
-
cmd->protection_mode = cpu_to_le16(prot_mode);
for (count = 0; count < mv_vif->legacy_nrates; count++)
@@ -2934,7 +2920,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
mwl8k_vif->priv = priv;
/* Setup initial PHY parameters */
- memcpy(mwl8k_vif->legacy_rates ,
+ memcpy(mwl8k_vif->legacy_rates,
priv->rates, sizeof(mwl8k_vif->legacy_rates));
mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);
@@ -3178,8 +3164,9 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
if (rc)
goto mwl8k_configure_filter_exit;
if (mc_count) {
- mc_count = mc_count < priv->num_mcaddrs ?
- mc_count : priv->num_mcaddrs;
+ if (mc_count > priv->num_mcaddrs)
+ mc_count = priv->num_mcaddrs;
+
rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
if (rc)
printk(KERN_ERR
@@ -3398,12 +3385,9 @@ static void mwl8k_tx_reclaim_handler(unsigned long data)
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_reclaim(hw, i, 0);
- if (priv->tx_wait != NULL) {
- int count = mwl8k_txq_busy(priv);
- if (count == 0) {
- complete(priv->tx_wait);
- priv->tx_wait = NULL;
- }
+ if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) {
+ complete(priv->tx_wait);
+ priv->tx_wait = NULL;
}
spin_unlock_bh(&priv->tx_lock);
}
@@ -3413,7 +3397,7 @@ static void mwl8k_finalize_join_worker(struct work_struct *work)
struct mwl8k_priv *priv =
container_of(work, struct mwl8k_priv, finalize_join_worker);
struct sk_buff *skb = priv->beacon_skb;
- u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period;
+ u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period;
mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim);
dev_kfree_skb(skb);
@@ -3500,7 +3484,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR);
/* Set rssi and noise values to dBm */
- hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM);
+ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
hw->vif_data_size = sizeof(struct mwl8k_vif);
priv->vif = NULL;
--
1.5.6.4
^ permalink raw reply related
* [PATCH 05/29] mwl8k: remove MWL8K_RADIO_* defines
From: Lennert Buytenhek @ 2009-08-18 3:51 UTC (permalink / raw)
To: linville, linux-wireless
Instead of passing a flag bitmask to mwl8k_cmd_802_11_radio_control,
pass the 'enable' and 'force' arguments as separate parameters, and
introduce wrappers for the common cases of enabling and disabling
without forcing.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 52 +++++++++++++++++++++--------------------
1 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index a3b0e19..f57d28c 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -186,9 +186,10 @@ struct mwl8k_priv {
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[12];
+ bool radio_on;
+
/* RF preamble: Short, Long or Auto */
u8 radio_preamble;
- u8 radio_state;
/* WMM MODE 1 for enabled; 0 for disabled */
bool wmm_mode;
@@ -278,9 +279,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
};
/* Radio settings */
-#define MWL8K_RADIO_FORCE 0x2
-#define MWL8K_RADIO_ENABLE 0x1
-#define MWL8K_RADIO_DISABLE 0x0
#define MWL8K_RADIO_AUTO_PREAMBLE 0x0005
#define MWL8K_RADIO_SHORT_PREAMBLE 0x0003
#define MWL8K_RADIO_LONG_PREAMBLE 0x0001
@@ -1195,7 +1193,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
count = mwl8k_txq_busy(priv);
if (count) {
priv->tx_wait = &cmd_wait;
- if (priv->radio_state)
+ if (priv->radio_on)
mwl8k_tx_start(priv);
}
spin_unlock_bh(&priv->tx_lock);
@@ -1318,7 +1316,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
ieee80211_tx_status_irqsafe(hw, skb);
- wake = !priv->inconfig && priv->radio_state;
+ wake = !priv->inconfig && priv->radio_on;
}
if (wake)
@@ -1726,18 +1724,16 @@ struct mwl8k_cmd_802_11_radio_control {
__le16 radio_on;
} __attribute__((packed));
-static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable)
+static int
+mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_802_11_radio_control *cmd;
int rc;
- if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) &&
- !(enable & MWL8K_RADIO_FORCE))
+ if (enable == priv->radio_on && !force)
return 0;
- enable &= MWL8K_RADIO_ENABLE;
-
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
@@ -1752,11 +1748,21 @@ static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable)
kfree(cmd);
if (!rc)
- priv->radio_state = enable;
+ priv->radio_on = enable;
return rc;
}
+static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw)
+{
+ return mwl8k_cmd_802_11_radio_control(hw, 0, 0);
+}
+
+static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw)
+{
+ return mwl8k_cmd_802_11_radio_control(hw, 1, 0);
+}
+
static int
mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
{
@@ -1770,8 +1776,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
MWL8K_RADIO_SHORT_PREAMBLE :
MWL8K_RADIO_LONG_PREAMBLE);
- return mwl8k_cmd_802_11_radio_control(hw,
- MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE);
+ return mwl8k_cmd_802_11_radio_control(hw, 1, 1);
}
/*
@@ -2483,7 +2488,7 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
if (!priv->inconfig &&
- priv->radio_state &&
+ priv->radio_on &&
mwl8k_txq_busy(priv))
mwl8k_tx_start(priv);
}
@@ -2661,7 +2666,7 @@ static void mwl8k_config_thread(struct work_struct *wt)
spin_lock_irq(&priv->tx_lock);
priv->inconfig = false;
- if (priv->pending_tx_pkts && priv->radio_state)
+ if (priv->pending_tx_pkts && priv->radio_on)
mwl8k_tx_start(priv);
spin_unlock_irq(&priv->tx_lock);
ieee80211_wake_queues(hw);
@@ -2745,7 +2750,7 @@ static int mwl8k_start_wt(struct work_struct *wt)
}
/* Turn on radio */
- if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
+ if (mwl8k_cmd_802_11_radio_enable(hw)) {
rc = -EIO;
goto mwl8k_start_exit;
}
@@ -2839,11 +2844,8 @@ static int mwl8k_stop_wt(struct work_struct *wt)
{
struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt;
struct ieee80211_hw *hw = worker->header.hw;
- int rc;
-
- rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
- return rc;
+ return mwl8k_cmd_802_11_radio_disable(hw);
}
static void mwl8k_stop(struct ieee80211_hw *hw)
@@ -2959,13 +2961,13 @@ static int mwl8k_config_wt(struct work_struct *wt)
int rc = 0;
if (!conf->radio_enabled) {
- mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
+ mwl8k_cmd_802_11_radio_disable(hw);
priv->current_channel = NULL;
rc = 0;
goto mwl8k_config_exit;
}
- if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
+ if (mwl8k_cmd_802_11_radio_enable(hw)) {
rc = -EINVAL;
goto mwl8k_config_exit;
}
@@ -3490,7 +3492,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
/* Set default radio state and preamble */
priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE;
- priv->radio_state = MWL8K_RADIO_DISABLE;
+ priv->radio_on = 0;
/* Finalize join worker */
INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
@@ -3571,7 +3573,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
}
/* Turn radio off */
- rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
+ rc = mwl8k_cmd_802_11_radio_disable(hw);
if (rc) {
printk(KERN_ERR "%s: Cannot disable\n", priv->name);
goto err_stop_firmware;
--
1.5.6.4
^ permalink raw reply related
* [PATCH 06/29] mwl8k: remove MWL8K_RADIO_*_PREAMBLE defines
From: Lennert Buytenhek @ 2009-08-18 3:51 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 22 +++++-----------------
1 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f57d28c..92b2fce 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -187,9 +187,7 @@ struct mwl8k_priv {
struct ieee80211_rate rates[12];
bool radio_on;
-
- /* RF preamble: Short, Long or Auto */
- u8 radio_preamble;
+ bool radio_short_preamble;
/* WMM MODE 1 for enabled; 0 for disabled */
bool wmm_mode;
@@ -278,17 +276,10 @@ static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 540, .hw_value = 108, },
};
-/* Radio settings */
-#define MWL8K_RADIO_AUTO_PREAMBLE 0x0005
-#define MWL8K_RADIO_SHORT_PREAMBLE 0x0003
-#define MWL8K_RADIO_LONG_PREAMBLE 0x0001
-
/* WMM */
#define MWL8K_WMM_ENABLE 1
#define MWL8K_WMM_DISABLE 0
-#define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE
-
/* Slot time */
/* Short Slot: 9us slot time */
@@ -1741,7 +1732,7 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_CMD_SET);
- cmd->control = cpu_to_le16(priv->radio_preamble);
+ cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1);
cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000);
rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -1772,9 +1763,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
return -EINVAL;
priv = hw->priv;
- priv->radio_preamble = (short_preamble ?
- MWL8K_RADIO_SHORT_PREAMBLE :
- MWL8K_RADIO_LONG_PREAMBLE);
+ priv->radio_short_preamble = short_preamble;
return mwl8k_cmd_802_11_radio_control(hw, 1, 1);
}
@@ -3058,8 +3047,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
goto mwl8k_bss_info_changed_exit;
/* Set radio preamble */
- if (mwl8k_set_radio_preamble(hw,
- info->use_short_preamble))
+ if (mwl8k_set_radio_preamble(hw, info->use_short_preamble))
goto mwl8k_bss_info_changed_exit;
/* Set slot time */
@@ -3491,8 +3479,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv->vif = NULL;
/* Set default radio state and preamble */
- priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE;
priv->radio_on = 0;
+ priv->radio_short_preamble = 0;
/* Finalize join worker */
INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
--
1.5.6.4
^ permalink raw reply related
* [PATCH 07/29] mwl8k: remove MWL8K_WMM_* defines
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 21 ++++++++-------------
1 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 92b2fce..c9bb9b1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -188,9 +188,7 @@ struct mwl8k_priv {
bool radio_on;
bool radio_short_preamble;
-
- /* WMM MODE 1 for enabled; 0 for disabled */
- bool wmm_mode;
+ bool wmm_enabled;
/* Set if PHY config is in progress */
bool inconfig;
@@ -276,10 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 540, .hw_value = 108, },
};
-/* WMM */
-#define MWL8K_WMM_ENABLE 1
-#define MWL8K_WMM_DISABLE 0
-
/* Slot time */
/* Short Slot: 9us slot time */
@@ -2028,13 +2022,13 @@ static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable)
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0;
+ cmd->action = cpu_to_le16(!!enable);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
if (!rc)
- priv->wmm_mode = enable;
+ priv->wmm_enabled = enable;
return rc;
}
@@ -2762,7 +2756,7 @@ static int mwl8k_start_wt(struct work_struct *wt)
}
/* Disable WMM. WMM gets enabled when stack sends WMM parms */
- if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) {
+ if (mwl8k_set_wmm(hw, 0)) {
rc = -EIO;
goto mwl8k_start_exit;
}
@@ -3260,10 +3254,11 @@ static int mwl8k_conf_tx_wt(struct work_struct *wt)
struct mwl8k_priv *priv = hw->priv;
int rc = 0;
- if (priv->wmm_mode == MWL8K_WMM_DISABLE)
- if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) {
+ if (!priv->wmm_enabled) {
+ if (mwl8k_set_wmm(hw, 1)) {
rc = -EINVAL;
goto mwl8k_conf_tx_exit;
+ }
}
if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min,
@@ -3433,7 +3428,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv->hostcmd_wait = NULL;
priv->tx_wait = NULL;
priv->inconfig = false;
- priv->wmm_mode = false;
+ priv->wmm_enabled = false;
priv->pending_tx_pkts = 0;
strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
--
1.5.6.4
^ permalink raw reply related
* [PATCH 08/29] mwl8k: remove MWL8K_*_SLOTTIME defines
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 15 +++------------
1 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index c9bb9b1..9f54204 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -274,14 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 540, .hw_value = 108, },
};
-/* Slot time */
-
-/* Short Slot: 9us slot time */
-#define MWL8K_SHORT_SLOTTIME 1
-
-/* Long slot: 20us slot time */
-#define MWL8K_LONG_SLOTTIME 0
-
/* Set or get info from Firmware */
#define MWL8K_CMD_SET 0x0001
#define MWL8K_CMD_GET 0x0000
@@ -1895,7 +1887,7 @@ struct mwl8k_cmd_set_slot {
__u8 short_slot;
} __attribute__((packed));
-static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time)
+static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
{
struct mwl8k_cmd_set_slot *cmd;
int rc;
@@ -1907,7 +1899,7 @@ static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time)
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_CMD_SET);
- cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0;
+ cmd->short_slot = short_slot_time;
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -3045,8 +3037,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
goto mwl8k_bss_info_changed_exit;
/* Set slot time */
- if (mwl8k_cmd_set_slot(hw, info->use_short_slot ?
- MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME))
+ if (mwl8k_cmd_set_slot(hw, info->use_short_slot))
goto mwl8k_bss_info_changed_exit;
/* Update peer rate info */
--
1.5.6.4
^ permalink raw reply related
* [PATCH 09/29] mwl8k: remove usage of deprecated radio_enabled
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9f54204..3a201a2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2935,7 +2935,7 @@ static int mwl8k_config_wt(struct work_struct *wt)
struct mwl8k_priv *priv = hw->priv;
int rc = 0;
- if (!conf->radio_enabled) {
+ if (conf->flags & IEEE80211_CONF_IDLE) {
mwl8k_cmd_802_11_radio_disable(hw);
priv->current_channel = NULL;
rc = 0;
--
1.5.6.4
^ permalink raw reply related
* [PATCH 10/29] mwl8k: fix mwl8k_configure_filter() parameter lifetime issue
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
mwl8k_configure_filter() passes pointers to total_flags and the
multicast address list to a workqueue function, while there is no
guarantee that those pointers will still be valid by the time the
workqueue function runs.
Solve this by passing total_flags by value, and by passing an
already built multicast address setup command packet to the workqueue
function so that we don't have to look at the multicast address list
itself outside of mwl8k_configure_filter().
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 72 +++++++++++++++++------------------------
1 files changed, 30 insertions(+), 42 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 3a201a2..e266bc1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1613,38 +1613,39 @@ struct mwl8k_cmd_mac_multicast_adr {
#define MWL8K_ENABLE_RX_MULTICAST 0x000F
-static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
- int mc_count,
- struct dev_addr_list *mclist)
+static struct mwl8k_cmd_pkt *
+__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
+ int mc_count, struct dev_addr_list *mclist)
{
+ struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_mac_multicast_adr *cmd;
- int index = 0;
- int rc;
- int size = sizeof(*cmd) + mc_count * ETH_ALEN;
+ int size;
+ int i;
+
+ if (mc_count > priv->num_mcaddrs)
+ mc_count = priv->num_mcaddrs;
- cmd = kzalloc(size, GFP_KERNEL);
+ size = sizeof(*cmd) + mc_count * ETH_ALEN;
+
+ cmd = kzalloc(size, GFP_ATOMIC);
if (cmd == NULL)
- return -ENOMEM;
+ return NULL;
cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
cmd->header.length = cpu_to_le16(size);
cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
cmd->numaddr = cpu_to_le16(mc_count);
- while (index < mc_count && mclist) {
+ for (i = 0; i < mc_count && mclist; i++) {
if (mclist->da_addrlen != ETH_ALEN) {
- rc = -EINVAL;
- goto mwl8k_cmd_mac_multicast_adr_exit;
+ kfree(cmd);
+ return NULL;
}
- memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN);
+ memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
mclist = mclist->next;
}
- rc = mwl8k_post_cmd(hw, &cmd->header);
-
-mwl8k_cmd_mac_multicast_adr_exit:
- kfree(cmd);
- return rc;
+ return &cmd->header;
}
/*
@@ -3101,9 +3102,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
struct mwl8k_configure_filter_worker {
struct mwl8k_work_struct header;
unsigned int changed_flags;
- unsigned int *total_flags;
- int mc_count;
- struct dev_addr_list *mclist;
+ unsigned int total_flags;
+ struct mwl8k_cmd_pkt *set_multicast_adr;
};
#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC
@@ -3112,18 +3112,14 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
{
struct mwl8k_configure_filter_worker *worker =
(struct mwl8k_configure_filter_worker *)wt;
-
struct ieee80211_hw *hw = worker->header.hw;
unsigned int changed_flags = worker->changed_flags;
- unsigned int *total_flags = worker->total_flags;
- int mc_count = worker->mc_count;
- struct dev_addr_list *mclist = worker->mclist;
-
+ unsigned int total_flags = worker->total_flags;
struct mwl8k_priv *priv = hw->priv;
int rc = 0;
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+ if (total_flags & FIF_BCN_PRBRESP_PROMISC)
rc = mwl8k_cmd_set_pre_scan(hw);
else {
u8 *bssid;
@@ -3136,20 +3132,12 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
}
}
- if (rc)
- goto mwl8k_configure_filter_exit;
- if (mc_count) {
- if (mc_count > priv->num_mcaddrs)
- mc_count = priv->num_mcaddrs;
-
- rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
- if (rc)
- printk(KERN_ERR
- "%s()Error setting multicast addresses\n",
- __func__);
+ if (worker->set_multicast_adr != NULL) {
+ if (!rc)
+ rc = mwl8k_post_cmd(hw, worker->set_multicast_adr);
+ kfree(worker->set_multicast_adr);
}
-mwl8k_configure_filter_exit:
return rc;
}
@@ -3159,7 +3147,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
int mc_count,
struct dev_addr_list *mclist)
{
-
struct mwl8k_configure_filter_worker *worker;
struct mwl8k_priv *priv = hw->priv;
@@ -3175,9 +3162,10 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
worker->changed_flags = changed_flags;
- worker->total_flags = total_flags;
- worker->mc_count = mc_count;
- worker->mclist = mclist;
+ worker->total_flags = *total_flags;
+ if (mc_count)
+ worker->set_multicast_adr =
+ __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
mwl8k_queue_work(hw, &worker->header, priv->config_wq,
mwl8k_configure_filter_wt);
--
1.5.6.4
^ permalink raw reply related
* [PATCH 11/29] mwl8k: ->add_interface() is not called for monitor interfaces
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
There is no need to check for NL80211_IFTYPE_MONITOR in
->add_interface(), as this function is never called for monitor
interfaces. Also, there is no need to advertise this bit in our
wiphy's ->interface_modes.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index e266bc1..4580b1d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2883,8 +2883,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
/*
* We only support managed interfaces for now.
*/
- if (conf->type != NL80211_IFTYPE_STATION &&
- conf->type != NL80211_IFTYPE_MONITOR)
+ if (conf->type != NL80211_IFTYPE_STATION)
return -EINVAL;
/* Clean out driver private area */
@@ -3444,8 +3443,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
hw->queues = MWL8K_TX_QUEUES;
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR);
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
/* Set rssi and noise values to dBm */
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
--
1.5.6.4
^ permalink raw reply related
* [PATCH 12/29] mwl8k: dma header manipulations can't fail
From: Lennert Buytenhek @ 2009-08-18 3:52 UTC (permalink / raw)
To: linville, linux-wireless
Adding and removing the DMA header that the mwl8k hardware requires
on tx and provides on rx can never fail, since we are guaranteed to
have enough headroom on the tx path to expand the packet, and we only
ever shrink the packet on the rx path. (And on both paths we are
guaranteed to be the only user of the skb we are handling.)
This allows removing all of the skb clone handling in the tx and tx
reclaim paths, and eliminates error checks in both the tx and rx
paths, simplifying the code a bit more.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 83 +++++++-----------------------------------
1 files changed, 13 insertions(+), 70 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 4580b1d..f4b197b 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -111,17 +111,6 @@ struct mwl8k_rx_queue {
struct sk_buff **rx_skb;
};
-struct mwl8k_skb {
- /*
- * The DMA engine requires a modification to the payload.
- * If the skbuff is shared/cloned, it needs to be unshared.
- * This method is used to ensure the stack always gets back
- * the skbuff it sent for transmission.
- */
- struct sk_buff *clone;
- struct sk_buff *skb;
-};
-
struct mwl8k_tx_queue {
/* hw transmits here */
int tx_head;
@@ -132,7 +121,7 @@ struct mwl8k_tx_queue {
struct ieee80211_tx_queue_stats tx_stats;
struct mwl8k_tx_desc *tx_desc_area;
dma_addr_t tx_desc_dma;
- struct mwl8k_skb *tx_skb;
+ struct sk_buff **tx_skb;
};
/* Pointers to the firmware data and meta information about it. */
@@ -714,12 +703,11 @@ struct mwl8k_dma_data {
} __attribute__((packed));
/* Routines to add/remove DMA header from skb. */
-static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
+static inline void mwl8k_remove_dma_header(struct sk_buff *skb)
{
- struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data);
+ struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data;
void *dst, *src = &tr->wh;
- __le16 fc = tr->wh.frame_control;
- int hdrlen = ieee80211_hdrlen(fc);
+ int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
dst = (void *)tr + space;
@@ -727,11 +715,9 @@ static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
memmove(dst, src, hdrlen);
skb_pull(skb, space);
}
-
- return 0;
}
-static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
+static inline void mwl8k_add_dma_header(struct sk_buff *skb)
{
struct ieee80211_hdr *wh;
u32 hdrlen, pktlen;
@@ -763,8 +749,6 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
* This includes all crypto material including the MIC.
*/
tr->fwlen = cpu_to_le16(pktlen - hdrlen);
-
- return skb;
}
@@ -967,10 +951,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
- if (mwl8k_remove_dma_header(skb)) {
- dev_kfree_skb(skb);
- continue;
- }
+ mwl8k_remove_dma_header(skb);
wh = (struct ieee80211_hdr *)skb->data;
@@ -1224,7 +1205,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
while (txq->tx_stats.len > 0) {
int tx;
- int rc;
struct mwl8k_tx_desc *tx_desc;
unsigned long addr;
int size;
@@ -1232,7 +1212,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
struct ieee80211_tx_info *info;
u32 status;
- rc = 0;
tx = txq->tx_head;
tx_desc = txq->tx_desc_area + tx;
@@ -1252,40 +1231,18 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
addr = le32_to_cpu(tx_desc->pkt_phys_addr);
size = le16_to_cpu(tx_desc->pkt_len);
- skb = txq->tx_skb[tx].skb;
- txq->tx_skb[tx].skb = NULL;
+ skb = txq->tx_skb[tx];
+ txq->tx_skb[tx] = NULL;
BUG_ON(skb == NULL);
pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
- rc = mwl8k_remove_dma_header(skb);
+ mwl8k_remove_dma_header(skb);
/* Mark descriptor as unused */
tx_desc->pkt_phys_addr = 0;
tx_desc->pkt_len = 0;
- if (txq->tx_skb[tx].clone) {
- /* Replace with original skb
- * before returning to stack
- * as buffer has been cloned
- */
- dev_kfree_skb(skb);
- skb = txq->tx_skb[tx].clone;
- txq->tx_skb[tx].clone = NULL;
- }
-
- if (rc) {
- /* Something has gone wrong here.
- * Failed to remove DMA header.
- * Print error message and drop packet.
- */
- printk(KERN_ERR "%s: Error removing DMA header from "
- "tx skb 0x%p.\n", priv->name, skb);
-
- dev_kfree_skb(skb);
- continue;
- }
-
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
if (MWL8K_TXD_SUCCESS(status))
@@ -1327,7 +1284,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
struct mwl8k_tx_desc *tx;
struct mwl8k_dma_data *tr;
struct mwl8k_vif *mwl8k_vif;
- struct sk_buff *org_skb = skb;
dma_addr_t dma;
u16 qos = 0;
bool qosframe = false, ampduframe = false;
@@ -1338,21 +1294,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
txq = priv->txq + index;
tx = txq->tx_desc_area + txq->tx_tail;
- BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL);
+ BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
/*
- * Append HW DMA header to start of packet. Drop packet if
- * there is not enough space or a failure to unshare/unclone
- * the skb.
+ * Append HW DMA header to start of packet.
*/
- skb = mwl8k_add_dma_header(skb);
-
- if (skb == NULL) {
- printk(KERN_DEBUG "%s: failed to prepend HW DMA "
- "header, dropping TX frame.\n", priv->name);
- dev_kfree_skb(org_skb);
- return NETDEV_TX_OK;
- }
+ mwl8k_add_dma_header(skb);
tx_info = IEEE80211_SKB_CB(skb);
mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
@@ -1380,8 +1327,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
printk(KERN_DEBUG "%s: failed to dma map skb, "
"dropping TX frame.\n", priv->name);
- if (org_skb != NULL)
- dev_kfree_skb(org_skb);
if (skb != NULL)
dev_kfree_skb(skb);
return NETDEV_TX_OK;
@@ -1437,9 +1382,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
tx->pkt_phys_addr = cpu_to_le32(dma);
tx->pkt_len = cpu_to_le16(skb->len);
- txq->tx_skb[txq->tx_tail].skb = skb;
- txq->tx_skb[txq->tx_tail].clone =
- skb == org_skb ? NULL : org_skb;
+ txq->tx_skb[txq->tx_tail] = skb;
spin_lock_bh(&priv->tx_lock);
--
1.5.6.4
^ permalink raw reply related
* [PATCH 13/29] mwl8k: don't touch 'command done' interrupt during firmware load
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
Since firmware load commands don't generate 'command done' interrupts
like normal commands do, polling for command done interrupts just
unnecessarily slows down the firmware load process. Removing this bit
of code speeds up loading a typical firmware image from 840 msec to
180 msec.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 24 +-----------------------
1 files changed, 1 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f4b197b..86b6b5d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -411,7 +411,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
{
void __iomem *regs = priv->regs;
dma_addr_t dma_addr;
- int rc;
int loops;
dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE);
@@ -425,7 +424,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
iowrite32(MWL8K_H2A_INT_DUMMY,
regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
- rc = -ETIMEDOUT;
loops = 1000;
do {
u32 int_code;
@@ -433,7 +431,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
iowrite32(0, regs + MWL8K_HIU_INT_CODE);
- rc = 0;
break;
}
@@ -442,26 +439,7 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE);
- /*
- * Clear 'command done' interrupt bit.
- */
- loops = 1000;
- do {
- u32 status;
-
- status = ioread32(priv->regs +
- MWL8K_HIU_A2H_INTERRUPT_STATUS);
- if (status & MWL8K_A2H_INT_OPC_DONE) {
- iowrite32(~MWL8K_A2H_INT_OPC_DONE,
- priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
- break;
- }
-
- udelay(1);
- } while (--loops);
-
- return rc;
+ return loops ? 0 : -ETIMEDOUT;
}
static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
--
1.5.6.4
^ permalink raw reply related
* [PATCH 14/29] mwl8k: don't hardcode the number of transmit queues
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
Use MWL8K_TX_QUEUES instead of a hardcoded "4" in a couple of places.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 86b6b5d..f482922 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1080,17 +1080,17 @@ struct mwl8k_txq_info {
};
static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
- struct mwl8k_txq_info txinfo[],
- u32 num_queues)
+ struct mwl8k_txq_info *txinfo)
{
int count, desc, status;
struct mwl8k_tx_queue *txq;
struct mwl8k_tx_desc *tx_desc;
int ndescs = 0;
- memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info));
+ memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info));
+
spin_lock_bh(&priv->tx_lock);
- for (count = 0; count < num_queues; count++) {
+ for (count = 0; count < MWL8K_TX_QUEUES; count++) {
txq = priv->txq + count;
txinfo[count].len = txq->tx_stats.len;
txinfo[count].head = txq->tx_head;
@@ -1135,7 +1135,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
spin_unlock_bh(&priv->tx_lock);
if (count) {
- struct mwl8k_txq_info txinfo[4];
+ struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES];
int index;
int newcount;
@@ -1152,8 +1152,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n",
__func__, __LINE__, delay_ms, count, newcount);
- mwl8k_scan_tx_ring(priv, txinfo, 4);
- for (index = 0; index < 4; index++)
+ mwl8k_scan_tx_ring(priv, txinfo);
+ for (index = 0; index < MWL8K_TX_QUEUES; index++)
printk(KERN_ERR
"TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
index,
--
1.5.6.4
^ permalink raw reply related
* [PATCH 15/29] mwl8k: no need to hold ->tx_lock while setting the hardware interrupt mask
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f482922..e46cf3c 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2768,9 +2768,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
printk(KERN_ERR "%s() timed out\n", __func__);
/* Disable interrupts */
- spin_lock_irq(&priv->tx_lock);
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- spin_unlock_irq(&priv->tx_lock);
free_irq(priv->pdev->irq, hw);
/* Stop finalize join worker */
@@ -3461,9 +3459,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
}
/* Disable interrupts */
- spin_lock_irq(&priv->tx_lock);
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- spin_unlock_irq(&priv->tx_lock);
free_irq(priv->pdev->irq, hw);
rc = ieee80211_register_hw(hw);
@@ -3487,9 +3483,7 @@ err_stop_firmware:
mwl8k_release_firmware(priv);
err_free_irq:
- spin_lock_irq(&priv->tx_lock);
iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- spin_unlock_irq(&priv->tx_lock);
free_irq(priv->pdev->irq, hw);
err_free_queues:
--
1.5.6.4
^ permalink raw reply related
* [PATCH 16/29] mwl8k: mwl8k_txq_xmit() rework
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
Various mwl8k_txq_xmit changes:
- Extract the QoS field before adding the DMA header.
- Only write to tx->status once, and only after all the other
descriptor fields have been set.
- Do all tx state manipulation under the tx spinlock.
- Remove the priv->inconfig check, as all transmit queues will
be frozen during config cycles, so we won't ever be asked to
transmit if a config cycle is running.
- Remove some more dead code.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 145 +++++++++++++++---------------------------
1 files changed, 52 insertions(+), 93 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index e46cf3c..f0d1fa7 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1257,46 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
{
struct mwl8k_priv *priv = hw->priv;
struct ieee80211_tx_info *tx_info;
+ struct mwl8k_vif *mwl8k_vif;
struct ieee80211_hdr *wh;
struct mwl8k_tx_queue *txq;
struct mwl8k_tx_desc *tx;
- struct mwl8k_dma_data *tr;
- struct mwl8k_vif *mwl8k_vif;
dma_addr_t dma;
- u16 qos = 0;
- bool qosframe = false, ampduframe = false;
- bool mcframe = false, eapolframe = false;
- bool amsduframe = false;
- __le16 fc;
+ u32 txstatus;
+ u8 txdatarate;
+ u16 qos;
- txq = priv->txq + index;
- tx = txq->tx_desc_area + txq->tx_tail;
-
- BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+ wh = (struct ieee80211_hdr *)skb->data;
+ if (ieee80211_is_data_qos(wh->frame_control))
+ qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+ else
+ qos = 0;
- /*
- * Append HW DMA header to start of packet.
- */
mwl8k_add_dma_header(skb);
+ wh = &((struct mwl8k_dma_data *)skb->data)->wh;
tx_info = IEEE80211_SKB_CB(skb);
mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
- tr = (struct mwl8k_dma_data *)skb->data;
- wh = &tr->wh;
- fc = wh->frame_control;
- qosframe = ieee80211_is_data_qos(fc);
- mcframe = is_multicast_ether_addr(wh->addr1);
- ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
u16 seqno = mwl8k_vif->seqno;
+
wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
wh->seq_ctrl |= cpu_to_le16(seqno << 4);
mwl8k_vif->seqno = seqno++ % 4096;
}
- if (qosframe)
- qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+ /* Setup firmware control bit fields for each frame type. */
+ txstatus = 0;
+ txdatarate = 0;
+ if (ieee80211_is_mgmt(wh->frame_control) ||
+ ieee80211_is_ctl(wh->frame_control)) {
+ txdatarate = 0;
+ qos = mwl8k_qos_setbit_eosp(qos);
+ /* Set Queue size to unspecified */
+ qos = mwl8k_qos_setbit_qlen(qos, 0xff);
+ } else if (ieee80211_is_data(wh->frame_control)) {
+ txdatarate = 1;
+ if (is_multicast_ether_addr(wh->addr1))
+ txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
+
+ /* Send pkt in an aggregate if AMPDU frame. */
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+ qos = mwl8k_qos_setbit_ack(qos,
+ MWL8K_TXD_ACK_POLICY_BLOCKACK);
+ else
+ qos = mwl8k_qos_setbit_ack(qos,
+ MWL8K_TXD_ACK_POLICY_NORMAL);
+
+ if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ qos = mwl8k_qos_setbit_amsdu(qos);
+ }
dma = pci_map_single(priv->pdev, skb->data,
skb->len, PCI_DMA_TODEVICE);
@@ -1304,95 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
if (pci_dma_mapping_error(priv->pdev, dma)) {
printk(KERN_DEBUG "%s: failed to dma map skb, "
"dropping TX frame.\n", priv->name);
-
- if (skb != NULL)
- dev_kfree_skb(skb);
+ dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
- /* Set desc header, cpu bit order. */
- tx->status = 0;
- tx->data_rate = 0;
- tx->tx_priority = index;
- tx->qos_control = 0;
- tx->rate_info = 0;
- tx->peer_id = mwl8k_vif->peer_id;
-
- amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
-
- /* Setup firmware control bit fields for each frame type. */
- if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
- tx->data_rate = 0;
- qos = mwl8k_qos_setbit_eosp(qos);
- /* Set Queue size to unspecified */
- qos = mwl8k_qos_setbit_qlen(qos, 0xff);
- } else if (ieee80211_is_data(fc)) {
- tx->data_rate = 1;
- if (mcframe)
- tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX;
+ spin_lock_bh(&priv->tx_lock);
- /*
- * Tell firmware to not send EAPOL pkts in an
- * aggregate. Verify against mac80211 tx path. If
- * stack turns off AMPDU for an EAPOL frame this
- * check will be removed.
- */
- if (eapolframe) {
- qos = mwl8k_qos_setbit_ack(qos,
- MWL8K_TXD_ACK_POLICY_NORMAL);
- } else {
- /* Send pkt in an aggregate if AMPDU frame. */
- if (ampduframe)
- qos = mwl8k_qos_setbit_ack(qos,
- MWL8K_TXD_ACK_POLICY_BLOCKACK);
- else
- qos = mwl8k_qos_setbit_ack(qos,
- MWL8K_TXD_ACK_POLICY_NORMAL);
+ txq = priv->txq + index;
- if (amsduframe)
- qos = mwl8k_qos_setbit_amsdu(qos);
- }
- }
+ BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+ txq->tx_skb[txq->tx_tail] = skb;
- /* Convert to little endian */
+ tx = txq->tx_desc_area + txq->tx_tail;
+ tx->data_rate = txdatarate;
+ tx->tx_priority = index;
tx->qos_control = cpu_to_le16(qos);
- tx->status = cpu_to_le32(tx->status);
tx->pkt_phys_addr = cpu_to_le32(dma);
tx->pkt_len = cpu_to_le16(skb->len);
-
- txq->tx_skb[txq->tx_tail] = skb;
-
- spin_lock_bh(&priv->tx_lock);
-
- tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK |
- MWL8K_TXD_STATUS_FW_OWNED);
+ tx->rate_info = 0;
+ tx->peer_id = mwl8k_vif->peer_id;
wmb();
+ tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
+
+ txq->tx_stats.count++;
txq->tx_stats.len++;
priv->pending_tx_pkts++;
- txq->tx_stats.count++;
- txq->tx_tail++;
+ txq->tx_tail++;
if (txq->tx_tail == MWL8K_TX_DESCS)
txq->tx_tail = 0;
+
if (txq->tx_head == txq->tx_tail)
ieee80211_stop_queue(hw, index);
- if (priv->inconfig) {
- /*
- * Silently queue packet when we are in the middle of
- * a config cycle. Notify firmware only if we are
- * waiting for TXQs to empty. If a packet is sent
- * before .config() is complete, perhaps it is better
- * to drop the packet, as the channel is being changed
- * and the packet will end up on the wrong channel.
- */
- printk(KERN_ERR "%s(): WARNING TX activity while "
- "in config\n", __func__);
-
- if (priv->tx_wait != NULL)
- mwl8k_tx_start(priv);
- } else
- mwl8k_tx_start(priv);
+ mwl8k_tx_start(priv);
spin_unlock_bh(&priv->tx_lock);
--
1.5.6.4
^ permalink raw reply related
* [PATCH 17/29] mwl8k: mwl8k_queue_work() cleanup
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
Delete most of the mwl8k_work_struct fields and options, since most
of them are unused or never changed from their defaults:
- We always use priv->config_wq, so delete the wqueue argument from
mwl8k_queue_work().
- MWL8K_WQ_SPIN is never used.
- MWL8K_WQ_TX_WAIT_EMPTY is always set, so assume it unconditionally.
- MWL8K_WQ_FREE_WORKSTRUCT is implied by MWL8K_WQ_POST_REQUEST, so
delete it and assume it whenever the latter is set.
- One of MWL8K_WQ_{POST_REQUEST,SLEEP} is always set, so change this
into a bool flag.
- timeout_ms/txwait_attempts/tx_timeout_ms are never changed from
their defaults, so just hardcode these in the workqueue worker.
- step is never used.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 210 +++++++++--------------------------------
1 files changed, 46 insertions(+), 164 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f0d1fa7..905f750 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1113,7 +1113,7 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
return ndescs;
}
-static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
+static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
DECLARE_COMPLETION_ONSTACK(cmd_wait);
@@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
int newcount;
timeout = wait_for_completion_timeout(&cmd_wait,
- msecs_to_jiffies(delay_ms));
+ msecs_to_jiffies(1000));
if (timeout)
return 0;
@@ -1149,8 +1149,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
newcount = mwl8k_txq_busy(priv);
spin_unlock_bh(&priv->tx_lock);
- printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n",
- __func__, __LINE__, delay_ms, count, newcount);
+ printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n",
+ __func__, __LINE__, count, newcount);
mwl8k_scan_tx_ring(priv, txinfo);
for (index = 0; index < MWL8K_TX_QUEUES; index++)
@@ -2391,82 +2391,18 @@ struct mwl8k_work_struct {
int rc;
/*
- * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX
- * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS.
+ * Whether to sleep for request completion.
*/
- u32 options;
-
- /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */
- unsigned long timeout_ms;
-
- /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */
- u32 txwait_attempts;
-
- /* Optional field. Defaults to MWL8K_TXWAIT_MS. */
- u32 tx_timeout_ms;
- u32 step;
+ bool sleep;
};
-/* Flags controlling behavior of config queue requests */
-
-/* Caller spins while waiting for completion. */
-#define MWL8K_WQ_SPIN 0x00000001
-
-/* Wait for TX queues to empty before proceeding with configuration. */
-#define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002
-
-/* Queue request and return immediately. */
-#define MWL8K_WQ_POST_REQUEST 0x00000004
-
-/*
- * Caller sleeps and waits for task complete notification.
- * Do not use in atomic context.
- */
-#define MWL8K_WQ_SLEEP 0x00000008
-
-/* Free work struct when task is done. */
-#define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010
-
-/*
- * Config request is queued and returns to caller imediately. Use
- * this in atomic context. Work struct is freed by mwl8k_queue_work()
- * when this flag is set.
- */
-#define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \
- MWL8K_WQ_FREE_WORKSTRUCT)
-
-/* Default work queue behavior is to sleep and wait for tx completion. */
-#define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY)
-
-/*
- * Default config request timeout. Add adjustments to make sure the
- * config thread waits long enough for both tx wait and cmd wait before
- * timing out.
- */
-
-/* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */
-#define MWL8K_TXWAIT_TIMEOUT_MS 1000
-
-/* Default number of TX wait attempts. */
-#define MWL8K_WQ_TXWAIT_ATTEMPTS 4
-
-/* Total time to wait for TXQ to drain. */
-#define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \
- MWL8K_WQ_TXWAIT_ATTEMPTS)
-
-/* Scheduling slop. */
-#define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200
-
-#define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \
- MWL8K_TXWAIT_MS + \
- MWL8K_OS_SCHEDULE_OVERHEAD_MS)
-
static void mwl8k_config_thread(struct work_struct *wt)
{
struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt;
struct ieee80211_hw *hw = worker->hw;
struct mwl8k_priv *priv = hw->priv;
int rc = 0;
+ int iter;
spin_lock_irq(&priv->tx_lock);
priv->inconfig = true;
@@ -2479,44 +2415,16 @@ static void mwl8k_config_thread(struct work_struct *wt)
* reconfiguration. This avoids interrupting any in-flight
* DMA transfers to the hardware.
*/
- if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) {
- u32 timeout;
- u32 time_remaining;
- u32 iter;
- u32 tx_wait_attempts = worker->txwait_attempts;
-
- time_remaining = worker->tx_timeout_ms;
- if (!tx_wait_attempts)
- tx_wait_attempts = 1;
-
- timeout = worker->tx_timeout_ms/tx_wait_attempts;
- if (!timeout)
- timeout = 1;
-
- iter = tx_wait_attempts;
- do {
- int wait_time;
-
- if (time_remaining > timeout) {
- time_remaining -= timeout;
- wait_time = timeout;
- } else
- wait_time = time_remaining;
-
- if (!wait_time)
- wait_time = 1;
-
- rc = mwl8k_tx_wait_empty(hw, wait_time);
- if (rc)
- printk(KERN_ERR "%s() txwait timeout=%ums "
- "Retry:%u/%u\n", __func__, timeout,
- tx_wait_attempts - iter + 1,
- tx_wait_attempts);
+ iter = 4;
+ do {
+ rc = mwl8k_tx_wait_empty(hw);
+ if (rc)
+ printk(KERN_ERR "%s() txwait timeout=1000ms "
+ "Retry:%u/%u\n", __func__, 4 - iter + 1, 4);
+ } while (rc && --iter);
- } while (rc && --iter);
+ rc = iter ? 0 : -ETIMEDOUT;
- rc = iter ? 0 : -ETIMEDOUT;
- }
if (!rc)
rc = worker->wfunc(wt);
@@ -2525,58 +2433,38 @@ static void mwl8k_config_thread(struct work_struct *wt)
if (priv->pending_tx_pkts && priv->radio_on)
mwl8k_tx_start(priv);
spin_unlock_irq(&priv->tx_lock);
+
ieee80211_wake_queues(hw);
- worker->rc = rc;
- if (worker->options & MWL8K_WQ_SLEEP)
+ if (worker->sleep) {
+ worker->rc = rc;
complete(worker->cmd_wait);
-
- if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT)
+ } else {
kfree(wt);
+ }
}
static int mwl8k_queue_work(struct ieee80211_hw *hw,
struct mwl8k_work_struct *worker,
- struct workqueue_struct *wqueue,
int (*wfunc)(struct work_struct *w))
{
+ struct mwl8k_priv *priv = hw->priv;
unsigned long timeout = 0;
int rc = 0;
DECLARE_COMPLETION_ONSTACK(cmd_wait);
- if (!worker->timeout_ms)
- worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS;
-
- if (!worker->options)
- worker->options = MWL8K_WQ_DEFAULT_OPTIONS;
-
- if (!worker->txwait_attempts)
- worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS;
-
- if (!worker->tx_timeout_ms)
- worker->tx_timeout_ms = MWL8K_TXWAIT_MS;
-
worker->hw = hw;
worker->cmd_wait = &cmd_wait;
worker->rc = 1;
worker->wfunc = wfunc;
INIT_WORK(&worker->wt, mwl8k_config_thread);
- queue_work(wqueue, &worker->wt);
+ queue_work(priv->config_wq, &worker->wt);
- if (worker->options & MWL8K_WQ_POST_REQUEST) {
- rc = 0;
- } else {
- if (worker->options & MWL8K_WQ_SPIN) {
- timeout = worker->timeout_ms;
- while (timeout && (worker->rc > 0)) {
- mdelay(1);
- timeout--;
- }
- } else if (worker->options & MWL8K_WQ_SLEEP)
- timeout = wait_for_completion_timeout(&cmd_wait,
- msecs_to_jiffies(worker->timeout_ms));
+ if (worker->sleep) {
+ timeout = wait_for_completion_timeout(&cmd_wait,
+ msecs_to_jiffies(10000));
if (timeout)
rc = worker->rc;
@@ -2669,8 +2557,9 @@ static int mwl8k_start(struct ieee80211_hw *hw)
goto mwl8k_start_disable_irq;
}
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq, mwl8k_start_wt);
+ worker->header.sleep = 1;
+
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_start_wt);
kfree(worker);
if (!rc)
return rc;
@@ -2720,8 +2609,9 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
if (worker == NULL)
return;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq, mwl8k_stop_wt);
+ worker->header.sleep = 1;
+
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_stop_wt);
kfree(worker);
if (rc == -ETIMEDOUT)
printk(KERN_ERR "%s() timed out\n", __func__);
@@ -2850,15 +2740,15 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
{
int rc = 0;
struct mwl8k_config_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (worker == NULL)
return -ENOMEM;
+ worker->header.sleep = 1;
worker->changed = changed;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq, mwl8k_config_wt);
+
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_config_wt);
if (rc == -ETIMEDOUT) {
printk(KERN_ERR "%s() timed out.\n", __func__);
rc = -EINVAL;
@@ -2951,7 +2841,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
u32 changed)
{
struct mwl8k_bss_info_changed_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
int rc;
@@ -2965,12 +2854,11 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
if (worker == NULL)
return;
+ worker->header.sleep = 1;
worker->vif = vif;
worker->info = info;
worker->changed = changed;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq,
- mwl8k_bss_info_changed_wt);
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_bss_info_changed_wt);
kfree(worker);
if (rc == -ETIMEDOUT)
printk(KERN_ERR "%s() timed out\n", __func__);
@@ -3025,7 +2913,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mclist)
{
struct mwl8k_configure_filter_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
/* Clear unsupported feature flags */
*total_flags &= MWL8K_SUPPORTED_IF_FLAGS;
@@ -3037,15 +2924,14 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
if (worker == NULL)
return;
- worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
+ worker->header.sleep = 0;
worker->changed_flags = changed_flags;
worker->total_flags = *total_flags;
if (mc_count)
worker->set_multicast_adr =
__mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
- mwl8k_queue_work(hw, &worker->header, priv->config_wq,
- mwl8k_configure_filter_wt);
+ mwl8k_queue_work(hw, &worker->header, mwl8k_configure_filter_wt);
}
struct mwl8k_set_rts_threshold_worker {
@@ -3071,17 +2957,15 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
int rc;
struct mwl8k_set_rts_threshold_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (worker == NULL)
return -ENOMEM;
+ worker->header.sleep = 1;
worker->value = value;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq,
- mwl8k_set_rts_threshold_wt);
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_set_rts_threshold_wt);
kfree(worker);
if (rc == -ETIMEDOUT) {
@@ -3129,16 +3013,15 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
{
int rc;
struct mwl8k_conf_tx_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (worker == NULL)
return -ENOMEM;
+ worker->header.sleep = 1;
worker->queue = queue;
worker->params = params;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq, mwl8k_conf_tx_wt);
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_conf_tx_wt);
kfree(worker);
if (rc == -ETIMEDOUT) {
printk(KERN_ERR "%s() timed out\n", __func__);
@@ -3182,15 +3065,14 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw,
{
int rc;
struct mwl8k_get_stats_worker *worker;
- struct mwl8k_priv *priv = hw->priv;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
if (worker == NULL)
return -ENOMEM;
+ worker->header.sleep = 1;
worker->stats = stats;
- rc = mwl8k_queue_work(hw, &worker->header,
- priv->config_wq, mwl8k_get_stats_wt);
+ rc = mwl8k_queue_work(hw, &worker->header, mwl8k_get_stats_wt);
kfree(worker);
if (rc == -ETIMEDOUT) {
--
1.5.6.4
^ permalink raw reply related
* [PATCH 18/29] mwl8k: fix firmware command serialisation
From: Lennert Buytenhek @ 2009-08-18 3:53 UTC (permalink / raw)
To: linville, linux-wireless
The current mwl8k_priv->fw_lock spinlock doesn't actually protect
against multiple commands being submitted at once, as it is not kept
held over the entire firmware command submission. And since waiting
for command completion sleeps, we can't use a spinlock anyway.
To fix mwl8k firmware command serialisation properly, we have the
following requirements:
- Some commands require that the packet transmit path is idle when
the command is issued. (For simplicity, we'll just quiesce the
transmit path for every command.)
- There are certain sequences of commands that need to be issued to
the hardware sequentially, with no other intervening commands.
This leads to an implementation of a "firmware lock" as a mutex that
can be taken recursively, and which is taken by both the low-level
command submission function (mwl8k_post_cmd) as well as any users of
that function that require issuing of an atomic sequence of commands,
and quiesces the transmit path whenever it's taken.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 154 ++++++++++++++++++++++++------------------
1 files changed, 89 insertions(+), 65 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 905f750..5516058 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -139,13 +139,18 @@ struct mwl8k_priv {
struct pci_dev *pdev;
u8 name[16];
- /* firmware access lock */
- spinlock_t fw_lock;
/* firmware files and meta data */
struct mwl8k_firmware fw;
u32 part_num;
+ /* firmware access */
+ struct mutex fw_mutex;
+ struct task_struct *fw_mutex_owner;
+ int fw_mutex_depth;
+ struct completion *tx_wait;
+ struct completion *hostcmd_wait;
+
/* lock held over TX and TX reap */
spinlock_t tx_lock;
@@ -179,9 +184,6 @@ struct mwl8k_priv {
bool radio_short_preamble;
bool wmm_enabled;
- /* Set if PHY config is in progress */
- bool inconfig;
-
/* XXX need to convert this to handle multiple interfaces */
bool capture_beacon;
u8 capture_bssid[ETH_ALEN];
@@ -200,8 +202,6 @@ struct mwl8k_priv {
/* Work thread to serialize configuration requests */
struct workqueue_struct *config_wq;
- struct completion *hostcmd_wait;
- struct completion *tx_wait;
};
/* Per interface specific private data */
@@ -1113,6 +1113,9 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
return ndescs;
}
+/*
+ * Must be called with hw->fw_mutex held and tx queues stopped.
+ */
static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
@@ -1122,9 +1125,6 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
might_sleep();
- if (priv->tx_wait != NULL)
- printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n");
-
spin_lock_bh(&priv->tx_lock);
count = mwl8k_txq_busy(priv);
if (count) {
@@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
int newcount;
timeout = wait_for_completion_timeout(&cmd_wait,
- msecs_to_jiffies(1000));
+ msecs_to_jiffies(5000));
if (timeout)
return 0;
@@ -1149,7 +1149,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
newcount = mwl8k_txq_busy(priv);
spin_unlock_bh(&priv->tx_lock);
- printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n",
+ printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n",
__func__, __LINE__, count, newcount);
mwl8k_scan_tx_ring(priv, txinfo);
@@ -1228,10 +1228,10 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
ieee80211_tx_status_irqsafe(hw, skb);
- wake = !priv->inconfig && priv->radio_on;
+ wake = 1;
}
- if (wake)
+ if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex))
ieee80211_wake_queue(hw, index);
}
@@ -1360,6 +1360,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
/*
+ * Firmware access.
+ *
+ * We have the following requirements for issuing firmware commands:
+ * - Some commands require that the packet transmit path is idle when
+ * the command is issued. (For simplicity, we'll just quiesce the
+ * transmit path for every command.)
+ * - There are certain sequences of commands that need to be issued to
+ * the hardware sequentially, with no other intervening commands.
+ *
+ * This leads to an implementation of a "firmware lock" as a mutex that
+ * can be taken recursively, and which is taken by both the low-level
+ * command submission function (mwl8k_post_cmd) as well as any users of
+ * that function that require issuing of an atomic sequence of commands,
+ * and quiesces the transmit path whenever it's taken.
+ */
+static int mwl8k_fw_lock(struct ieee80211_hw *hw)
+{
+ struct mwl8k_priv *priv = hw->priv;
+
+ if (priv->fw_mutex_owner != current) {
+ int rc;
+
+ mutex_lock(&priv->fw_mutex);
+ ieee80211_stop_queues(hw);
+
+ rc = mwl8k_tx_wait_empty(hw);
+ if (rc) {
+ ieee80211_wake_queues(hw);
+ mutex_unlock(&priv->fw_mutex);
+
+ return rc;
+ }
+
+ priv->fw_mutex_owner = current;
+ }
+
+ priv->fw_mutex_depth++;
+
+ return 0;
+}
+
+static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
+{
+ struct mwl8k_priv *priv = hw->priv;
+
+ if (!--priv->fw_mutex_depth) {
+ ieee80211_wake_queues(hw);
+ priv->fw_mutex_owner = NULL;
+ mutex_unlock(&priv->fw_mutex);
+ }
+}
+
+
+/*
* Command processing.
*/
@@ -1384,28 +1438,28 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
if (pci_dma_mapping_error(priv->pdev, dma_addr))
return -ENOMEM;
- if (priv->hostcmd_wait != NULL)
- printk(KERN_ERR "WARNING host command in progress\n");
+ rc = mwl8k_fw_lock(hw);
+ if (rc)
+ return rc;
- spin_lock_irq(&priv->fw_lock);
priv->hostcmd_wait = &cmd_wait;
iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
iowrite32(MWL8K_H2A_INT_DOORBELL,
regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
iowrite32(MWL8K_H2A_INT_DUMMY,
regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
- spin_unlock_irq(&priv->fw_lock);
timeout = wait_for_completion_timeout(&cmd_wait,
msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
+ priv->hostcmd_wait = NULL;
+
+ mwl8k_fw_unlock(hw);
+
pci_unmap_single(priv->pdev, dma_addr, dma_size,
PCI_DMA_BIDIRECTIONAL);
if (!timeout) {
- spin_lock_irq(&priv->fw_lock);
- priv->hostcmd_wait = NULL;
- spin_unlock_irq(&priv->fw_lock);
printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
priv->name,
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
@@ -2336,17 +2390,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
}
if (status & MWL8K_A2H_INT_OPC_DONE) {
- if (priv->hostcmd_wait != NULL) {
+ if (priv->hostcmd_wait != NULL)
complete(priv->hostcmd_wait);
- priv->hostcmd_wait = NULL;
- }
}
if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
- if (!priv->inconfig &&
- priv->radio_on &&
- mwl8k_txq_busy(priv))
- mwl8k_tx_start(priv);
+ if (!mutex_is_locked(&priv->fw_mutex) &&
+ priv->radio_on && mwl8k_txq_busy(priv))
+ mwl8k_tx_start(priv);
}
return IRQ_HANDLED;
@@ -2400,41 +2451,13 @@ static void mwl8k_config_thread(struct work_struct *wt)
{
struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt;
struct ieee80211_hw *hw = worker->hw;
- struct mwl8k_priv *priv = hw->priv;
int rc = 0;
- int iter;
- spin_lock_irq(&priv->tx_lock);
- priv->inconfig = true;
- spin_unlock_irq(&priv->tx_lock);
-
- ieee80211_stop_queues(hw);
-
- /*
- * Wait for host queues to drain before doing PHY
- * reconfiguration. This avoids interrupting any in-flight
- * DMA transfers to the hardware.
- */
- iter = 4;
- do {
- rc = mwl8k_tx_wait_empty(hw);
- if (rc)
- printk(KERN_ERR "%s() txwait timeout=1000ms "
- "Retry:%u/%u\n", __func__, 4 - iter + 1, 4);
- } while (rc && --iter);
-
- rc = iter ? 0 : -ETIMEDOUT;
-
- if (!rc)
+ rc = mwl8k_fw_lock(hw);
+ if (!rc) {
rc = worker->wfunc(wt);
-
- spin_lock_irq(&priv->tx_lock);
- priv->inconfig = false;
- if (priv->pending_tx_pkts && priv->radio_on)
- mwl8k_tx_start(priv);
- spin_unlock_irq(&priv->tx_lock);
-
- ieee80211_wake_queues(hw);
+ mwl8k_fw_unlock(hw);
+ }
if (worker->sleep) {
worker->rc = rc;
@@ -3163,15 +3186,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv = hw->priv;
priv->hw = hw;
priv->pdev = pdev;
- priv->hostcmd_wait = NULL;
- priv->tx_wait = NULL;
- priv->inconfig = false;
priv->wmm_enabled = false;
priv->pending_tx_pkts = 0;
strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
- spin_lock_init(&priv->fw_lock);
-
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
@@ -3237,6 +3255,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
goto err_iounmap;
rxq_refill(hw, 0, INT_MAX);
+ mutex_init(&priv->fw_mutex);
+ priv->fw_mutex_owner = NULL;
+ priv->fw_mutex_depth = 0;
+ priv->tx_wait = NULL;
+ priv->hostcmd_wait = NULL;
+
spin_lock_init(&priv->tx_lock);
for (i = 0; i < MWL8K_TX_QUEUES; i++) {
--
1.5.6.4
^ permalink raw reply related
* [PATCH 19/29] mwl8k: get rid of mwl8k_start() workqueue use
From: Lennert Buytenhek @ 2009-08-18 3:54 UTC (permalink / raw)
To: linville, linux-wireless
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
drivers/net/wireless/mwl8k.c | 105 ++++++++++-------------------------------
1 files changed, 26 insertions(+), 79 deletions(-)
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 5516058..69e6879 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2500,106 +2500,53 @@ static int mwl8k_queue_work(struct ieee80211_hw *hw,
return rc;
}
-struct mwl8k_start_worker {
- struct mwl8k_work_struct header;
-};
-
-static int mwl8k_start_wt(struct work_struct *wt)
-{
- struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt;
- struct ieee80211_hw *hw = worker->header.hw;
- struct mwl8k_priv *priv = hw->priv;
- int rc = 0;
-
- if (priv->vif != NULL) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- /* Turn on radio */
- if (mwl8k_cmd_802_11_radio_enable(hw)) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- /* Purge TX/RX HW queues */
- if (mwl8k_cmd_set_pre_scan(hw)) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- /* Enable firmware rate adaptation */
- if (mwl8k_cmd_setrateadaptmode(hw, 0)) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- /* Disable WMM. WMM gets enabled when stack sends WMM parms */
- if (mwl8k_set_wmm(hw, 0)) {
- rc = -EIO;
- goto mwl8k_start_exit;
- }
-
- /* Disable sniffer mode */
- if (mwl8k_enable_sniffer(hw, 0))
- rc = -EIO;
-
-mwl8k_start_exit:
- return rc;
-}
-
static int mwl8k_start(struct ieee80211_hw *hw)
{
- struct mwl8k_start_worker *worker;
struct mwl8k_priv *priv = hw->priv;
int rc;
- /* Enable tx reclaim tasklet */
- tasklet_enable(&priv->tx_reclaim_task);
-
rc = request_irq(priv->pdev->irq, &mwl8k_interrupt,
IRQF_SHARED, MWL8K_NAME, hw);
if (rc) {
printk(KERN_ERR "%s: failed to register IRQ handler\n",
priv->name);
- rc = -EIO;
- goto mwl8k_start_disable_tasklet;
+ return -EIO;
}
+ /* Enable tx reclaim tasklet */
+ tasklet_enable(&priv->tx_reclaim_task);
+
/* Enable interrupts */
iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- worker = kzalloc(sizeof(*worker), GFP_KERNEL);
- if (worker == NULL) {
- rc = -ENOMEM;
- goto mwl8k_start_disable_irq;
- }
+ rc = mwl8k_fw_lock(hw);
+ if (!rc) {
+ rc = mwl8k_cmd_802_11_radio_enable(hw);
- worker->header.sleep = 1;
+ if (!rc)
+ rc = mwl8k_cmd_set_pre_scan(hw);
- rc = mwl8k_queue_work(hw, &worker->header, mwl8k_start_wt);
- kfree(worker);
- if (!rc)
- return rc;
+ if (!rc)
+ rc = mwl8k_cmd_set_post_scan(hw,
+ "\x00\x00\x00\x00\x00\x00");
- if (rc == -ETIMEDOUT)
- printk(KERN_ERR "%s() timed out\n", __func__);
+ if (!rc)
+ rc = mwl8k_cmd_setrateadaptmode(hw, 0);
- rc = -EIO;
+ if (!rc)
+ rc = mwl8k_set_wmm(hw, 0);
-mwl8k_start_disable_irq:
- spin_lock_irq(&priv->tx_lock);
- iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
- spin_unlock_irq(&priv->tx_lock);
- free_irq(priv->pdev->irq, hw);
+ if (!rc)
+ rc = mwl8k_enable_sniffer(hw, 0);
-mwl8k_start_disable_tasklet:
- tasklet_disable(&priv->tx_reclaim_task);
+ mwl8k_fw_unlock(hw);
+ }
+
+ if (rc) {
+ iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+ free_irq(priv->pdev->irq, hw);
+ tasklet_disable(&priv->tx_reclaim_task);
+ }
return rc;
}
--
1.5.6.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox