Commit 95f84f29 authored by John W. Linville's avatar John W. Linville
parents a1775846 95a77610
...@@ -1361,7 +1361,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, ...@@ -1361,7 +1361,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
acx->ht_protection = acx->ht_protection =
(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
acx->rifs_mode = 0; acx->rifs_mode = 0;
acx->gf_protection = 0; acx->gf_protection =
!!(ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
acx->ht_tx_burst_limit = 0; acx->ht_tx_burst_limit = 0;
acx->dual_cts_protection = 0; acx->dual_cts_protection = 0;
......
...@@ -488,6 +488,9 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) ...@@ -488,6 +488,9 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
wl->hw_pg_ver = (s8)fuse; wl->hw_pg_ver = (s8)fuse;
if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
} }
/* uploads NVS and firmware */ /* uploads NVS and firmware */
......
...@@ -59,6 +59,11 @@ struct wl1271_static_data { ...@@ -59,6 +59,11 @@ struct wl1271_static_data {
#define PG_VER_MASK 0x3c #define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2 #define PG_VER_OFFSET 2
#define PG_MAJOR_VER_MASK 0x3
#define PG_MAJOR_VER_OFFSET 0x0
#define PG_MINOR_VER_MASK 0xc
#define PG_MINOR_VER_OFFSET 0x2
#define CMD_MBOX_ADDRESS 0x407B4 #define CMD_MBOX_ADDRESS 0x407B4
#define POLARITY_LOW BIT(1) #define POLARITY_LOW BIT(1)
......
...@@ -63,6 +63,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, ...@@ -63,6 +63,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
cmd->status = 0; cmd->status = 0;
WARN_ON(len % 4 != 0); WARN_ON(len % 4 != 0);
WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));
wl1271_write(wl, wl->cmd_box_addr, buf, len, false); wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
......
...@@ -99,7 +99,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) ...@@ -99,7 +99,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
ret = wl1271_ps_elp_wakeup(wl, false); ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
...@@ -168,5 +168,6 @@ void wl1271_unregister_hw(struct wl1271 *wl); ...@@ -168,5 +168,6 @@ void wl1271_unregister_hw(struct wl1271 *wl);
int wl1271_init_ieee80211(struct wl1271 *wl); int wl1271_init_ieee80211(struct wl1271 *wl);
struct ieee80211_hw *wl1271_alloc_hw(void); struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl); int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
#endif #endif
This diff is collapsed.
...@@ -69,7 +69,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) ...@@ -69,7 +69,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
} }
} }
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) int wl1271_ps_elp_wakeup(struct wl1271 *wl)
{ {
DECLARE_COMPLETION_ONSTACK(compl); DECLARE_COMPLETION_ONSTACK(compl);
unsigned long flags; unsigned long flags;
...@@ -87,7 +87,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) ...@@ -87,7 +87,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
* the completion variable in one entity. * the completion variable in one entity.
*/ */
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
if (work_pending(&wl->irq_work) || chip_awake) if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
pending = true; pending = true;
else else
wl->elp_compl = &compl; wl->elp_compl = &compl;
...@@ -149,7 +149,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, ...@@ -149,7 +149,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_ACTIVE_MODE: case STATION_ACTIVE_MODE:
default: default:
wl1271_debug(DEBUG_PSM, "leaving psm"); wl1271_debug(DEBUG_PSM, "leaving psm");
ret = wl1271_ps_elp_wakeup(wl, false); ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
u32 rates, bool send); u32 rates, bool send);
void wl1271_ps_elp_sleep(struct wl1271 *wl); void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); int wl1271_ps_elp_wakeup(struct wl1271 *wl);
void wl1271_elp_work(struct work_struct *work); void wl1271_elp_work(struct work_struct *work);
void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
......
...@@ -129,7 +129,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) ...@@ -129,7 +129,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
skb_trim(skb, skb->len - desc->pad_len); skb_trim(skb, skb->len - desc->pad_len);
ieee80211_rx_ni(wl->hw, skb); skb_queue_tail(&wl->deferred_rx_queue, skb);
ieee80211_queue_work(wl->hw, &wl->netstack_work);
return 0; return 0;
} }
...@@ -198,6 +199,12 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) ...@@ -198,6 +199,12 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
pkt_offset += pkt_length; pkt_offset += pkt_length;
} }
} }
/*
* Write the driver's packet counter to the FW. This is only required
* for older hardware revisions
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "cmd.h" #include "cmd.h"
#include "scan.h" #include "scan.h"
#include "acx.h" #include "acx.h"
#include "ps.h"
void wl1271_scan_complete_work(struct work_struct *work) void wl1271_scan_complete_work(struct work_struct *work)
{ {
...@@ -40,10 +41,11 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -40,10 +41,11 @@ void wl1271_scan_complete_work(struct work_struct *work)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->scan.state == WL1271_SCAN_STATE_IDLE) { if (wl->state == WL1271_STATE_OFF)
mutex_unlock(&wl->mutex); goto out;
return;
} if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
goto out;
wl->scan.state = WL1271_SCAN_STATE_IDLE; wl->scan.state = WL1271_SCAN_STATE_IDLE;
kfree(wl->scan.scanned_ch); kfree(wl->scan.scanned_ch);
...@@ -52,13 +54,19 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -52,13 +54,19 @@ void wl1271_scan_complete_work(struct work_struct *work)
ieee80211_scan_completed(wl->hw, false); ieee80211_scan_completed(wl->hw, false);
/* restore hardware connection monitoring template */ /* restore hardware connection monitoring template */
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
if (wl1271_ps_elp_wakeup(wl) == 0) {
wl1271_cmd_build_ap_probe_req(wl, wl->probereq); wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
wl1271_ps_elp_sleep(wl);
}
}
if (wl->scan.failed) { if (wl->scan.failed) {
wl1271_info("Scan completed due to error."); wl1271_info("Scan completed due to error.");
ieee80211_queue_work(wl->hw, &wl->recovery_work); ieee80211_queue_work(wl->hw, &wl->recovery_work);
} }
out:
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h> #include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/wl12xx.h> #include <linux/wl12xx.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -60,7 +61,7 @@ static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) ...@@ -60,7 +61,7 @@ static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
return &(wl_to_func(wl)->dev); return &(wl_to_func(wl)->dev);
} }
static irqreturn_t wl1271_irq(int irq, void *cookie) static irqreturn_t wl1271_hardirq(int irq, void *cookie)
{ {
struct wl1271 *wl = cookie; struct wl1271 *wl = cookie;
unsigned long flags; unsigned long flags;
...@@ -69,17 +70,14 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) ...@@ -69,17 +70,14 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
/* complete the ELP completion */ /* complete the ELP completion */
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
if (wl->elp_compl) { if (wl->elp_compl) {
complete(wl->elp_compl); complete(wl->elp_compl);
wl->elp_compl = NULL; wl->elp_compl = NULL;
} }
if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
ieee80211_queue_work(wl->hw, &wl->irq_work);
set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
spin_unlock_irqrestore(&wl->wl_lock, flags); spin_unlock_irqrestore(&wl->wl_lock, flags);
return IRQ_HANDLED; return IRQ_WAKE_THREAD;
} }
static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
...@@ -106,8 +104,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, ...@@ -106,8 +104,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
int ret; int ret;
struct sdio_func *func = wl_to_func(wl); struct sdio_func *func = wl_to_func(wl);
sdio_claim_host(func);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
...@@ -123,8 +119,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, ...@@ -123,8 +119,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
} }
sdio_release_host(func);
if (ret) if (ret)
wl1271_error("sdio read failed (%d)", ret); wl1271_error("sdio read failed (%d)", ret);
} }
...@@ -135,8 +129,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, ...@@ -135,8 +129,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
int ret; int ret;
struct sdio_func *func = wl_to_func(wl); struct sdio_func *func = wl_to_func(wl);
sdio_claim_host(func);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
...@@ -152,8 +144,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, ...@@ -152,8 +144,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
ret = sdio_memcpy_toio(func, addr, buf, len); ret = sdio_memcpy_toio(func, addr, buf, len);
} }
sdio_release_host(func);
if (ret) if (ret)
wl1271_error("sdio write failed (%d)", ret); wl1271_error("sdio write failed (%d)", ret);
} }
...@@ -163,14 +153,18 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) ...@@ -163,14 +153,18 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
struct sdio_func *func = wl_to_func(wl); struct sdio_func *func = wl_to_func(wl);
int ret; int ret;
/* Power up the card */ /* Make sure the card will not be powered off by runtime PM */
ret = pm_runtime_get_sync(&func->dev); ret = pm_runtime_get_sync(&func->dev);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* Runtime PM might be disabled, so power up the card manually */
ret = mmc_power_restore_host(func->card->host);
if (ret < 0)
goto out;
sdio_claim_host(func); sdio_claim_host(func);
sdio_enable_func(func); sdio_enable_func(func);
sdio_release_host(func);
out: out:
return ret; return ret;
...@@ -179,12 +173,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) ...@@ -179,12 +173,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
static int wl1271_sdio_power_off(struct wl1271 *wl) static int wl1271_sdio_power_off(struct wl1271 *wl)
{ {
struct sdio_func *func = wl_to_func(wl); struct sdio_func *func = wl_to_func(wl);
int ret;
sdio_claim_host(func);
sdio_disable_func(func); sdio_disable_func(func);
sdio_release_host(func); sdio_release_host(func);
/* Power down the card */ /* Runtime PM might be disabled, so power off the card manually */
ret = mmc_power_save_host(func->card->host);
if (ret < 0)
return ret;
/* Let runtime PM know the card is powered off */
return pm_runtime_put_sync(&func->dev); return pm_runtime_put_sync(&func->dev);
} }
...@@ -241,14 +240,14 @@ static int __devinit wl1271_probe(struct sdio_func *func, ...@@ -241,14 +240,14 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl->irq = wlan_data->irq; wl->irq = wlan_data->irq;
wl->ref_clock = wlan_data->board_ref_clock; wl->ref_clock = wlan_data->board_ref_clock;
ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
DRIVER_NAME, wl);
if (ret < 0) { if (ret < 0) {
wl1271_error("request_irq() failed: %d", ret); wl1271_error("request_irq() failed: %d", ret);
goto out_free; goto out_free;
} }
set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
disable_irq(wl->irq); disable_irq(wl->irq);
ret = wl1271_init_ieee80211(wl); ret = wl1271_init_ieee80211(wl);
...@@ -271,7 +270,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, ...@@ -271,7 +270,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
out_irq: out_irq:
free_irq(wl->irq, wl); free_irq(wl->irq, wl);
out_free: out_free:
wl1271_free_hw(wl); wl1271_free_hw(wl);
......
...@@ -320,28 +320,23 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, ...@@ -320,28 +320,23 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
spi_sync(wl_to_spi(wl), &m); spi_sync(wl_to_spi(wl), &m);
} }
static irqreturn_t wl1271_irq(int irq, void *cookie) static irqreturn_t wl1271_hardirq(int irq, void *cookie)
{ {
struct wl1271 *wl; struct wl1271 *wl = cookie;
unsigned long flags; unsigned long flags;
wl1271_debug(DEBUG_IRQ, "IRQ"); wl1271_debug(DEBUG_IRQ, "IRQ");
wl = cookie;
/* complete the ELP completion */ /* complete the ELP completion */
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
if (wl->elp_compl) { if (wl->elp_compl) {
complete(wl->elp_compl); complete(wl->elp_compl);
wl->elp_compl = NULL; wl->elp_compl = NULL;
} }
if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
ieee80211_queue_work(wl->hw, &wl->irq_work);
set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
spin_unlock_irqrestore(&wl->wl_lock, flags); spin_unlock_irqrestore(&wl->wl_lock, flags);
return IRQ_HANDLED; return IRQ_WAKE_THREAD;
} }
static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
...@@ -413,14 +408,14 @@ static int __devinit wl1271_probe(struct spi_device *spi) ...@@ -413,14 +408,14 @@ static int __devinit wl1271_probe(struct spi_device *spi)
goto out_free; goto out_free;
} }
ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
DRIVER_NAME, wl);
if (ret < 0) { if (ret < 0) {
wl1271_error("request_irq() failed: %d", ret); wl1271_error("request_irq() failed: %d", ret);
goto out_free; goto out_free;
} }
set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
disable_irq(wl->irq); disable_irq(wl->irq);
ret = wl1271_init_ieee80211(wl); ret = wl1271_init_ieee80211(wl);
......
...@@ -464,7 +464,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) ...@@ -464,7 +464,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
while ((skb = wl1271_skb_dequeue(wl))) { while ((skb = wl1271_skb_dequeue(wl))) {
if (!woken_up) { if (!woken_up) {
ret = wl1271_ps_elp_wakeup(wl, false); ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) if (ret < 0)
goto out_ack; goto out_ack;
woken_up = true; woken_up = true;
...@@ -506,8 +506,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl) ...@@ -506,8 +506,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
sent_packets = true; sent_packets = true;
} }
if (sent_packets) { if (sent_packets) {
/* interrupt the firmware with the new packets */ /*
wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); * Interrupt the firmware with the new packets. This is only
* required for older hardware revisions
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
wl->tx_packets_count);
wl1271_handle_tx_low_watermark(wl); wl1271_handle_tx_low_watermark(wl);
} }
...@@ -583,7 +589,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, ...@@ -583,7 +589,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
result->rate_class_index, result->status); result->rate_class_index, result->status);
/* return the packet to the stack */ /* return the packet to the stack */
ieee80211_tx_status(wl->hw, skb); skb_queue_tail(&wl->deferred_tx_queue, skb);
ieee80211_queue_work(wl->hw, &wl->netstack_work);
wl1271_free_tx_id(wl, result->id); wl1271_free_tx_id(wl, result->id);
} }
...@@ -687,14 +694,28 @@ void wl1271_tx_reset(struct wl1271 *wl) ...@@ -687,14 +694,28 @@ void wl1271_tx_reset(struct wl1271 *wl)
*/ */
wl1271_handle_tx_low_watermark(wl); wl1271_handle_tx_low_watermark(wl);
for (i = 0; i < ACX_TX_DESCRIPTORS; i++) for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
if (wl->tx_frames[i] != NULL) { if (wl->tx_frames[i] == NULL)
continue;
skb = wl->tx_frames[i]; skb = wl->tx_frames[i];
wl1271_free_tx_id(wl, i); wl1271_free_tx_id(wl, i);
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
/* Remove private headers before passing the skb to mac80211 */
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
if (info->control.hw_key &&
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data,
hdrlen);
skb_pull(skb, WL1271_TKIP_IV_SPACE);
}
info->status.rates[0].idx = -1; info->status.rates[0].idx = -1;
info->status.rates[0].count = 0; info->status.rates[0].count = 0;
ieee80211_tx_status(wl->hw, skb); ieee80211_tx_status(wl->hw, skb);
} }
} }
......
...@@ -130,10 +130,10 @@ extern u32 wl12xx_debug_level; ...@@ -130,10 +130,10 @@ extern u32 wl12xx_debug_level;
#define WL1271_FW_NAME "wl1271-fw-2.bin" #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
#define WL1271_AP_FW_NAME "wl1271-fw-ap.bin" #define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL1271_NVS_NAME "wl1271-nvs.bin" #define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
...@@ -317,10 +317,10 @@ enum wl12xx_flags { ...@@ -317,10 +317,10 @@ enum wl12xx_flags {
WL1271_FLAG_JOINED, WL1271_FLAG_JOINED,
WL1271_FLAG_GPIO_POWER, WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING,
WL1271_FLAG_IN_ELP, WL1271_FLAG_IN_ELP,
WL1271_FLAG_PSM, WL1271_FLAG_PSM,
WL1271_FLAG_PSM_REQUESTED, WL1271_FLAG_PSM_REQUESTED,
WL1271_FLAG_IRQ_PENDING,
WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_IDLE, WL1271_FLAG_IDLE,
WL1271_FLAG_IDLE_REQUESTED, WL1271_FLAG_IDLE_REQUESTED,
...@@ -404,6 +404,12 @@ struct wl1271 { ...@@ -404,6 +404,12 @@ struct wl1271 {
struct sk_buff_head tx_queue[NUM_TX_QUEUES]; struct sk_buff_head tx_queue[NUM_TX_QUEUES];
int tx_queue_count; int tx_queue_count;
/* Frames received, not handled yet by mac80211 */
struct sk_buff_head deferred_rx_queue;
/* Frames sent, not returned yet to mac80211 */
struct sk_buff_head deferred_tx_queue;
struct work_struct tx_work; struct work_struct tx_work;
/* Pending TX frames */ /* Pending TX frames */
...@@ -424,8 +430,8 @@ struct wl1271 { ...@@ -424,8 +430,8 @@ struct wl1271 {
/* Intermediate buffer, used for packet aggregation */ /* Intermediate buffer, used for packet aggregation */
u8 *aggr_buf; u8 *aggr_buf;
/* The target interrupt mask */ /* Network stack work */
struct work_struct irq_work; struct work_struct netstack_work;
/* Hardware recovery work */ /* Hardware recovery work */
struct work_struct recovery_work; struct work_struct recovery_work;
...@@ -535,6 +541,9 @@ struct wl1271 { ...@@ -535,6 +541,9 @@ struct wl1271 {
/* AP-mode - a bitmap of links currently in PS mode in mac80211 */ /* AP-mode - a bitmap of links currently in PS mode in mac80211 */
unsigned long ap_ps_map; unsigned long ap_ps_map;
/* Quirks of specific hardware revisions */
unsigned int quirks;
}; };
struct wl1271_station { struct wl1271_station {
...@@ -553,6 +562,8 @@ int wl1271_plt_stop(struct wl1271 *wl); ...@@ -553,6 +562,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_TX_QUEUE_LOW_WATERMARK 10 #define WL1271_TX_QUEUE_LOW_WATERMARK 10
#define WL1271_TX_QUEUE_HIGH_WATERMARK 25 #define WL1271_TX_QUEUE_HIGH_WATERMARK 25
#define WL1271_DEFERRED_QUEUE_LIMIT 64
/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
on in case is has been shut down shortly before */ on in case is has been shut down shortly before */
#define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */ #define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */
...@@ -562,4 +573,9 @@ int wl1271_plt_stop(struct wl1271 *wl); ...@@ -562,4 +573,9 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define HW_BG_RATES_MASK 0xffff #define HW_BG_RATES_MASK 0xffff
#define HW_HT_RATES_OFFSET 16 #define HW_HT_RATES_OFFSET 16
/* Quirks */
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment