From 0a1d3abcc43231e341b6890b873dc27cba848218 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Thu, 14 Jul 2011 11:50:27 +0300 Subject: [PATCH 001/129] wl12xx: Add support to RX packets payload alignment In case of QoS packets the packet payload isn't aligned to 4 bytes. In that case the mac80211 layer take care of that via memmove() in ieee80211_deliver_skb(). Add support of copy packets from aggregation buffer to the skbs with packet payload aligned care. In case of QoS packets copy the packets in offset of 2 bytes guarantee payload aligned to 4 bytes. Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 39 +++++++++++++++++++++++++------- drivers/net/wireless/wl12xx/rx.h | 8 ++++--- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 0450fb49dbb1..46f4af6ca723 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -38,12 +38,20 @@ static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status, } static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status, - u32 drv_rx_counter) + u32 drv_rx_counter) { return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; } +static bool wl1271_rx_get_unaligned(struct wl1271_fw_common_status *status, + u32 drv_rx_counter) +{ + /* Convert the value to bool */ + return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & + RX_BUF_UNALIGNED_PAYLOAD); +} + static void wl1271_rx_status(struct wl1271 *wl, struct wl1271_rx_descriptor *desc, struct ieee80211_rx_status *status, @@ -89,7 +97,8 @@ static void wl1271_rx_status(struct wl1271 *wl, } } -static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) +static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, + bool unaligned) { struct wl1271_rx_descriptor *desc; struct sk_buff *skb; @@ -97,6 +106,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) u8 *buf; u8 beacon = 0; u8 is_data = 0; + u8 reserved = unaligned ? NET_IP_ALIGN : 0; /* * In PLT mode we seem to get frames and mac80211 warns about them, @@ -131,17 +141,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) return -EINVAL; } - skb = __dev_alloc_skb(length, GFP_KERNEL); + /* skb length not included rx descriptor */ + skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL); if (!skb) { wl1271_error("Couldn't allocate RX frame"); return -ENOMEM; } - buf = skb_put(skb, length); - memcpy(buf, data, length); + /* reserve the unaligned payload(if any) */ + skb_reserve(skb, reserved); - /* now we pull the descriptor out of the buffer */ - skb_pull(skb, sizeof(*desc)); + buf = skb_put(skb, length - sizeof(*desc)); + + /* + * Copy packets from aggregation buffer to the skbs without rx + * descriptor and with packet payload aligned care. In case of unaligned + * packets copy the packets in offset of 2 bytes guarantee IP header + * payload aligned to 4 bytes. + */ + memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_beacon(hdr->frame_control)) @@ -175,6 +193,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) u32 pkt_offset; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool had_data = false; + bool unaligned = false; while (drv_rx_counter != fw_rx_counter) { buf_size = 0; @@ -222,6 +241,10 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) while (pkt_offset < buf_size) { pkt_length = wl1271_rx_get_buf_size(status, drv_rx_counter); + + unaligned = wl1271_rx_get_unaligned(status, + drv_rx_counter); + /* * the handle data call can only fail in memory-outage * conditions, in that case the received frame will just @@ -229,7 +252,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) */ if (wl1271_rx_handle_data(wl, wl->aggr_buf + pkt_offset, - pkt_length) == 1) + pkt_length, unaligned) == 1) had_data = true; wl->rx_counter++; diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index c88e3fa1d603..0325b9de612e 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -93,9 +93,11 @@ #define WL1271_RX_DESC_MIC_FAIL 0x02 #define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03 -#define RX_MEM_BLOCK_MASK 0xFF -#define RX_BUF_SIZE_MASK 0xFFF00 -#define RX_BUF_SIZE_SHIFT_DIV 6 +#define RX_MEM_BLOCK_MASK 0xFF +#define RX_BUF_SIZE_MASK 0xFFF00 +#define RX_BUF_SIZE_SHIFT_DIV 6 +/* If set, the start of IP payload is not 4 bytes aligned */ +#define RX_BUF_UNALIGNED_PAYLOAD BIT(20) enum { WL12XX_RX_CLASS_UNKNOWN, From 6f07b72adaeddc9a90306ab4f2237b90967fd3ce Mon Sep 17 00:00:00 2001 From: Gery Kahn Date: Mon, 18 Jul 2011 14:21:49 +0300 Subject: [PATCH 002/129] wl12xx: fixes for hw_pg_ver and chip id reporting Fix the value of PG version for 128x at sysfs, remove write permissions from PG version (hw_pg_ver) in sysfs and add remove files (hw_pg_ver,bt_coex_state) from sysfs while freeing hardware. New macro names for register Fuse_data_2_1 depend on architecture. Propagate chip id through wiphy in PLT mode which still not work of a bug in ethtool. Signed-off-by: Gery Kahn Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 13 ++++++++----- drivers/net/wireless/wl12xx/boot.h | 3 ++- drivers/net/wireless/wl12xx/main.c | 12 +++++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 5ebc64d89407..a816f2ffa6a9 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -549,13 +549,13 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) { u32 fuse; - fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); + if (wl->chip.id == CHIP_ID_1283_PG20) + fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); + else + fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; 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; } static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) @@ -696,7 +696,8 @@ static int wl127x_boot_clk(struct wl1271 *wl) u32 pause; u32 clk; - wl1271_boot_hw_version(wl); + if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) + wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; if (wl->ref_clock == CONF_REF_CLK_19_2_E || wl->ref_clock == CONF_REF_CLK_38_4_E || @@ -750,6 +751,8 @@ int wl1271_load_firmware(struct wl1271 *wl) u32 tmp, clk; int selected_clock = -1; + wl1271_boot_hw_version(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) { ret = wl128x_boot_clk(wl, &selected_clock); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index e8f8255bbabe..06dad9380fa7 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -55,7 +55,8 @@ struct wl1271_static_data { #define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_PULL 0x0cb4 -#define REG_FUSE_DATA_2_1 0x050a +#define WL127X_REG_FUSE_DATA_2_1 0x050a +#define WL128X_REG_FUSE_DATA_2_1 0x2152 #define PG_VER_MASK 0x3c #define PG_VER_OFFSET 2 diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3418299e17c8..98258fe0e29d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1395,6 +1395,7 @@ out: int wl1271_plt_start(struct wl1271 *wl) { int retries = WL1271_BOOT_RETRIES; + struct wiphy *wiphy = wl->hw->wiphy; int ret; mutex_lock(&wl->mutex); @@ -1428,6 +1429,11 @@ int wl1271_plt_start(struct wl1271 *wl) wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip.id; + strncpy(wiphy->fw_version, wl->chip.fw_ver_str, + sizeof(wiphy->fw_version)); + goto out; irq_disable: @@ -4126,7 +4132,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, return len; } -static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(hw_pg_ver, S_IRUGO, wl1271_sysfs_show_hw_pg_ver, NULL); static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, @@ -4522,6 +4528,10 @@ int wl1271_free_hw(struct wl1271 *wl) mutex_unlock(&wl->mutex); device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr); + + device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + + device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); platform_device_unregister(wl->plat_dev); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); From 7bb5d6ce9e6ebb3bb71915cb0224523d3c284b4f Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:00 +0300 Subject: [PATCH 003/129] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" This does not make sense in fw >= 6/7.3.0.0.75 (wl127x/wl128x) - we don't use Tx blocks to measure FW occupancy anymore. This reverts commit 9e374a37b6fa2310b71d3c5657cd0c1e693120c6. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 5 +- drivers/net/wireless/wl12xx/main.c | 30 ++++-------- drivers/net/wireless/wl12xx/tx.c | 68 +++++++++------------------ drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 4 files changed, 33 insertions(+), 72 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 37934b5601cd..3b5f240d7031 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -339,10 +339,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") DRIVER_STATE_PRINT_INT(tx_blocks_available); - DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]); - DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]); - DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]); - DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks); DRIVER_STATE_PRINT_INT(tx_frames_cnt); DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); DRIVER_STATE_PRINT_INT(tx_queue_count[0]); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 98258fe0e29d..f91875e379a2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -824,24 +824,13 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, } } -static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl) -{ - int i; - u32 total_alloc_blocks = 0; - - for (i = 0; i < NUM_TX_QUEUES; i++) - total_alloc_blocks += wl->tx_allocated_blocks[i]; - - return total_alloc_blocks; -} - static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_full_status *full_status) { struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; - u32 freed_blocks = 0, ac_freed_blocks; + u32 freed_blocks = 0; int i; if (wl->bss_type == BSS_TYPE_AP_BSS) { @@ -861,23 +850,21 @@ static void wl1271_fw_status(struct wl1271 *wl, /* update number of available TX blocks */ for (i = 0; i < NUM_TX_QUEUES; i++) { - ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) - - wl->tx_blocks_freed[i]; - freed_blocks += ac_freed_blocks; - - wl->tx_allocated_blocks[i] -= ac_freed_blocks; + freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - + wl->tx_blocks_freed[i]; wl->tx_blocks_freed[i] = le32_to_cpu(status->tx_released_blks[i]); } + wl->tx_allocated_blocks -= freed_blocks; + if (wl->bss_type == BSS_TYPE_AP_BSS) { /* Update num of allocated TX blocks per link and ps status */ wl1271_irq_update_links_status(wl, &full_status->ap); wl->tx_blocks_available += freed_blocks; } else { - int avail = full_status->sta.tx_total - - wl1271_tx_allocated_blocks(wl); + int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; /* * The FW might change the total number of TX memblocks before @@ -2013,6 +2000,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; + wl->tx_allocated_blocks = 0; wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->time_offset = 0; @@ -2033,10 +2021,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, */ wl->flags = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) { + for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; - wl->tx_allocated_blocks[i] = 0; - } wl1271_debugfs_reset(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 48fde96ce0d4..0696aedaf806 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -168,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 len; u32 total_blocks; - int id, ret = -EBUSY, ac; + int id, ret = -EBUSY; u32 spare_blocks; if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) @@ -206,9 +206,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, desc->id = id; wl->tx_blocks_available -= total_blocks; - - ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - wl->tx_allocated_blocks[ac] += total_blocks; + wl->tx_allocated_blocks += total_blocks; if (wl->bss_type == BSS_TYPE_AP_BSS) wl->links[hlid].allocated_blks += total_blocks; @@ -459,41 +457,21 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl) } } -static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, - struct sk_buff_head *queues) -{ - int i, q = -1; - u32 min_blks = 0xffffffff; - - /* - * Find a non-empty ac where: - * 1. There are packets to transmit - * 2. The FW has the least allocated blocks - */ - for (i = 0; i < NUM_TX_QUEUES; i++) - if (!skb_queue_empty(&queues[i]) && - (wl->tx_allocated_blocks[i] < min_blks)) { - q = i; - min_blks = wl->tx_allocated_blocks[q]; - } - - if (q == -1) - return NULL; - - return &queues[q]; -} - static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) { struct sk_buff *skb = NULL; unsigned long flags; - struct sk_buff_head *queue; - queue = wl1271_select_queue(wl, wl->tx_queue); - if (!queue) + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); + if (skb) goto out; - - skb = skb_dequeue(queue); + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); + if (skb) + goto out; + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); + if (skb) + goto out; + skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); out: if (skb) { @@ -511,7 +489,6 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) struct sk_buff *skb = NULL; unsigned long flags; int i, h, start_hlid; - struct sk_buff_head *queue; /* start from the link after the last one */ start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; @@ -520,20 +497,21 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) for (i = 0; i < AP_MAX_LINKS; i++) { h = (start_hlid + i) % AP_MAX_LINKS; - /* only consider connected stations */ - if (h >= WL1271_AP_STA_HLID_START && - !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) - continue; - - queue = wl1271_select_queue(wl, wl->links[h].tx_queue); - if (!queue) - continue; - - skb = skb_dequeue(queue); + skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]); if (skb) - break; + goto out; + skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]); + if (skb) + goto out; + skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]); + if (skb) + goto out; + skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]); + if (skb) + goto out; } +out: if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->last_tx_hlid = h; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 0bc29356ebe4..5b00a84acab2 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -424,7 +424,7 @@ struct wl1271 { /* Accounting for allocated / available TX blocks on HW */ u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; - u32 tx_allocated_blocks[NUM_TX_QUEUES]; + u32 tx_allocated_blocks; u32 tx_results_count; /* Transmitted TX packets counter for chipset interface */ From c302b2c959164622558474871ae942da0e484a38 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 17 Aug 2011 10:45:48 +0300 Subject: [PATCH 004/129] wl12xx: Use a single fw for both STA and AP roles Firmware >= 6/7.3.0.0.75 (wl127x/wl128x) supports both STA and AP roles. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 31 +++++----------------------- drivers/net/wireless/wl12xx/sdio.c | 4 +--- drivers/net/wireless/wl12xx/spi.c | 4 +--- drivers/net/wireless/wl12xx/wl12xx.h | 7 ++----- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f91875e379a2..7b29573ef244 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1043,25 +1043,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) const char *fw_name; int ret; - switch (wl->bss_type) { - case BSS_TYPE_AP_BSS: - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_AP_FW_NAME; - else - fw_name = WL127X_AP_FW_NAME; - break; - case BSS_TYPE_IBSS: - case BSS_TYPE_STA_BSS: - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME; - else - fw_name = WL1271_FW_NAME; - break; - default: - wl1271_error("no compatible firmware for bss_type %d", - wl->bss_type); - return -EINVAL; - } + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_FW_NAME; + else + fw_name = WL127X_FW_NAME; wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); @@ -1090,7 +1075,6 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) } memcpy(wl->fw, fw->data, wl->fw_len); - wl->fw_bss_type = wl->bss_type; ret = 0; out: @@ -1361,8 +1345,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) goto out; } - /* Make sure the firmware type matches the BSS type */ - if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) { + if (wl->fw == NULL) { ret = wl1271_fetch_firmware(wl); if (ret < 0) goto out; @@ -1796,9 +1779,6 @@ static int wl1271_op_start(struct ieee80211_hw *hw) * * The MAC address is first known when the corresponding interface * is added. That is where we will initialize the hardware. - * - * In addition, we currently have different firmwares for AP and managed - * operation. We will know which to boot according to interface type. */ return 0; @@ -4393,7 +4373,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->hw_pg_ver = -1; wl->bss_type = MAX_BSS_TYPE; wl->set_bss_type = MAX_BSS_TYPE; - wl->fw_bss_type = MAX_BSS_TYPE; wl->last_tx_hlid = 0; wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5cf18c2c23f0..ac2e5661397c 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -412,7 +412,5 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL1271_FW_NAME); +MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL127X_AP_FW_NAME); -MODULE_FIRMWARE(WL128X_AP_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index e0b3736d7e19..0f9718677860 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -486,8 +486,6 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL1271_FW_NAME); +MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL127X_AP_FW_NAME); -MODULE_FIRMWARE(WL128X_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 5b00a84acab2..dc0013e9b9f7 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -130,10 +130,8 @@ extern u32 wl12xx_debug_level; -#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" -#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" -#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" +#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" +#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" /* * wl127x and wl128x are using the same NVS file name. However, the @@ -405,7 +403,6 @@ struct wl1271 { u8 *fw; size_t fw_len; - u8 fw_bss_type; void *nvs; size_t nvs_len; From 2920743a14764eda099700e1eca9a282393cee16 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:02 +0300 Subject: [PATCH 005/129] wl12xx: use 1 spare block in all cases Remove support for firmwares that require 2 spare blocks for packet TX (and delete the WL12XX_QUIRK_USE_2_SPARE_BLOCKS quirk definition) Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 10 ---------- drivers/net/wireless/wl12xx/tx.c | 7 ++----- drivers/net/wireless/wl12xx/wl12xx.h | 6 ------ 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index a816f2ffa6a9..930a638523fb 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -107,16 +107,6 @@ static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl) unsigned int quirks = 0; unsigned int *fw_ver = wl->chip.fw_ver; - /* Only for wl127x */ - if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && - /* Check STA version */ - (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && - (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || - /* Check AP version */ - ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && - (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) - quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; - /* Only new station firmwares support routing fw logs to the host */ if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 0696aedaf806..c67340ff83c8 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -169,12 +169,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 len; u32 total_blocks; int id, ret = -EBUSY; - u32 spare_blocks; - if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) - spare_blocks = 2; - else - spare_blocks = 1; + /* we use 1 spare block */ + u32 spare_blocks = 1; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index dc0013e9b9f7..0bdeae5c802d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -656,12 +656,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) -/* - * Older firmwares use 2 spare TX blocks - * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) - */ -#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) - /* WL128X requires aggregated packets to be aligned to the SDIO block size */ #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) From dbe25cb5eb04b0ffdad582a93f9fe9edd0ed791b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:03 +0300 Subject: [PATCH 006/129] wl12xx: temporarily disable advanced ap functions In order to keep to driver compiling during the patchset, while avoiding one-huge-patch, temporarily disable some advanced ap functions. These changes will be reverted later in the patchset, as part of the patches for advanced ap functions support. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 4 ++++ drivers/net/wireless/wl12xx/tx.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7b29573ef244..4fa760230ac7 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -773,6 +773,7 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } +#if 0 static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks) { bool fw_ps; @@ -823,6 +824,7 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, wl->links[hlid].allocated_blks); } } +#endif static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_full_status *full_status) @@ -861,7 +863,9 @@ static void wl1271_fw_status(struct wl1271 *wl, if (wl->bss_type == BSS_TYPE_AP_BSS) { /* Update num of allocated TX blocks per link and ps status */ +#if 0 wl1271_irq_update_links_status(wl, &full_status->ap); +#endif wl->tx_blocks_available += freed_blocks; } else { int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index c67340ff83c8..938af1de6c2c 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -111,6 +111,7 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, wl1271_acx_set_inconnection_sta(wl, hdr->addr1); } +#if 0 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) { bool fw_ps; @@ -130,6 +131,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) wl1271_ps_link_start(wl, hlid, true); } +#endif u8 wl1271_tx_get_hlid(struct sk_buff *skb) { @@ -384,7 +386,9 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); +#if 0 wl1271_tx_regulate_link(wl, hlid); +#endif } else { wl1271_tx_update_filters(wl, skb); } From 08c1d1c7042330e2280a7718be4ad88c2e8f8268 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:04 +0300 Subject: [PATCH 007/129] wl12xx: remove rx filtering stuff The new fw doesn't support rx_filtering configuration (as a stand-alone command. the rx filtering is done automatically according to the active role). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 28 ------ drivers/net/wireless/wl12xx/acx.h | 118 -------------------------- drivers/net/wireless/wl12xx/boot.c | 3 - drivers/net/wireless/wl12xx/cmd.c | 4 - drivers/net/wireless/wl12xx/debugfs.c | 3 - drivers/net/wireless/wl12xx/init.c | 12 +-- drivers/net/wireless/wl12xx/io.h | 1 - drivers/net/wireless/wl12xx/main.c | 62 ++------------ drivers/net/wireless/wl12xx/reg.h | 75 ---------------- drivers/net/wireless/wl12xx/rx.c | 11 --- drivers/net/wireless/wl12xx/rx.h | 1 - drivers/net/wireless/wl12xx/scan.c | 3 - drivers/net/wireless/wl12xx/tx.c | 4 +- drivers/net/wireless/wl12xx/wl12xx.h | 22 ----- 14 files changed, 8 insertions(+), 339 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 7e33f1f4f3d4..6447a0969ffe 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -183,34 +183,6 @@ out: return ret; } -int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter) -{ - struct acx_rx_config *rx_config; - int ret; - - wl1271_debug(DEBUG_ACX, "acx rx config"); - - rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); - if (!rx_config) { - ret = -ENOMEM; - goto out; - } - - rx_config->config_options = cpu_to_le32(config); - rx_config->filter_options = cpu_to_le32(filter); - - ret = wl1271_cmd_configure(wl, ACX_RX_CFG, - rx_config, sizeof(*rx_config)); - if (ret < 0) { - wl1271_warning("failed to set rx config: %d", ret); - goto out; - } - -out: - kfree(rx_config); - return ret; -} - int wl1271_acx_pd_threshold(struct wl1271 *wl) { struct acx_packet_detection *pd; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index d2eb86eccc04..4ae0085c58ea 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -160,94 +160,6 @@ struct acx_rx_msdu_lifetime { __le32 lifetime; } __packed; -/* - * RX Config Options Table - * Bit Definition - * === ========== - * 31:14 Reserved - * 13 Copy RX Status - when set, write three receive status words - * to top of rx'd MPDUs. - * When cleared, do not write three status words (added rev 1.5) - * 12 Reserved - * 11 RX Complete upon FCS error - when set, give rx complete - * interrupt for FCS errors, after the rx filtering, e.g. unicast - * frames not to us with FCS error will not generate an interrupt. - * 10 SSID Filter Enable - When set, the WiLink discards all beacon, - * probe request, and probe response frames with an SSID that does - * not match the SSID specified by the host in the START/JOIN - * command. - * When clear, the WiLink receives frames with any SSID. - * 9 Broadcast Filter Enable - When set, the WiLink discards all - * broadcast frames. When clear, the WiLink receives all received - * broadcast frames. - * 8:6 Reserved - * 5 BSSID Filter Enable - When set, the WiLink discards any frames - * with a BSSID that does not match the BSSID specified by the - * host. - * When clear, the WiLink receives frames from any BSSID. - * 4 MAC Addr Filter - When set, the WiLink discards any frames - * with a destination address that does not match the MAC address - * of the adaptor. - * When clear, the WiLink receives frames destined to any MAC - * address. - * 3 Promiscuous - When set, the WiLink receives all valid frames - * (i.e., all frames that pass the FCS check). - * When clear, only frames that pass the other filters specified - * are received. - * 2 FCS - When set, the WiLink includes the FCS with the received - * frame. - * When cleared, the FCS is discarded. - * 1 PLCP header - When set, write all data from baseband to frame - * buffer including PHY header. - * 0 Reserved - Always equal to 0. - * - * RX Filter Options Table - * Bit Definition - * === ========== - * 31:12 Reserved - Always equal to 0. - * 11 Association - When set, the WiLink receives all association - * related frames (association request/response, reassocation - * request/response, and disassociation). When clear, these frames - * are discarded. - * 10 Auth/De auth - When set, the WiLink receives all authentication - * and de-authentication frames. When clear, these frames are - * discarded. - * 9 Beacon - When set, the WiLink receives all beacon frames. - * When clear, these frames are discarded. - * 8 Contention Free - When set, the WiLink receives all contention - * free frames. - * When clear, these frames are discarded. - * 7 Control - When set, the WiLink receives all control frames. - * When clear, these frames are discarded. - * 6 Data - When set, the WiLink receives all data frames. - * When clear, these frames are discarded. - * 5 FCS Error - When set, the WiLink receives frames that have FCS - * errors. - * When clear, these frames are discarded. - * 4 Management - When set, the WiLink receives all management - * frames. - * When clear, these frames are discarded. - * 3 Probe Request - When set, the WiLink receives all probe request - * frames. - * When clear, these frames are discarded. - * 2 Probe Response - When set, the WiLink receives all probe - * response frames. - * When clear, these frames are discarded. - * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK - * frames. - * When clear, these frames are discarded. - * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames - * that have reserved frame types and sub types as defined by the - * 802.11 specification. - * When clear, these frames are discarded. - */ -struct acx_rx_config { - struct acx_header header; - - __le32 config_options; - __le32 filter_options; -} __packed; - struct acx_packet_detection { struct acx_header header; @@ -424,35 +336,6 @@ struct acx_event_mask { __le32 high_event_mask; /* Unused */ } __packed; -#define CFG_RX_FCS BIT(2) -#define CFG_RX_ALL_GOOD BIT(3) -#define CFG_UNI_FILTER_EN BIT(4) -#define CFG_BSSID_FILTER_EN BIT(5) -#define CFG_MC_FILTER_EN BIT(6) -#define CFG_MC_ADDR0_EN BIT(7) -#define CFG_MC_ADDR1_EN BIT(8) -#define CFG_BC_REJECT_EN BIT(9) -#define CFG_SSID_FILTER_EN BIT(10) -#define CFG_RX_INT_FCS_ERROR BIT(11) -#define CFG_RX_INT_ENCRYPTED BIT(12) -#define CFG_RX_WR_RX_STATUS BIT(13) -#define CFG_RX_FILTER_NULTI BIT(14) -#define CFG_RX_RESERVE BIT(15) -#define CFG_RX_TIMESTAMP_TSF BIT(16) - -#define CFG_RX_RSV_EN BIT(0) -#define CFG_RX_RCTS_ACK BIT(1) -#define CFG_RX_PRSP_EN BIT(2) -#define CFG_RX_PREQ_EN BIT(3) -#define CFG_RX_MGMT_EN BIT(4) -#define CFG_RX_FCS_ERROR BIT(5) -#define CFG_RX_DATA_EN BIT(6) -#define CFG_RX_CTL_EN BIT(7) -#define CFG_RX_CF_EN BIT(8) -#define CFG_RX_BCN_EN BIT(9) -#define CFG_RX_AUTH_EN BIT(10) -#define CFG_RX_ASSOC_EN BIT(11) - #define SCAN_PASSIVE BIT(0) #define SCAN_5GHZ_BAND BIT(1) #define SCAN_TRIGGERED BIT(2) @@ -1342,7 +1225,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl); int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, size_t len); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); -int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter); int wl1271_acx_pd_threshold(struct wl1271 *wl); int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 930a638523fb..41791ffd26ea 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -845,9 +845,6 @@ int wl1271_boot(struct wl1271 *wl) /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); - /* set the wl1271 default filters */ - wl1271_set_default_filters(wl); - wl1271_event_mbox_config(wl); out: diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 97dd237a9580..b6ef65a57b71 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -382,8 +382,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) for (i = 0; i < ETH_ALEN; i++) bssid[i] = wl->bssid[ETH_ALEN - i - 1]; - join->rx_config_options = cpu_to_le32(wl->rx_config); - join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->bss_type = bss_type; join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); join->supported_rate_set = cpu_to_le32(wl->rate_set); @@ -1004,8 +1002,6 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) goto out; } - cmd->rx_config_options = cpu_to_le32(wl->rx_config); - cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); /* disconnect reason is not used in immediate disconnections */ cmd->type = DISCONNECT_IMMEDIATE; diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 3b5f240d7031..fd1c301be7c7 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -366,9 +366,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(beacon_int); DRIVER_STATE_PRINT_INT(psm_entry_retry); DRIVER_STATE_PRINT_INT(ps_poll_failures); - DRIVER_STATE_PRINT_HEX(filters); - DRIVER_STATE_PRINT_HEX(rx_config); - DRIVER_STATE_PRINT_HEX(rx_filter); DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(rssi_thold); DRIVER_STATE_PRINT_INT(last_rssi_event); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index c3e9a2e4410e..44cd515a057e 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -227,7 +227,7 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl) return 0; } -static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) +static int wl12xx_init_rx_config(struct wl1271 *wl) { int ret; @@ -235,10 +235,6 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) if (ret < 0) return ret; - ret = wl1271_acx_rx_config(wl, config, filter); - if (ret < 0) - return ret; - return 0; } @@ -650,11 +646,7 @@ int wl1271_hw_init(struct wl1271 *wl) return ret; /* RX config */ - ret = wl1271_init_rx_config(wl, - RX_CFG_PROMISCUOUS | RX_CFG_TSF, - RX_FILTER_OPTION_DEF); - /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, - RX_FILTER_OPTION_FILTER_ALL); */ + ret = wl12xx_init_rx_config(wl); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index a2fe4f506ada..e839341dfafe 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -186,6 +186,5 @@ int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); bool wl1271_set_block_size(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl); -void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 4fa760230ac7..7fcdfa3ee1db 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1991,7 +1991,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->vif = NULL; - wl->filters = 0; wl1271_free_ap_keys(wl); memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; @@ -2037,39 +2036,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } -void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) -{ - wl1271_set_default_filters(wl); - - /* combine requested filters with current filter config */ - filters = wl->filters | filters; - - wl1271_debug(DEBUG_FILTERS, "RX filters set: "); - - if (filters & FIF_PROMISC_IN_BSS) { - wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); - wl->rx_config &= ~CFG_UNI_FILTER_EN; - wl->rx_config |= CFG_BSSID_FILTER_EN; - } - if (filters & FIF_BCN_PRBRESP_PROMISC) { - wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); - wl->rx_config &= ~CFG_BSSID_FILTER_EN; - wl->rx_config &= ~CFG_SSID_FILTER_EN; - } - if (filters & FIF_OTHER_BSS) { - wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); - wl->rx_config &= ~CFG_BSSID_FILTER_EN; - } - if (filters & FIF_CONTROL) { - wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); - wl->rx_filter |= CFG_RX_CTL_EN; - } - if (filters & FIF_FCSFAIL) { - wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); - wl->rx_filter |= CFG_RX_FCS_ERROR; - } -} - static int wl1271_dummy_join(struct wl1271 *wl) { int ret = 0; @@ -2079,9 +2045,6 @@ static int wl1271_dummy_join(struct wl1271 *wl) memcpy(wl->bssid, dummy_bssid, ETH_ALEN); - /* pass through frames from all BSS */ - wl1271_configure_filters(wl, FIF_OTHER_BSS); - ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) goto out; @@ -2163,9 +2126,6 @@ static int wl1271_unjoin(struct wl1271 *wl) wl->tx_security_last_seq_lsb = 0; wl->tx_security_seq = 0; - /* stop filtering packets based on bssid */ - wl1271_configure_filters(wl, FIF_OTHER_BSS); - out: return ret; } @@ -2434,18 +2394,11 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, goto out_sleep; } - /* determine, whether supported filter values have changed */ - if (changed == 0) - goto out_sleep; - - /* configure filters */ - wl->filters = *total; - wl1271_configure_filters(wl, 0); - - /* apply configured filters */ - ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); - if (ret < 0) - goto out_sleep; + /* + * the fw doesn't provide an api to configure the filters. instead, + * the filters configuration is based on the active roles / ROC + * state. + */ out_sleep: wl1271_ps_elp_sleep(wl); @@ -3168,9 +3121,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (ret < 0) goto out; - /* filter out all packets not from this BSSID */ - wl1271_configure_filters(wl, 0); - /* Need to update the BSSID (for filtering etc) */ do_join = true; } @@ -4363,8 +4313,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->beacon_int = WL1271_DEFAULT_BEACON_INT; wl->default_key = 0; wl->rx_counter = 0; - wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h index 440a4ee9cb42..3f570f397586 100644 --- a/drivers/net/wireless/wl12xx/reg.h +++ b/drivers/net/wireless/wl12xx/reg.h @@ -296,81 +296,6 @@ ===============================================*/ #define REG_EVENT_MAILBOX_PTR (SCR_PAD1) - -/* Misc */ - -#define REG_ENABLE_TX_RX (ENABLE) -/* - * Rx configuration (filter) information element - * --------------------------------------------- - */ -#define REG_RX_CONFIG (RX_CFG) -#define REG_RX_FILTER (RX_FILTER_CFG) - - -#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 - -/* promiscuous - receives all valid frames */ -#define RX_CFG_PROMISCUOUS 0x0008 - -/* receives frames from any BSSID */ -#define RX_CFG_BSSID 0x0020 - -/* receives frames destined to any MAC address */ -#define RX_CFG_MAC 0x0010 - -#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 -#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 -#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 -#define RX_CFG_ENABLE_ANY_BSSID 0x0000 - -/* discards all broadcast frames */ -#define RX_CFG_DISABLE_BCAST 0x0200 - -#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 -#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 -#define RX_CFG_COPY_RX_STATUS 0x2000 -#define RX_CFG_TSF 0x10000 - -#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ - | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ - | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) - -#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ - | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) - -#define RX_FILTER_OPTION_FILTER_ALL 0 - -#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ - | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) - -#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ - | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ - | CFG_RX_PRSP_EN) - - /*=============================================== EEPROM Read/Write Request 32bit RW ------------------------------------------ diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 46f4af6ca723..7a0c5fe294b2 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -283,14 +283,3 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) jiffies + msecs_to_jiffies(timeout)); } } - -void wl1271_set_default_filters(struct wl1271 *wl) -{ - if (wl->bss_type == BSS_TYPE_AP_BSS) { - wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER; - } else { - wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; - } -} diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index 0325b9de612e..d3c0591665e8 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -131,6 +131,5 @@ struct wl1271_rx_descriptor { void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); -void wl1271_set_default_filters(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index edfe01c321ca..78a9b23a41b8 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -167,9 +167,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, } cmd->params.tx_rate = cpu_to_le32(basic_rate); - cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); - cmd->params.rx_filter_options = - cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; cmd->params.tx_rate = cpu_to_le32(basic_rate); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 938af1de6c2c..8a745fbe0f45 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -90,9 +90,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (!ieee80211_is_auth(hdr->frame_control)) return 0; - wl1271_configure_filters(wl, FIF_OTHER_BSS); - - return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); + return 0; } static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 0bdeae5c802d..7707895120be 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -112,24 +112,6 @@ extern u32 wl12xx_debug_level; true); \ } while (0) -#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \ - CFG_BSSID_FILTER_EN | \ - CFG_MC_FILTER_EN) - -#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ - CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ - CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ - CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) - -#define WL1271_DEFAULT_AP_RX_CONFIG 0 - -#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \ - CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ - CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \ - CFG_RX_ASSOC_EN) - - - #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" @@ -532,10 +514,6 @@ struct wl1271 { struct work_struct rx_streaming_disable_work; struct timer_list rx_streaming_timer; - unsigned int filters; - unsigned int rx_config; - unsigned int rx_filter; - struct completion *elp_compl; struct completion *ps_compl; struct delayed_work elp_work; From 4d56ad9cae9e8553176427adc2335f8a7f4556b2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:05 +0300 Subject: [PATCH 008/129] wl12xx: update fw status struct Update the fw status struct according to the new fw api (fw >= 6/7.0.0.35). All the roles use the same struct now. The memory accounting was changed a bit according to the struct changes. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 5 +- drivers/net/wireless/wl12xx/main.c | 82 +++++++++++---------------- drivers/net/wireless/wl12xx/rx.c | 18 +++--- drivers/net/wireless/wl12xx/rx.h | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 55 ++++++++---------- 5 files changed, 68 insertions(+), 94 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index fd1c301be7c7..3102652c7625 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -349,10 +349,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_packets_count); DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_LHEX(flags); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(session_counter); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7fcdfa3ee1db..96f76b104e75 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -826,22 +826,14 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, } #endif -static void wl1271_fw_status(struct wl1271 *wl, - struct wl1271_fw_full_status *full_status) +static void wl12xx_fw_status(struct wl1271 *wl, + struct wl12xx_fw_status *status) { - struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; - u32 freed_blocks = 0; - int i; + int avail, freed_blocks; - if (wl->bss_type == BSS_TYPE_AP_BSS) { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_ap_status), false); - } else { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_sta_status), false); - } + wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -850,42 +842,36 @@ static void wl1271_fw_status(struct wl1271 *wl, status->drv_rx_counter, status->tx_results_counter); - /* update number of available TX blocks */ - for (i = 0; i < NUM_TX_QUEUES; i++) { - freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - - wl->tx_blocks_freed[i]; - - wl->tx_blocks_freed[i] = - le32_to_cpu(status->tx_released_blks[i]); - } + freed_blocks = le32_to_cpu(status->total_released_blks) - + wl->tx_blocks_freed; + wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); wl->tx_allocated_blocks -= freed_blocks; - if (wl->bss_type == BSS_TYPE_AP_BSS) { - /* Update num of allocated TX blocks per link and ps status */ -#if 0 - wl1271_irq_update_links_status(wl, &full_status->ap); -#endif - wl->tx_blocks_available += freed_blocks; - } else { - int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; + avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; - /* - * The FW might change the total number of TX memblocks before - * we get a notification about blocks being released. Thus, the - * available blocks calculation might yield a temporary result - * which is lower than the actual available blocks. Keeping in - * mind that only blocks that were allocated can be moved from - * TX to RX, tx_blocks_available should never decrease here. - */ - wl->tx_blocks_available = max((int)wl->tx_blocks_available, - avail); - } + /* + * The FW might change the total number of TX memblocks before + * we get a notification about blocks being released. Thus, the + * available blocks calculation might yield a temporary result + * which is lower than the actual available blocks. Keeping in + * mind that only blocks that were allocated can be moved from + * TX to RX, tx_blocks_available should never decrease here. + */ + wl->tx_blocks_available = max((int)wl->tx_blocks_available, + avail); /* if more blocks are available now, tx work can be scheduled */ if (wl->tx_blocks_available > old_tx_blk_count) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); + /* for AP update num of allocated TX blocks per link and ps status */ + if (wl->bss_type == BSS_TYPE_AP_BSS) { +#if 0 + wl1271_irq_update_links_status(wl, status); +#endif + } + /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - @@ -958,8 +944,8 @@ irqreturn_t wl1271_irq(int irq, void *cookie) clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); smp_mb__after_clear_bit(); - wl1271_fw_status(wl, wl->fw_status); - intr = le32_to_cpu(wl->fw_status->common.intr); + wl12xx_fw_status(wl, wl->fw_status); + intr = le32_to_cpu(wl->fw_status->intr); intr &= WL1271_INTR_MASK; if (!intr) { done = true; @@ -978,7 +964,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) if (likely(intr & WL1271_ACX_INTR_DATA)) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - wl1271_rx(wl, &wl->fw_status->common); + wl12xx_rx(wl, wl->fw_status); /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); @@ -995,7 +981,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) } /* check for tx results */ - if (wl->fw_status->common.tx_results_counter != + if (wl->fw_status->tx_results_counter != (wl->tx_results_count & 0xff)) wl1271_tx_complete(wl); @@ -1169,8 +1155,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) wl12xx_cmd_stop_fwlog(wl); /* Read the first memory block address */ - wl1271_fw_status(wl, wl->fw_status); - first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr); + wl12xx_fw_status(wl, wl->fw_status); + first_addr = le32_to_cpu(wl->fw_status->log_start_addr); if (!first_addr) goto out; @@ -1186,7 +1172,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) * of each memory block hold the hardware address of the next * one. The last memory block points to the first one. */ - addr = __le32_to_cpup((__le32 *)block); + addr = le32_to_cpup((__le32 *)block); if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), WL12XX_HW_BLOCK_SIZE - sizeof(addr))) break; @@ -1923,7 +1909,6 @@ out: static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { - int i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2004,8 +1989,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, */ wl->flags = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) - wl->tx_blocks_freed[i] = 0; + wl->tx_blocks_freed = 0; wl1271_debugfs_reset(wl); diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 7a0c5fe294b2..78d8410da1f4 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -30,21 +30,21 @@ #include "rx.h" #include "io.h" -static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status, +static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, u32 drv_rx_counter) { return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_MEM_BLOCK_MASK; } -static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status, - u32 drv_rx_counter) +static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status, + u32 drv_rx_counter) { return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; } -static bool wl1271_rx_get_unaligned(struct wl1271_fw_common_status *status, +static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status, u32 drv_rx_counter) { /* Convert the value to bool */ @@ -181,7 +181,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, return is_data; } -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) +void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; u32 buf_size; @@ -199,7 +199,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) buf_size = 0; rx_counter = drv_rx_counter; while (rx_counter != fw_rx_counter) { - pkt_length = wl1271_rx_get_buf_size(status, rx_counter); + pkt_length = wl12xx_rx_get_buf_size(status, rx_counter); if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) break; buf_size += pkt_length; @@ -218,7 +218,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) * For aggregated packets, only the first memory block * should be retrieved. The FW takes care of the rest. */ - mem_block = wl1271_rx_get_mem_block(status, + mem_block = wl12xx_rx_get_mem_block(status, drv_rx_counter); wl->rx_mem_pool_addr.addr = (mem_block << 8) + @@ -239,10 +239,10 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) /* Split data into separate packets */ pkt_offset = 0; while (pkt_offset < buf_size) { - pkt_length = wl1271_rx_get_buf_size(status, + pkt_length = wl12xx_rx_get_buf_size(status, drv_rx_counter); - unaligned = wl1271_rx_get_unaligned(status, + unaligned = wl12xx_rx_get_unaligned(status, drv_rx_counter); /* diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index d3c0591665e8..00c1c1d27aaa 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -129,7 +129,7 @@ struct wl1271_rx_descriptor { u8 reserved; } __packed; -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status); +void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); #endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7707895120be..f708cd70185a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -137,6 +137,7 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_BEACON_INT 100 #define WL1271_DEFAULT_DTIM_PERIOD 1 +#define WL12XX_MAX_LINKS 8 #define WL1271_AP_GLOBAL_HLID 0 #define WL1271_AP_BROADCAST_HLID 1 #define WL1271_AP_STA_HLID_START 2 @@ -230,23 +231,15 @@ struct wl1271_stats { /* Broadcast and Global links + links to stations */ #define AP_MAX_LINKS (AP_MAX_STATIONS + 2) -/* FW status registers common for AP/STA */ -struct wl1271_fw_common_status { +/* FW status registers */ +struct wl12xx_fw_status { __le32 intr; u8 fw_rx_counter; u8 drv_rx_counter; u8 reserved; u8 tx_results_counter; __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; - __le32 tx_released_blks[NUM_TX_QUEUES]; __le32 fw_localtime; -} __packed; - -/* FW status registers for AP */ -struct wl1271_fw_ap_status { - struct wl1271_fw_common_status common; - - /* Next fields valid only in AP FW */ /* * A bitmap (where each bit represents a single HLID) @@ -254,30 +247,30 @@ struct wl1271_fw_ap_status { */ __le32 link_ps_bitmap; - /* Number of freed MBs per HLID */ - u8 tx_lnk_free_blks[AP_MAX_LINKS]; - u8 padding_1[1]; -} __packed; + /* + * A bitmap (where each bit represents a single HLID) to indicate + * if the station is in Fast mode + */ + __le32 link_fast_bitmap; -/* FW status registers for STA */ -struct wl1271_fw_sta_status { - struct wl1271_fw_common_status common; + /* Cumulative counter of total released mem blocks since FW-reset */ + __le32 total_released_blks; - u8 tx_total; - u8 reserved1; - __le16 reserved2; + /* Size (in Memory Blocks) of TX pool */ + __le32 tx_total; + + /* Cumulative counter of released mem-blocks per AC */ + u8 tx_released_blks[NUM_TX_QUEUES]; + + /* Cumulative counter of freed MBs per HLID */ + u8 tx_lnk_free_blks[WL12XX_MAX_LINKS]; + + /* Cumulative counter of released Voice memory blocks */ + u8 tx_voice_released_blks; + u8 padding_1[7]; __le32 log_start_addr; } __packed; -struct wl1271_fw_full_status { - union { - struct wl1271_fw_common_status common; - struct wl1271_fw_sta_status sta; - struct wl1271_fw_ap_status ap; - }; -} __packed; - - struct wl1271_rx_mem_pool_addr { u32 addr; u32 addr_extra; @@ -401,7 +394,7 @@ struct wl1271 { struct wl1271_acx_mem_map *target_mem_map; /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed[NUM_TX_QUEUES]; + u32 tx_blocks_freed; u32 tx_blocks_available; u32 tx_allocated_blocks; u32 tx_results_count; @@ -537,7 +530,7 @@ struct wl1271 { u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - struct wl1271_fw_full_status *fw_status; + struct wl12xx_fw_status *fw_status; struct wl1271_tx_hw_res_if *tx_res_if; struct ieee80211_vif *vif; From 7f097988f1bff42177b99cb4c8ec62e818d0b1a6 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:06 +0300 Subject: [PATCH 009/129] wl12xx: update acx commands Update the acx commands according to the new fw api (fw >= 6/7.3.0.0.75). The main change in most of the ACXs is the addition of a new role_id/link_id field, which is required for multi-role operation. Currently, we don't really support multi-role, as most of our data (inside wl) is global. As the current fw doesn't support concurrent roles yet, keep it this way and add wl->role_id and wl->sta_hlid to save the active role/link. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 113 +++++++++------------ drivers/net/wireless/wl12xx/acx.h | 142 +++++++++++++++------------ drivers/net/wireless/wl12xx/init.c | 4 +- drivers/net/wireless/wl12xx/main.c | 5 +- drivers/net/wireless/wl12xx/wl12xx.h | 4 + 5 files changed, 138 insertions(+), 130 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 6447a0969ffe..dfb1cbb35acd 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -46,6 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl) goto out; } + wake_up->role_id = wl->role_id; wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->listen_interval = wl->conf.conn.listen_interval; @@ -101,6 +102,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) goto out; } + acx->role_id = wl->role_id; acx->current_tx_power = power * 10; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); @@ -128,6 +130,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl) } /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ + feature->role_id = wl->role_id; feature->data_flow_options = 0; feature->options = 0; @@ -222,6 +225,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) goto out; } + slot->role_id = wl->role_id; slot->wone_index = STATION_WONE_INDEX; slot->slot_time = slot_time; @@ -251,6 +255,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, } /* MAC filtering */ + acx->role_id = wl->role_id; acx->enabled = enable; acx->num_groups = mc_list_len; memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); @@ -280,6 +285,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) wl1271_debug(DEBUG_ACX, "acx service period timeout"); + rx_timeout->role_id = wl->role_id; rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); @@ -316,6 +322,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) goto out; } + rts->role_id = wl->role_id; rts->threshold = cpu_to_le16((u16)rts_threshold); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); @@ -375,6 +382,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) goto out; } + beacon_filter->role_id = wl->role_id; beacon_filter->enable = enable_filter; /* @@ -411,6 +419,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) } /* configure default beacon pass-through rules */ + ie_table->role_id = wl->role_id; ie_table->num_ie = 0; for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); @@ -472,6 +481,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) timeout = wl->conf.conn.bss_lose_timeout; } + acx->role_id = wl->role_id; acx->synch_fail_thold = cpu_to_le32(threshold); acx->bss_lose_timeout = cpu_to_le32(timeout); @@ -619,6 +629,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) goto out; } + bb->role_id = wl->role_id; bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; @@ -648,6 +659,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) goto out; } + acx_aid->role_id = wl->role_id; acx_aid->aid = cpu_to_le16(aid); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); @@ -703,6 +715,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) goto out; } + acx->role_id = wl->role_id; acx->preamble = preamble; ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); @@ -730,6 +743,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, goto out; } + acx->role_id = wl->role_id; acx->ctsprotect = ctsprotect; ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); @@ -761,9 +775,8 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) int wl1271_acx_sta_rate_policies(struct wl1271 *wl) { - struct acx_sta_rate_policy *acx; + struct acx_rate_policy *acx; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; - int idx = 0; int ret = 0; wl1271_debug(DEBUG_ACX, "acx rate policies"); @@ -775,25 +788,30 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) goto out; } + wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", + wl->basic_rate, wl->rate_set); + /* configure one basic rate class */ - idx = ACX_TX_BASIC_RATE; - acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); - acx->rate_class[idx].short_retry_limit = c->short_retry_limit; - acx->rate_class[idx].long_retry_limit = c->long_retry_limit; - acx->rate_class[idx].aflags = c->aflags; + acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); + acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate); + acx->rate_policy.short_retry_limit = c->short_retry_limit; + acx->rate_policy.long_retry_limit = c->long_retry_limit; + acx->rate_policy.aflags = c->aflags; + + ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("Setting of rate policies failed: %d", ret); + goto out; + } /* configure one AP supported rate class */ - idx = ACX_TX_AP_FULL_RATE; - acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); - acx->rate_class[idx].short_retry_limit = c->short_retry_limit; - acx->rate_class[idx].long_retry_limit = c->long_retry_limit; - acx->rate_class[idx].aflags = c->aflags; + acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); + acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set); + acx->rate_policy.short_retry_limit = c->short_retry_limit; + acx->rate_policy.long_retry_limit = c->long_retry_limit; + acx->rate_policy.aflags = c->aflags; - acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); - wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", - acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates, - acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates); ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); if (ret < 0) { @@ -809,7 +827,7 @@ out: int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx) { - struct acx_ap_rate_policy *acx; + struct acx_rate_policy *acx; int ret = 0; wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", @@ -855,6 +873,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, goto out; } + acx->role_id = wl->role_id; acx->ac = ac; acx->cw_min = cw_min; acx->cw_max = cpu_to_le16(cw_max); @@ -888,6 +907,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, goto out; } + acx->role_id = wl->role_id; acx->queue_id = queue_id; acx->channel_type = channel_type; acx->tsid = tsid; @@ -967,52 +987,9 @@ out: return ret; } -int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) +int wl12xx_acx_mem_cfg(struct wl1271 *wl) { - struct wl1271_acx_ap_config_memory *mem_conf; - struct conf_memory_settings *mem; - int ret; - - wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); - - mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); - if (!mem_conf) { - ret = -ENOMEM; - goto out; - } - - if (wl->chip.id == CHIP_ID_1283_PG20) - /* - * FIXME: The 128x AP FW does not yet support dynamic memory. - * Use the base memory configuration for 128x for now. This - * should be fine tuned in the future. - */ - mem = &wl->conf.mem_wl128x; - else - mem = &wl->conf.mem_wl127x; - - /* memory config */ - mem_conf->num_stations = mem->num_stations; - mem_conf->rx_mem_block_num = mem->rx_block_num; - mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; - mem_conf->num_ssid_profiles = mem->ssid_profiles; - mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); - - ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, - sizeof(*mem_conf)); - if (ret < 0) { - wl1271_warning("wl1271 mem config failed: %d", ret); - goto out; - } - -out: - kfree(mem_conf); - return ret; -} - -int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) -{ - struct wl1271_acx_sta_config_memory *mem_conf; + struct wl12xx_acx_config_memory *mem_conf; struct conf_memory_settings *mem; int ret; @@ -1155,6 +1132,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) goto out; } + acx->role_id = wl->role_id; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->max_consecutive = wl->conf.conn.bet_max_consecutive; @@ -1182,6 +1160,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) goto out; } + acx->role_id = wl->role_id; acx->version = ACX_IPV4_VERSION; acx->enable = enable; @@ -1241,6 +1220,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) goto out; } + acx->role_id = wl->role_id; acx->enabled = enable; ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); @@ -1267,6 +1247,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) goto out; } + acx->role_id = wl->role_id; acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->index = index; acx->tpl_validation = tpl_valid; @@ -1300,6 +1281,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, wl->last_rssi_event = -1; + acx->role_id = wl->role_id; acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->type = WL1271_ACX_TRIG_TYPE_EDGE; @@ -1338,6 +1320,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) goto out; } + acx->role_id = wl->role_id; acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_data = c->avg_weight_rssi_data; acx->snr_beacon = c->avg_weight_snr_beacon; @@ -1359,7 +1342,6 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, bool allow_ht_operation) { struct wl1271_acx_ht_capabilities *acx; - u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int ret = 0; u32 ht_capabilites = 0; @@ -1390,7 +1372,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, acx->ampdu_min_spacing = ht_cap->ampdu_density; } - memcpy(acx->mac_address, mac_address, ETH_ALEN); + acx->hlid = wl->sta_hlid; acx->ht_capabilites = cpu_to_le32(ht_capabilites); ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); @@ -1418,6 +1400,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, goto out; } + acx->role_id = wl->role_id; acx->ht_protection = (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); acx->rifs_mode = 0; @@ -1578,6 +1561,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) if (!(conf_queues & BIT(i))) continue; + rx_streaming->role_id = wl->role_id; rx_streaming->tid = i; rx_streaming->enable = enable_queues & BIT(i); rx_streaming->period = wl->conf.rx_streaming.interval; @@ -1607,6 +1591,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) if (!acx) return -ENOMEM; + acx->role_id = wl->role_id; acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 4ae0085c58ea..67258a15de21 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -101,6 +101,17 @@ struct acx_error_counter { __le32 seq_num_miss; } __packed; +enum wl12xx_role { + WL1271_ROLE_STA = 0, + WL1271_ROLE_IBSS, + WL1271_ROLE_AP, + WL1271_ROLE_DEVICE, + WL1271_ROLE_P2P_CL, + WL1271_ROLE_P2P_GO, + + WL12XX_INVALID_ROLE_TYPE = 0xff +}; + enum wl1271_psm_mode { /* Active mode */ WL1271_PSM_CAM = 0, @@ -179,9 +190,10 @@ enum acx_slot_type { struct acx_slot { struct acx_header header; + u8 role_id; u8 wone_index; /* Reserved */ u8 slot_time; - u8 reserved[6]; + u8 reserved[5]; } __packed; @@ -191,29 +203,35 @@ struct acx_slot { struct acx_dot11_grp_addr_tbl { struct acx_header header; + u8 role_id; u8 enabled; u8 num_groups; - u8 pad[2]; + u8 pad[1]; u8 mac_table[ADDRESS_GROUP_MAX_LEN]; } __packed; struct acx_rx_timeout { struct acx_header header; + u8 role_id; + u8 reserved; __le16 ps_poll_timeout; __le16 upsd_timeout; + u8 padding[2]; } __packed; struct acx_rts_threshold { struct acx_header header; + u8 role_id; + u8 reserved; __le16 threshold; - u8 pad[2]; } __packed; struct acx_beacon_filter_option { struct acx_header header; + u8 role_id; u8 enable; /* * The number of beacons without the unicast TIM @@ -223,7 +241,7 @@ struct acx_beacon_filter_option { * without the unicast TIM bit set are dropped. */ u8 max_num_beacons; - u8 pad[2]; + u8 pad[1]; } __packed; /* @@ -262,14 +280,17 @@ struct acx_beacon_filter_option { struct acx_beacon_filter_ie_table { struct acx_header header; + u8 role_id; u8 num_ie; - u8 pad[3]; + u8 pad[2]; u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; } __packed; struct acx_conn_monit_params { struct acx_header header; + u8 role_id; + u8 padding[3]; __le32 synch_fail_thold; /* number of beacons missed */ __le32 bss_lose_timeout; /* number of TU's from synch fail */ } __packed; @@ -318,15 +339,16 @@ struct acx_energy_detection { struct acx_beacon_broadcast { struct acx_header header; - __le16 beacon_rx_timeout; - __le16 broadcast_timeout; - + u8 role_id; /* Enables receiving of broadcast packets in PS mode */ u8 rx_broadcast_in_ps; + __le16 beacon_rx_timeout; + __le16 broadcast_timeout; + /* Consecutive PS Poll failures before updating the host */ u8 ps_poll_threshold; - u8 pad[2]; + u8 pad[1]; } __packed; struct acx_event_mask { @@ -348,6 +370,8 @@ struct acx_event_mask { struct acx_feature_config { struct acx_header header; + u8 role_id; + u8 padding[3]; __le32 options; __le32 data_flow_options; } __packed; @@ -355,16 +379,18 @@ struct acx_feature_config { struct acx_current_tx_power { struct acx_header header; + u8 role_id; u8 current_tx_power; - u8 padding[3]; + u8 padding[2]; } __packed; struct acx_wake_up_condition { struct acx_header header; + u8 role_id; u8 wake_up_event; /* Only one bit can be set */ u8 listen_interval; - u8 pad[2]; + u8 pad[1]; } __packed; struct acx_aid { @@ -373,8 +399,9 @@ struct acx_aid { /* * To be set when associated with an AP. */ + u8 role_id; + u8 reserved; __le16 aid; - u8 pad[2]; } __packed; enum acx_preamble_type { @@ -389,8 +416,9 @@ struct acx_preamble { * When set, the WiLink transmits the frames with a short preamble and * when cleared, the WiLink transmits the frames with a long preamble. */ + u8 role_id; u8 preamble; - u8 padding[3]; + u8 padding[2]; } __packed; enum acx_ctsprotect_type { @@ -400,8 +428,9 @@ enum acx_ctsprotect_type { struct acx_ctsprotect { struct acx_header header; + u8 role_id; u8 ctsprotect; - u8 padding[3]; + u8 padding[2]; } __packed; struct acx_tx_statistics { @@ -636,18 +665,9 @@ struct acx_rate_class { #define ACX_TX_BASIC_RATE 0 #define ACX_TX_AP_FULL_RATE 1 -#define ACX_TX_RATE_POLICY_CNT 2 -struct acx_sta_rate_policy { - struct acx_header header; - - __le32 rate_class_cnt; - struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; -} __packed; - - #define ACX_TX_AP_MODE_MGMT_RATE 4 #define ACX_TX_AP_MODE_BCST_RATE 5 -struct acx_ap_rate_policy { +struct acx_rate_policy { struct acx_header header; __le32 rate_policy_idx; @@ -656,22 +676,23 @@ struct acx_ap_rate_policy { struct acx_ac_cfg { struct acx_header header; + u8 role_id; u8 ac; + u8 aifsn; u8 cw_min; __le16 cw_max; - u8 aifsn; - u8 reserved; __le16 tx_op_limit; } __packed; struct acx_tid_config { struct acx_header header; + u8 role_id; u8 queue_id; u8 channel_type; u8 tsid; u8 ps_scheme; u8 ack_policy; - u8 padding[3]; + u8 padding[2]; __le32 apsd_conf[2]; } __packed; @@ -687,19 +708,7 @@ struct acx_tx_config_options { __le16 tx_compl_threshold; /* number of packets */ } __packed; -#define ACX_TX_DESCRIPTORS 32 - -struct wl1271_acx_ap_config_memory { - struct acx_header header; - - u8 rx_mem_block_num; - u8 tx_min_mem_block_num; - u8 num_stations; - u8 num_ssid_profiles; - __le32 total_tx_descriptors; -} __packed; - -struct wl1271_acx_sta_config_memory { +struct wl12xx_acx_config_memory { struct acx_header header; u8 rx_mem_block_num; @@ -773,9 +782,10 @@ struct wl1271_acx_rx_config_opt { struct wl1271_acx_bet_enable { struct acx_header header; + u8 role_id; u8 enable; u8 max_consecutive; - u8 padding[2]; + u8 padding[1]; } __packed; #define ACX_IPV4_VERSION 4 @@ -788,9 +798,10 @@ struct wl1271_acx_bet_enable { struct wl1271_acx_arp_filter { struct acx_header header; + u8 role_id; u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ u8 enable; /* bitmap of enabled ARP filtering features */ - u8 padding[2]; + u8 padding[1]; u8 address[16]; /* The configured device IP address - all ARP requests directed to this IP address will pass through. For IPv4, the first four bytes are @@ -808,8 +819,9 @@ struct wl1271_acx_pm_config { struct wl1271_acx_keep_alive_mode { struct acx_header header; + u8 role_id; u8 enabled; - u8 padding[3]; + u8 padding[2]; } __packed; enum { @@ -825,11 +837,11 @@ enum { struct wl1271_acx_keep_alive_config { struct acx_header header; - __le32 period; + u8 role_id; u8 index; u8 tpl_validation; u8 trigger; - u8 padding; + __le32 period; } __packed; #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) @@ -873,20 +885,23 @@ enum { struct wl1271_acx_rssi_snr_trigger { struct acx_header header; - __le16 threshold; - __le16 pacing; /* 0 - 60000 ms */ + u8 role_id; u8 metric; u8 type; u8 dir; + __le16 threshold; + __le16 pacing; /* 0 - 60000 ms */ u8 hysteresis; u8 index; u8 enable; - u8 padding[2]; + u8 padding[1]; }; struct wl1271_acx_rssi_snr_avg_weights { struct acx_header header; + u8 role_id; + u8 padding[3]; u8 rssi_beacon; u8 rssi_data; u8 snr_beacon; @@ -916,13 +931,8 @@ struct wl1271_acx_ht_capabilities { */ __le32 ht_capabilites; - /* - * Indicates to which peer these capabilities apply. - * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance - * for all peers. - * Only valid for IBSS/DLS operation. - */ - u8 mac_address[ETH_ALEN]; + /* Indicates to which link these capabilities apply. */ + u8 hlid; /* * This the maximum A-MPDU length supported by the AP. The FW may not @@ -932,6 +942,8 @@ struct wl1271_acx_ht_capabilities { /* This is the minimal spacing required when sending A-MPDUs to the AP*/ u8 ampdu_min_spacing; + + u8 padding; } __packed; /* HT Capabilites Fw Bit Mask Mapping */ @@ -950,6 +962,8 @@ struct wl1271_acx_ht_capabilities { struct wl1271_acx_ht_information { struct acx_header header; + u8 role_id; + /* Values: 0 - RIFS not allowed, 1 - RIFS allowed */ u8 rifs_mode; @@ -971,7 +985,7 @@ struct wl1271_acx_ht_information { */ u8 dual_cts_protection; - u8 padding[3]; + u8 padding[2]; } __packed; #define RX_BA_WIN_SIZE 8 @@ -1041,6 +1055,7 @@ struct wl1271_acx_fw_tsf_information { struct wl1271_acx_ps_rx_streaming { struct acx_header header; + u8 role_id; u8 tid; u8 enable; @@ -1049,17 +1064,20 @@ struct wl1271_acx_ps_rx_streaming { /* timeout before first trigger (0-200 msec) */ u8 timeout; + u8 padding[3]; } __packed; struct wl1271_acx_ap_max_tx_retry { struct acx_header header; + u8 role_id; + u8 padding_1; + /* * the number of frames transmission failures before * issuing the aging event. */ __le16 max_tx_retry; - u8 padding_1[2]; } __packed; struct wl1271_acx_config_ps { @@ -1151,10 +1169,7 @@ enum { ACX_AC_CFG = 0x0007, ACX_MEM_MAP = 0x0008, ACX_AID = 0x000A, - /* ACX_FW_REV is missing in the ref driver, but seems to work */ - ACX_FW_REV = 0x000D, ACX_MEDIUM_USAGE = 0x000F, - ACX_RX_CFG = 0x0010, ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ ACX_STATISTICS = 0x0013, /* Debug API */ ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, @@ -1170,7 +1185,6 @@ enum { ACX_CCA_THRESHOLD = 0x0025, ACX_EVENT_MBOX_MASK = 0x0026, ACX_CONN_MONIT_PARAMS = 0x002D, - ACX_CONS_TX_FAILURE = 0x002F, ACX_BCN_DTIM_OPTIONS = 0x0031, ACX_SG_ENABLE = 0x0032, ACX_SG_CFG = 0x0033, @@ -1202,6 +1216,9 @@ enum { ACX_PEER_HT_CAP = 0x0057, ACX_HT_BSS_OPERATION = 0x0058, ACX_COEX_ACTIVITY = 0x0059, + ACX_BURST_MODE = 0x005C, + ACX_SET_RATE_MGMT_PARAMS = 0x005D, + ACX_SET_RATE_ADAPT_PARAMS = 0x0060, ACX_SET_DCO_ITRIM_PARAMS = 0x0061, ACX_GEN_FW_CMD = 0x0070, ACX_HOST_IF_CFG_BITMAP = 0x0071, @@ -1256,8 +1273,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u32 apsd_conf0, u32 apsd_conf1); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); -int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); -int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); +int wl12xx_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 44cd515a057e..5a3325761d04 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -388,7 +388,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_sta_mem_cfg(wl); + ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) return ret; @@ -447,7 +447,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_ap_mem_cfg(wl); + ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 96f76b104e75..07d50b761610 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -718,7 +718,7 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; - ret = wl1271_acx_sta_mem_cfg(wl); + ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) goto out_free_memmap; @@ -1981,6 +1981,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; wl->sched_scanning = false; + wl->role_id = WL12XX_INVALID_ROLE_ID; /* * this is performed after the cancel_work calls and the associated @@ -4317,6 +4318,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sched_scanning = false; wl->tx_security_seq = 0; wl->tx_security_last_seq_lsb = 0; + wl->role_id = WL12XX_INVALID_ROLE_ID; + wl->sta_hlid = WL12XX_INVALID_LINK_ID; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index f708cd70185a..9f71dc75a01b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -138,6 +138,8 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_DTIM_PERIOD 1 #define WL12XX_MAX_LINKS 8 +#define WL12XX_INVALID_ROLE_ID 0xff +#define WL12XX_INVALID_LINK_ID 0xff #define WL1271_AP_GLOBAL_HLID 0 #define WL1271_AP_BROADCAST_HLID 1 #define WL1271_AP_STA_HLID_START 2 @@ -390,6 +392,8 @@ struct wl1271 { u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; int channel; + u8 role_id; + u8 sta_hlid; struct wl1271_acx_mem_map *target_mem_map; From c690ec816f9fa2ab2b6200c5b79b6933acca49a4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:07 +0300 Subject: [PATCH 010/129] wl12xx: update commands & events Change the commands and events according to the new fw api (fw >= 6/7.3.0.0.75). The main change is the replacement of JOIN/DISCONNECT commands, with ROLE_START/ROLE_STOP commands. The use of these commands should be preceded by the ROLE_ENABLE command (allocating role resources), and followed by the ROLE_DISABLE command (freeing role resources). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 17 +- drivers/net/wireless/wl12xx/cmd.c | 537 ++++++++++++++++----------- drivers/net/wireless/wl12xx/cmd.h | 314 ++++++++-------- drivers/net/wireless/wl12xx/event.c | 4 +- drivers/net/wireless/wl12xx/event.h | 78 ++-- drivers/net/wireless/wl12xx/init.c | 6 - drivers/net/wireless/wl12xx/main.c | 26 +- drivers/net/wireless/wl12xx/tx.c | 5 +- drivers/net/wireless/wl12xx/wl12xx.h | 5 + 9 files changed, 537 insertions(+), 455 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 41791ffd26ea..cc70422c0575 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -494,21 +494,18 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl->event_mask = BSS_LOSE_EVENT_ID | SCAN_COMPLETE_EVENT_ID | PS_REPORT_EVENT_ID | - JOIN_EVENT_COMPLETE_ID | DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | SOFT_GEMINI_SENSE_EVENT_ID | PERIODIC_SCAN_REPORT_EVENT_ID | - PERIODIC_SCAN_COMPLETE_EVENT_ID; - - if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | - INACTIVE_STA_EVENT_ID | - MAX_TX_RETRY_EVENT_ID; - else - wl->event_mask |= DUMMY_PACKET_EVENT_ID | - BA_SESSION_RX_CONSTRAINT_EVENT_ID; + PERIODIC_SCAN_COMPLETE_EVENT_ID | + DUMMY_PACKET_EVENT_ID | + PEER_REMOVE_COMPLETE_EVENT_ID | + BA_SESSION_RX_CONSTRAINT_EVENT_ID | + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | + INACTIVE_STA_EVENT_ID | + MAX_TX_RETRY_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b6ef65a57b71..b13eed129a92 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -363,61 +363,294 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) return 0; } -int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) { - struct wl1271_cmd_join *join; - int ret, i; - u8 *bssid; + struct wl12xx_cmd_role_enable *cmd; + int ret; - join = kzalloc(sizeof(*join), GFP_KERNEL); - if (!join) { + wl1271_debug(DEBUG_CMD, "cmd role enable"); + + if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID)) + return -EBUSY; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { ret = -ENOMEM; goto out; } - wl1271_debug(DEBUG_CMD, "cmd join"); - - /* Reverse order BSSID */ - bssid = (u8 *) &join->bssid_lsb; - for (i = 0; i < ETH_ALEN; i++) - bssid[i] = wl->bssid[ETH_ALEN - i - 1]; - - join->bss_type = bss_type; - join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); - join->supported_rate_set = cpu_to_le32(wl->rate_set); - - if (wl->band == IEEE80211_BAND_5GHZ) - join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; - - join->beacon_interval = cpu_to_le16(wl->beacon_int); - join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; - - join->channel = wl->channel; - join->ssid_len = wl->ssid_len; - memcpy(join->ssid, wl->ssid, wl->ssid_len); - - join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; - - wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", - join->basic_rate_set, join->supported_rate_set); - - ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd join"); + /* get role id */ + cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES); + if (cmd->role_id >= WL12XX_MAX_ROLES) { + ret = -EBUSY; goto out_free; } - ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); - if (ret < 0) - wl1271_error("cmd join event completion error"); + memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); + cmd->role_type = role_type; + + ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto out_free; + } + + __set_bit(cmd->role_id, wl->roles_map); + *role_id = cmd->role_id; out_free: - kfree(join); + kfree(cmd); out: return ret; } +int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) +{ + struct wl12xx_cmd_role_disable *cmd; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd role disable"); + + if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID)) + return -ENOENT; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + cmd->role_id = *role_id; + + ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role disable"); + goto out_free; + } + + __clear_bit(*role_id, wl->roles_map); + *role_id = WL12XX_INVALID_ROLE_ID; + +out_free: + kfree(cmd); + +out: + return ret; +} + +static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) +{ + u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); + if (link >= WL12XX_MAX_LINKS) + return -EBUSY; + + __set_bit(link, wl->links_map); + *hlid = link; + return 0; +} + +static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) +{ + if (*hlid == WL12XX_INVALID_LINK_ID) + return; + + __clear_bit(*hlid, wl->links_map); + *hlid = WL12XX_INVALID_LINK_ID; +} + +int wl12xx_cmd_role_start_sta(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_start *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); + + cmd->role_id = wl->role_id; + if (wl->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wl->channel; + cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; + cmd->sta.ssid_len = wl->ssid_len; + memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); + memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wl->rate_set); + + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->sta_hlid); + if (ret) + goto out_free; + } + cmd->sta.hlid = wl->sta_hlid; + cmd->sta.session = wl->session_counter; + cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " + "basic_rate_set: 0x%x, remote_rates: 0x%x", + wl->role_id, cmd->sta.hlid, cmd->sta.session, + wl->basic_rate_set, wl->rate_set); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role start sta"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error. */ + wl12xx_free_link(wl, &wl->sta_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); + + cmd->role_id = wl->role_id; + cmd->disc_type = DISCONNECT_IMMEDIATE; + cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop sta"); + goto out_free; + } + + ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); + if (ret < 0) { + wl1271_error("cmd role stop sta event completion error"); + goto out_free; + } + + wl12xx_free_link(wl, &wl->sta_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_start_ap(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_start *cmd; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); + + /* + * We currently do not support hidden SSID. The real SSID + * should be fetched from mac80211 first. + */ + if (wl->ssid_len == 0) { + wl1271_warning("Hidden SSID currently not supported for AP"); + ret = -EINVAL; + goto out; + } + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->role_id = wl->role_id; + cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); + cmd->ap.bss_index = WL1271_AP_BSS_INDEX; + cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID; + cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID; + cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->ap.dtim_interval = bss_conf->dtim_period; + cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; + cmd->channel = wl->channel; + cmd->ap.ssid_len = wl->ssid_len; + cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; + memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); + cmd->ap.local_rates = cpu_to_le32(0xffffffff); + + switch (wl->band) { + case IEEE80211_BAND_2GHZ: + cmd->band = RADIO_BAND_2_4GHZ; + break; + case IEEE80211_BAND_5GHZ: + cmd->band = RADIO_BAND_5GHZ; + break; + default: + wl1271_warning("ap start - unknown band: %d", (int)wl->band); + cmd->band = RADIO_BAND_2_4GHZ; + break; + } + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role start ap"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); + + cmd->role_id = wl->role_id; + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop ap"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + + /** * send test command to firmware * @@ -565,6 +798,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) goto out; } + ps_params->role_id = wl->role_id; ps_params->ps_mode = ps_mode; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, @@ -811,9 +1045,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) wl->basic_rate); } -int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) +int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) { - struct wl1271_cmd_set_sta_keys *cmd; + struct wl1271_cmd_set_keys *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); @@ -824,7 +1058,9 @@ int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) goto out; } - cmd->id = id; + cmd->hlid = hlid; + cmd->key_id = id; + cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; cmd->key_action = cpu_to_le16(KEY_SET_ID); cmd->key_type = KEY_WEP; @@ -840,42 +1076,11 @@ out: return ret; } -int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) -{ - struct wl1271_cmd_set_ap_keys *cmd; - int ret = 0; - - wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->hlid = WL1271_AP_BROADCAST_HLID; - cmd->key_id = id; - cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; - cmd->key_action = cpu_to_le16(KEY_SET_ID); - cmd->key_type = KEY_WEP; - - ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret); - goto out; - } - -out: - kfree(cmd); - - return ret; -} - int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16) { - struct wl1271_cmd_set_sta_keys *cmd; + struct wl1271_cmd_set_keys *cmd; int ret = 0; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -884,8 +1089,14 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, goto out; } - if (key_type != KEY_WEP) - memcpy(cmd->addr, addr, ETH_ALEN); + cmd->hlid = wl->sta_hlid; + + if (key_type == KEY_WEP) + cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; + else if (is_broadcast_ether_addr(addr)) + cmd->lid_key_type = BROADCAST_LID_TYPE; + else + cmd->lid_key_type = UNICAST_LID_TYPE; cmd->key_action = cpu_to_le16(action); cmd->key_size = key_size; @@ -894,10 +1105,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); - /* we have only one SSID profile */ - cmd->ssid_profile = 0; - - cmd->id = id; + cmd->key_id = id; if (key_type == KEY_TKIP) { /* @@ -928,11 +1136,15 @@ out: return ret; } +/* + * TODO: merge with sta/ibss into 1 set_key function. + * note there are slight diffs + */ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16) { - struct wl1271_cmd_set_ap_keys *cmd; + struct wl1271_cmd_set_keys *cmd; int ret = 0; u8 lid_type; @@ -989,45 +1201,12 @@ out: return ret; } -int wl1271_cmd_disconnect(struct wl1271 *wl) +int wl12xx_cmd_set_peer_state(struct wl1271 *wl) { - struct wl1271_cmd_disconnect *cmd; + struct wl12xx_cmd_set_peer_state *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd disconnect"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - /* disconnect reason is not used in immediate disconnections */ - cmd->type = DISCONNECT_IMMEDIATE; - - ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to send disconnect command"); - goto out_free; - } - - ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); - if (ret < 0) - wl1271_error("cmd disconnect event completion error"); - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl1271_cmd_set_sta_state(struct wl1271 *wl) -{ - struct wl1271_cmd_set_sta_state *cmd; - int ret = 0; - - wl1271_debug(DEBUG_CMD, "cmd set sta state"); + wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", wl->sta_hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1035,11 +1214,12 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl) goto out; } + cmd->hlid = wl->sta_hlid; cmd->state = WL1271_CMD_STA_STATE_CONNECTED; - ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send set STA state command"); + wl1271_error("failed to send set peer state command"); goto out_free; } @@ -1049,106 +1229,12 @@ out_free: out: return ret; } - -int wl1271_cmd_start_bss(struct wl1271 *wl) +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) { - struct wl1271_cmd_bss_start *cmd; - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + struct wl12xx_cmd_add_peer *cmd; int ret; - wl1271_debug(DEBUG_CMD, "cmd start bss"); - - /* - * FIXME: We currently do not support hidden SSID. The real SSID - * should be fetched from mac80211 first. - */ - if (wl->ssid_len == 0) { - wl1271_warning("Hidden SSID currently not supported for AP"); - ret = -EINVAL; - goto out; - } - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); - - cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); - cmd->bss_index = WL1271_AP_BSS_INDEX; - cmd->global_hlid = WL1271_AP_GLOBAL_HLID; - cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; - cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set); - cmd->beacon_interval = cpu_to_le16(wl->beacon_int); - cmd->dtim_interval = bss_conf->dtim_period; - cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP; - cmd->channel = wl->channel; - cmd->ssid_len = wl->ssid_len; - cmd->ssid_type = SSID_TYPE_PUBLIC; - memcpy(cmd->ssid, wl->ssid, wl->ssid_len); - - switch (wl->band) { - case IEEE80211_BAND_2GHZ: - cmd->band = RADIO_BAND_2_4GHZ; - break; - case IEEE80211_BAND_5GHZ: - cmd->band = RADIO_BAND_5GHZ; - break; - default: - wl1271_warning("bss start - unknown band: %d", (int)wl->band); - cmd->band = RADIO_BAND_2_4GHZ; - break; - } - - ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd start bss"); - goto out_free; - } - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl1271_cmd_stop_bss(struct wl1271 *wl) -{ - struct wl1271_cmd_bss_start *cmd; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd stop bss"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->bss_index = WL1271_AP_BSS_INDEX; - - ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd stop bss"); - goto out_free; - } - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) -{ - struct wl1271_cmd_add_sta *cmd; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid); + wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1168,11 +1254,11 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta->supp_rates[wl->band])); - wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); + wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates); - ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to initiate cmd add sta"); + wl1271_error("failed to initiate cmd add peer"); goto out_free; } @@ -1183,12 +1269,12 @@ out: return ret; } -int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) +int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) { - struct wl1271_cmd_remove_sta *cmd; + struct wl12xx_cmd_remove_peer *cmd; int ret; - wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); + wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1201,9 +1287,9 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) cmd->reason_opcode = 0; cmd->send_deauth_flag = 0; - ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to initiate cmd remove sta"); + wl1271_error("failed to initiate cmd remove peer"); goto out_free; } @@ -1211,7 +1297,8 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) * We are ok with a timeout here. The event is sometimes not sent * due to a firmware bug. */ - wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); + wl1271_cmd_wait_for_event_or_timeout(wl, + PEER_REMOVE_COMPLETE_EVENT_ID); out_free: kfree(cmd); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index bba077ecd945..16e0a877bf57 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -36,7 +36,14 @@ int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); -int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id); +int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); +int wl12xx_cmd_role_start_dev(struct wl1271 *wl); +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); +int wl12xx_cmd_role_start_sta(struct wl1271 *wl); +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); +int wl12xx_cmd_role_start_ap(struct wl1271 *wl); +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); @@ -56,20 +63,16 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); int wl1271_build_qos_null_data(struct wl1271 *wl); int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); -int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id); -int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id); +int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16); int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); -int wl1271_cmd_disconnect(struct wl1271 *wl); -int wl1271_cmd_set_sta_state(struct wl1271 *wl); -int wl1271_cmd_start_bss(struct wl1271 *wl); -int wl1271_cmd_stop_bss(struct wl1271 *wl); -int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); -int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid); +int wl12xx_cmd_set_peer_state(struct wl1271 *wl); +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); +int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl); int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); @@ -83,25 +86,21 @@ enum wl1271_commands { CMD_DISABLE_TX = 6, CMD_SCAN = 8, CMD_STOP_SCAN = 9, - CMD_START_JOIN = 11, CMD_SET_KEYS = 12, CMD_READ_MEMORY = 13, CMD_WRITE_MEMORY = 14, CMD_SET_TEMPLATE = 19, CMD_TEST = 23, CMD_NOISE_HIST = 28, - CMD_LNA_CONTROL = 32, + CMD_QUIET_ELEMENT_SET_STATE = 29, CMD_SET_BCN_MODE = 33, CMD_MEASUREMENT = 34, CMD_STOP_MEASUREMENT = 35, - CMD_DISCONNECT = 36, CMD_SET_PS_MODE = 37, CMD_CHANNEL_SWITCH = 38, CMD_STOP_CHANNEL_SWICTH = 39, CMD_AP_DISCOVERY = 40, CMD_STOP_AP_DISCOVERY = 41, - CMD_SPS_SCAN = 42, - CMD_STOP_SPS_SCAN = 43, CMD_HEALTH_CHECK = 45, CMD_DEBUG = 46, CMD_TRIGGER_SCAN_TO = 47, @@ -109,16 +108,30 @@ enum wl1271_commands { CMD_CONNECTION_SCAN_SSID_CFG = 49, CMD_START_PERIODIC_SCAN = 50, CMD_STOP_PERIODIC_SCAN = 51, - CMD_SET_STA_STATE = 52, - CMD_CONFIG_FWLOGGER = 53, - CMD_START_FWLOGGER = 54, - CMD_STOP_FWLOGGER = 55, + CMD_SET_PEER_STATE = 52, + CMD_REMAIN_ON_CHANNEL = 53, + CMD_CANCEL_REMAIN_ON_CHANNEL = 54, - /* AP mode commands */ - CMD_BSS_START = 60, - CMD_BSS_STOP = 61, - CMD_ADD_STA = 62, - CMD_REMOVE_STA = 63, + CMD_CONFIG_FWLOGGER = 55, + CMD_START_FWLOGGER = 56, + CMD_STOP_FWLOGGER = 57, + + /* AP commands */ + CMD_ADD_PEER = 62, + CMD_REMOVE_PEER = 63, + + /* Role API */ + CMD_ROLE_ENABLE = 70, + CMD_ROLE_DISABLE = 71, + CMD_ROLE_START = 72, + CMD_ROLE_STOP = 73, + + /* WIFI Direct */ + CMD_WFD_START_DISCOVERY = 80, + CMD_WFD_STOP_DISCOVERY = 81, + CMD_WFD_ATTRIBUTE_CONFIG = 82, + + CMD_NOP = 100, NUM_COMMANDS, MAX_COMMAND_ID = 0xFFFF, @@ -147,14 +160,12 @@ enum cmd_templ { CMD_TEMPL_CTS, /* * For CTS-to-self (FastCTS) mechanism * for BT/WLAN coexistence (SoftGemini). */ - CMD_TEMPL_ARP_RSP, - CMD_TEMPL_LINK_MEASUREMENT_REPORT, - - /* AP-mode specific */ - CMD_TEMPL_AP_BEACON = 13, + CMD_TEMPL_AP_BEACON, CMD_TEMPL_AP_PROBE_RESPONSE, - CMD_TEMPL_AP_ARP_RSP, + CMD_TEMPL_ARP_RSP, CMD_TEMPL_DEAUTH_AP, + CMD_TEMPL_TEMPORARY, + CMD_TEMPL_LINK_MEASUREMENT_REPORT, CMD_TEMPL_MAX = 0xff }; @@ -193,6 +204,7 @@ enum { CMD_STATUS_WRONG_NESTING = 19, CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ + CMD_STATUS_TEMPLATE_OOM = 23, MAX_COMMAND_STATUS = 0xff }; @@ -210,38 +222,114 @@ enum { #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 #define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10 -struct wl1271_cmd_join { +struct wl12xx_cmd_role_enable { struct wl1271_cmd_header header; - __le32 bssid_lsb; - __le16 bssid_msb; - __le16 beacon_interval; /* in TBTTs */ - __le32 rx_config_options; - __le32 rx_filter_options; + u8 role_id; + u8 role_type; + u8 mac_address[ETH_ALEN]; +} __packed; - /* - * The target uses this field to determine the rate at - * which to transmit control frame responses (such as - * ACK or CTS frames). - */ - __le32 basic_rate_set; - __le32 supported_rate_set; - u8 dtim_interval; - /* - * bits 0-2: This bitwise field specifies the type - * of BSS to start or join (BSS_TYPE_*). - * bit 4: Band - The radio band in which to join - * or start. - * 0 - 2.4GHz band - * 1 - 5GHz band - * bits 3, 5-7: Reserved - */ - u8 bss_type; +struct wl12xx_cmd_role_disable { + struct wl1271_cmd_header header; + + u8 role_id; + u8 padding[3]; +} __packed; + +enum wl12xx_band { + WL12XX_BAND_2_4GHZ = 0, + WL12XX_BAND_5GHZ = 1, + WL12XX_BAND_JAPAN_4_9_GHZ = 2, + WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ, + WL12XX_BAND_INVALID = 0x7E, + WL12XX_BAND_MAX_RADIO = 0x7F, +}; + +struct wl12xx_cmd_role_start { + struct wl1271_cmd_header header; + + u8 role_id; + u8 band; u8 channel; - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ctrl; /* JOIN_CMD_CTRL_* */ - u8 reserved[3]; + u8 padding; + + union { + struct { + u8 hlid; + u8 session; + u8 padding_1[54]; + } __packed device; + /* sta & p2p_cli use the same struct */ + struct { + u8 bssid[ETH_ALEN]; + u8 hlid; /* data hlid */ + u8 session; + __le32 remote_rates; /* remote supported rates */ + + /* + * The target uses this field to determine the rate at + * which to transmit control frame responses (such as + * ACK or CTS frames). + */ + __le32 basic_rate_set; + __le32 local_rates; /* local supported rates */ + + u8 ssid_type; + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + + __le16 beacon_interval; /* in TBTTs */ + } __packed sta; + struct { + u8 bssid[ETH_ALEN]; + u8 hlid; /* data hlid */ + u8 dtim_interval; + __le32 remote_rates; /* remote supported rates */ + + __le32 basic_rate_set; + __le32 local_rates; /* local supported rates */ + + u8 ssid_type; + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + + __le16 beacon_interval; /* in TBTTs */ + + u8 padding_1[4]; + } __packed ibss; + /* ap & p2p_go use the same struct */ + struct { + __le16 aging_period; /* in secs */ + u8 beacon_expiry; /* in ms */ + u8 bss_index; + /* The host link id for the AP's global queue */ + u8 global_hlid; + /* The host link id for the AP's broadcast queue */ + u8 broadcast_hlid; + + __le16 beacon_interval; /* in TBTTs */ + + __le32 basic_rate_set; + __le32 local_rates; /* local supported rates */ + + u8 dtim_interval; + + u8 ssid_type; + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + + u8 padding_1[5]; + } __packed ap; + }; +} __packed; + +struct wl12xx_cmd_role_stop { + struct wl1271_cmd_header header; + + u8 role_id; + u8 disc_type; /* only STA and P2P_CLI */ + __le16 reason; /* only STA and P2P_CLI */ } __packed; struct cmd_enabledisable_path { @@ -287,8 +375,9 @@ enum wl1271_cmd_ps_mode { struct wl1271_cmd_ps_params { struct wl1271_cmd_header header; + u8 role_id; u8 ps_mode; /* STATION_* */ - u8 padding[3]; + u8 padding[2]; } __packed; /* HW encryption keys */ @@ -301,6 +390,12 @@ enum wl1271_cmd_key_action { MAX_KEY_ACTION = 0xffff, }; +enum wl1271_cmd_lid_key_type { + UNICAST_LID_TYPE = 0, + BROADCAST_LID_TYPE = 1, + WEP_DEFAULT_LID_TYPE = 2 +}; + enum wl1271_cmd_key_type { KEY_NONE = 0, KEY_WEP = 1, @@ -309,44 +404,7 @@ enum wl1271_cmd_key_type { KEY_GEM = 4, }; -/* FIXME: Add description for key-types */ - -struct wl1271_cmd_set_sta_keys { - struct wl1271_cmd_header header; - - /* Ignored for default WEP key */ - u8 addr[ETH_ALEN]; - - /* key_action_e */ - __le16 key_action; - - __le16 reserved_1; - - /* key size in bytes */ - u8 key_size; - - /* key_type_e */ - u8 key_type; - u8 ssid_profile; - - /* - * TKIP, AES: frame's key id field. - * For WEP default key: key id; - */ - u8 id; - u8 reserved_2[6]; - u8 key[MAX_KEY_SIZE]; - __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; - __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; -} __packed; - -enum wl1271_cmd_lid_key_type { - UNICAST_LID_TYPE = 0, - BROADCAST_LID_TYPE = 1, - WEP_DEFAULT_LID_TYPE = 2 -}; - -struct wl1271_cmd_set_ap_keys { +struct wl1271_cmd_set_keys { struct wl1271_cmd_header header; /* @@ -496,69 +554,23 @@ enum wl1271_disconnect_type { DISCONNECT_DISASSOC }; -struct wl1271_cmd_disconnect { - struct wl1271_cmd_header header; - - __le32 rx_config_options; - __le32 rx_filter_options; - - __le16 reason; - u8 type; - - u8 padding; -} __packed; - #define WL1271_CMD_STA_STATE_CONNECTED 1 -struct wl1271_cmd_set_sta_state { +struct wl12xx_cmd_set_peer_state { struct wl1271_cmd_header header; + u8 hlid; u8 state; - u8 padding[3]; + u8 padding[2]; } __packed; -enum wl1271_ssid_type { - SSID_TYPE_PUBLIC = 0, - SSID_TYPE_HIDDEN = 1 +enum wl12xx_ssid_type { + WL12XX_SSID_TYPE_PUBLIC = 0, + WL12XX_SSID_TYPE_HIDDEN = 1, + WL12XX_SSID_TYPE_ANY = 2, }; -struct wl1271_cmd_bss_start { - struct wl1271_cmd_header header; - - /* wl1271_ssid_type */ - u8 ssid_type; - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 padding_1[2]; - - /* Basic rate set */ - __le32 basic_rate_set; - /* Aging period in seconds*/ - __le16 aging_period; - - /* - * This field specifies the time between target beacon - * transmission times (TBTTs), in time units (TUs). - * Valid values are 1 to 1024. - */ - __le16 beacon_interval; - u8 bssid[ETH_ALEN]; - u8 bss_index; - /* Radio band */ - u8 band; - u8 channel; - /* The host link id for the AP's global queue */ - u8 global_hlid; - /* The host link id for the AP's broadcast queue */ - u8 broadcast_hlid; - /* DTIM count */ - u8 dtim_interval; - /* Beacon expiry time in ms */ - u8 beacon_expiry; - u8 padding_2[3]; -} __packed; - -struct wl1271_cmd_add_sta { +struct wl12xx_cmd_add_peer { struct wl1271_cmd_header header; u8 addr[ETH_ALEN]; @@ -572,7 +584,7 @@ struct wl1271_cmd_add_sta { u8 padding1; } __packed; -struct wl1271_cmd_remove_sta { +struct wl12xx_cmd_remove_peer { struct wl1271_cmd_header header; u8 hlid; diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 304aaa2ee011..431ceae6c1c8 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -285,10 +285,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " - "ba_allowed = 0x%x", mbox->ba_allowed); + "ba_allowed = 0x%x", mbox->rx_ba_allowed); if (wl->vif) - wl1271_stop_ba_event(wl, mbox->ba_allowed); + wl1271_stop_ba_event(wl, mbox->rx_ba_allowed); } if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index e524ad6fe4e3..49c1a0ede5b1 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -49,32 +49,27 @@ enum { MEASUREMENT_START_EVENT_ID = BIT(8), MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), SCAN_COMPLETE_EVENT_ID = BIT(10), - SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11), + WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), PS_REPORT_EVENT_ID = BIT(13), PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), DISCONNECT_EVENT_COMPLETE_ID = BIT(15), - JOIN_EVENT_COMPLETE_ID = BIT(16), + /* BIT(16) is reserved */ CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), MAX_TX_RETRY_EVENT_ID = BIT(20), - /* STA: dummy paket for dynamic mem blocks */ - DUMMY_PACKET_EVENT_ID = BIT(21), - /* AP: STA remove complete */ - STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), + DUMMY_PACKET_EVENT_ID = BIT(21), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), - /* STA: SG prediction */ - SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), - /* AP: Inactive STA */ - INACTIVE_STA_EVENT_ID = BIT(23), + CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), - DBG_EVENT_ID = BIT(26), - HEALTH_CHECK_REPLY_EVENT_ID = BIT(27), + INACTIVE_STA_EVENT_ID = BIT(26), + PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27), PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30), + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31), EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, }; @@ -83,15 +78,6 @@ enum { EVENT_ENTER_POWER_SAVE_SUCCESS, }; -struct event_debug_report { - u8 debug_event_id; - u8 num_params; - __le16 pad; - __le32 report_1; - __le32 report_2; - __le32 report_3; -} __packed; - #define NUM_OF_RSSI_SNR_TRIGGERS 8 struct event_mailbox { @@ -100,49 +86,45 @@ struct event_mailbox { __le32 reserved_1; __le32 reserved_2; - u8 dbg_event_id; - u8 num_relevant_params; - __le16 reserved_3; - __le32 event_report_p1; - __le32 event_report_p2; - __le32 event_report_p3; - u8 number_of_scan_results; u8 scan_tag; - u8 reserved_4[2]; - __le32 compl_scheduled_scan_status; + u8 completed_scan_status; + u8 reserved_3; - __le16 scheduled_scan_attended_channels; u8 soft_gemini_sense_info; u8 soft_gemini_protective_info; s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; u8 channel_switch_status; u8 scheduled_scan_status; u8 ps_status; + /* tuned channel (roc) */ + u8 roc_channel; - /* AP FW only */ - u8 hlid_removed; + __le16 hlid_removed_bitmap; - /* a bitmap of hlids for stations that have been inactive too long */ + /* bitmap of aged stations (by HLID) */ __le16 sta_aging_status; - /* a bitmap of hlids for stations which didn't respond to TX */ + /* bitmap of stations (by HLID) which exceeded max tx retries */ __le16 sta_tx_retry_exceeded; - /* - * Bitmap, Each bit set represents the Role ID for which this constraint - * is set. Range: 0 - FF, FF means ANY role - */ - u8 ba_role_id; - /* - * Bitmap, Each bit set represents the Link ID for which this constraint - * is set. Not applicable if ba_role_id is set to ANY role (FF). - * Range: 0 - FFFF, FFFF means ANY link in that role - */ - u8 ba_link_id; - u8 ba_allowed; + /* discovery completed results */ + u8 discovery_tag; + u8 number_of_preq_results; + u8 number_of_prsp_results; + u8 reserved_5; - u8 reserved_5[21]; + /* rx ba constraint */ + u8 role_id; /* 0xFF means any role. */ + u8 rx_ba_allowed; + u8 reserved_6[2]; + + u8 ps_poll_delivery_failure_role_ids; + u8 stopped_role_ids; + u8 started_role_ids; + u8 change_auto_mode_timeout; + + u8 reserved_7[12]; } __packed; int wl1271_event_unmask(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 5a3325761d04..76e6f37b87ad 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -404,12 +404,6 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) { int ret, i; - ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key); - if (ret < 0) { - wl1271_warning("couldn't set default key"); - return ret; - } - /* disable all keep-alive templates */ for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_acx_keep_alive_config(wl, i, diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 07d50b761610..4689d0bccf6d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -415,7 +415,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) return 0; - ret = wl1271_cmd_set_sta_state(wl); + ret = wl12xx_cmd_set_peer_state(wl); if (ret < 0) return ret; @@ -1982,6 +1982,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->ap_ps_map = 0; wl->sched_scanning = false; wl->role_id = WL12XX_INVALID_ROLE_ID; + memset(wl->roles_map, 0, sizeof(wl->roles_map)); + memset(wl->links_map, 0, sizeof(wl->links_map)); /* * this is performed after the cancel_work calls and the associated @@ -2030,7 +2032,7 @@ static int wl1271_dummy_join(struct wl1271 *wl) memcpy(wl->bssid, dummy_bssid, ETH_ALEN); - ret = wl1271_cmd_join(wl, wl->set_bss_type); + ret = wl12xx_cmd_role_start_sta(wl); if (ret < 0) goto out; @@ -2059,7 +2061,7 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) if (set_assoc) set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); - ret = wl1271_cmd_join(wl, wl->set_bss_type); + ret = wl12xx_cmd_role_start_sta(wl); if (ret < 0) goto out; @@ -2100,7 +2102,7 @@ static int wl1271_unjoin(struct wl1271 *wl) int ret; /* to stop listening to a channel, we disconnect */ - ret = wl1271_cmd_disconnect(wl); + ret = wl12xx_cmd_role_stop_sta(wl); if (ret < 0) goto out; @@ -2472,7 +2474,8 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) } if (wep_key_added) { - ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key); + ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, + WL1271_AP_BROADCAST_HLID); if (ret < 0) goto out; } @@ -2550,8 +2553,9 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, /* the default WEP key needs to be configured at least once */ if (key_type == KEY_WEP) { - ret = wl1271_cmd_set_sta_default_wep_key(wl, - wl->default_key); + ret = wl12xx_cmd_set_default_wep_key(wl, + wl->default_key, + wl->sta_hlid); if (ret < 0) return ret; } @@ -3008,7 +3012,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON_ENABLED)) { if (bss_conf->enable_beacon) { if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl1271_cmd_start_bss(wl); + ret = wl12xx_cmd_role_start_ap(wl); if (ret < 0) goto out; @@ -3021,7 +3025,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, } } else { if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl1271_cmd_stop_bss(wl); + ret = wl12xx_cmd_role_stop_ap(wl); if (ret < 0) goto out; @@ -3532,7 +3536,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (ret < 0) goto out_free_sta; - ret = wl1271_cmd_add_sta(wl, sta, hlid); + ret = wl12xx_cmd_add_peer(wl, sta, hlid); if (ret < 0) goto out_sleep; @@ -3575,7 +3579,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid); + ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); if (ret < 0) goto out_sleep; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8a745fbe0f45..f4973366a88b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -37,9 +37,10 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); if (is_ap) - ret = wl1271_cmd_set_ap_default_wep_key(wl, id); + ret = wl12xx_cmd_set_default_wep_key(wl, id, + WL1271_AP_BROADCAST_HLID); else - ret = wl1271_cmd_set_sta_default_wep_key(wl, id); + ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9f71dc75a01b..3d43875163e1 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -137,6 +137,7 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_BEACON_INT 100 #define WL1271_DEFAULT_DTIM_PERIOD 1 +#define WL12XX_MAX_ROLES 4 #define WL12XX_MAX_LINKS 8 #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff @@ -394,6 +395,10 @@ struct wl1271 { int channel; u8 role_id; u8 sta_hlid; + u8 dev_hlid; + + unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; + unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; struct wl1271_acx_mem_map *target_mem_map; From b78b47eb73fcf4f04226ab8014aa8dadf11675d9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:08 +0300 Subject: [PATCH 011/129] wl12xx: enable/disable role on interface add/remove According to the new multi-role flow, we have to enable the role before using (starting) it, and disable it on cleanup (after it's no longer needed). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 4689d0bccf6d..3e77f59e3397 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1779,6 +1779,21 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); } +static u8 wl12xx_get_role_type(struct wl1271 *wl) +{ + switch (wl->bss_type) { + case BSS_TYPE_AP_BSS: + return WL1271_ROLE_AP; + + case BSS_TYPE_STA_BSS: + return WL1271_ROLE_STA; + + default: + wl1271_error("invalid bss_type: %d", wl->bss_type); + } + return WL12XX_INVALID_ROLE_TYPE; +} + static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1786,6 +1801,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct wiphy *wiphy = hw->wiphy; int retries = WL1271_BOOT_RETRIES; int ret = 0; + u8 role_type; bool booted = false; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", @@ -1826,6 +1842,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } + role_type = wl12xx_get_role_type(wl); + if (role_type == WL12XX_INVALID_ROLE_TYPE) { + ret = -EINVAL; + goto out; + } memcpy(wl->mac_addr, vif->addr, ETH_ALEN); if (wl->state != WL1271_STATE_OFF) { @@ -1845,6 +1866,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto power_off; + ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); + if (ret < 0) + goto irq_disable; + ret = wl1271_hw_init(wl); if (ret < 0) goto irq_disable; @@ -1909,6 +1934,7 @@ out: static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { + int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -1933,6 +1959,21 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, ieee80211_scan_completed(wl->hw, true); } + if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { + /* disable active roles */ + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto deinit; + + ret = wl12xx_cmd_role_disable(wl, &wl->role_id); + if (ret < 0) + goto deinit; + + wl1271_ps_elp_sleep(wl); + } +deinit: + wl->sta_hlid = WL12XX_INVALID_LINK_ID; + /* * this must be before the cancel_work calls below, so that the work * functions don't perform further work. From 04e8079c69d6fa1aa023b0b6f58f818f965c10bb Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:09 +0300 Subject: [PATCH 012/129] wl12xx: add device role commands The device role is a special role used for rx and tx frames prior to association (as the STA role can get packets only from its associated bssid) Since this role is required for the sta association process, we enable it when a new sta interface is created. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 91 ++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/main.c | 25 +++++++- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b13eed129a92..e29343ed6ea2 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -458,6 +458,97 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) *hlid = WL12XX_INVALID_LINK_ID; } +int wl12xx_cmd_role_start_dev(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_start *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id); + + cmd->role_id = wl->dev_role_id; + if (wl->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wl->channel; + + if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->dev_hlid); + if (ret) + goto out_free; + } + cmd->device.hlid = wl->dev_hlid; + cmd->device.session = wl->session_counter; + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", + cmd->role_id, cmd->device.hlid, cmd->device.session); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error */ + __clear_bit(wl->dev_hlid, wl->links_map); + wl->dev_hlid = WL12XX_INVALID_LINK_ID; + + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop dev"); + + cmd->role_id = wl->dev_role_id; + cmd->disc_type = DISCONNECT_IMMEDIATE; + cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop"); + goto out_free; + } + + ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); + if (ret < 0) { + wl1271_error("cmd role stop dev event completion error"); + goto out_free; + } + + wl12xx_free_link(wl, &wl->dev_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + int wl12xx_cmd_role_start_sta(struct wl1271 *wl) { struct wl12xx_cmd_role_start *cmd; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3e77f59e3397..7b0b7c34ef76 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1866,6 +1866,20 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto power_off; + if (wl->bss_type == BSS_TYPE_STA_BSS) { + /* + * The device role is a special role used for + * rx and tx frames prior to association (as + * the STA role can get packets only from + * its associated bssid) + */ + ret = wl12xx_cmd_role_enable(wl, + WL1271_ROLE_DEVICE, + &wl->dev_role_id); + if (ret < 0) + goto irq_disable; + } + ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); if (ret < 0) goto irq_disable; @@ -1965,6 +1979,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (ret < 0) goto deinit; + if (wl->bss_type == BSS_TYPE_STA_BSS) { + ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); + if (ret < 0) + goto deinit; + } + ret = wl12xx_cmd_role_disable(wl, &wl->role_id); if (ret < 0) goto deinit; @@ -1973,6 +1993,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, } deinit: wl->sta_hlid = WL12XX_INVALID_LINK_ID; + wl->dev_hlid = WL12XX_INVALID_LINK_ID; /* * this must be before the cancel_work calls below, so that the work @@ -2023,6 +2044,7 @@ deinit: wl->ap_ps_map = 0; wl->sched_scanning = false; wl->role_id = WL12XX_INVALID_ROLE_ID; + wl->dev_role_id = WL12XX_INVALID_ROLE_ID; memset(wl->roles_map, 0, sizeof(wl->roles_map)); memset(wl->links_map, 0, sizeof(wl->links_map)); @@ -4365,7 +4387,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_security_last_seq_lsb = 0; wl->role_id = WL12XX_INVALID_ROLE_ID; wl->sta_hlid = WL12XX_INVALID_LINK_ID; - + wl->dev_role_id = WL12XX_INVALID_ROLE_ID; + wl->dev_hlid = WL12XX_INVALID_LINK_ID; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); wl->fwlog_size = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 3d43875163e1..ab46664969ec 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -394,6 +394,7 @@ struct wl1271 { u8 ssid_len; int channel; u8 role_id; + u8 dev_role_id; u8 sta_hlid; u8 dev_hlid; From a4e02f330a69a305c4f7bc98d56e72aa0d4b6032 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:10 +0300 Subject: [PATCH 013/129] wl12xx: update scan cmd api Update the scan command to use the new fw api (fw 6/7.3.0.0.75). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/scan.c | 8 +++++++- drivers/net/wireless/wl12xx/scan.h | 25 ++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 78a9b23a41b8..54a4e75a37fe 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -156,6 +156,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, if (passive || wl->scan.req->n_ssids == 0) scan_options |= WL1271_SCAN_OPT_PASSIVE; + if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { + ret = -EINVAL; + goto out; + } + cmd->params.role_id = wl->role_id; cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, @@ -167,7 +172,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, } cmd->params.tx_rate = cpu_to_le32(basic_rate); - cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tid_trigger = 0; @@ -183,6 +187,8 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); } + memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); + ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, wl->scan.req->ie, wl->scan.req->ie_len, band); diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 0b2a2987439d..92115156522f 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -46,7 +46,10 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl); #define WL1271_SCAN_CURRENT_TX_PWR 0 #define WL1271_SCAN_OPT_ACTIVE 0 #define WL1271_SCAN_OPT_PASSIVE 1 +#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2 #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 +/* scan even if we fail to enter psm */ +#define WL1271_SCAN_OPT_FORCE 8 #define WL1271_SCAN_BAND_2_4_GHZ 0 #define WL1271_SCAN_BAND_5_GHZ 1 @@ -62,27 +65,27 @@ enum { }; struct basic_scan_params { - __le32 rx_config_options; - __le32 rx_filter_options; /* Scan option flags (WL1271_SCAN_OPT_*) */ __le16 scan_options; + u8 role_id; /* Number of scan channels in the list (maximum 30) */ u8 n_ch; /* This field indicates the number of probe requests to send per channel for an active scan */ u8 n_probe_reqs; - /* Rate bit field for sending the probes */ - __le32 tx_rate; u8 tid_trigger; u8 ssid_len; - /* in order to align */ - u8 padding1[2]; + u8 use_ssid_list; + + /* Rate bit field for sending the probes */ + __le32 tx_rate; + u8 ssid[IEEE80211_MAX_SSID_LEN]; /* Band to scan */ u8 band; - u8 use_ssid_list; + u8 scan_tag; - u8 padding2; + u8 padding2[2]; } __packed; struct basic_scan_channel_params { @@ -105,6 +108,10 @@ struct wl1271_cmd_scan { struct basic_scan_params params; struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; + + /* src mac address */ + u8 addr[ETH_ALEN]; + u8 padding[2]; } __packed; struct wl1271_cmd_trigger_scan_to { @@ -184,7 +191,7 @@ struct wl1271_cmd_sched_scan_config { } __packed; -#define SCHED_SCAN_MAX_SSIDS 8 +#define SCHED_SCAN_MAX_SSIDS 16 enum { SCAN_SSID_TYPE_PUBLIC = 0, From 79b122dc51797b650201f21360481a0450e9b7e4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:11 +0300 Subject: [PATCH 014/129] wl12xx: update rx/tx Update the rx/tx descriptors according to the new fw api (fw >= 6/7.3.0.0.75) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.h | 7 ++----- drivers/net/wireless/wl12xx/tx.c | 15 +++++++++++---- drivers/net/wireless/wl12xx/tx.h | 14 ++++---------- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index 00c1c1d27aaa..86ba6b1d0cdc 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -86,7 +86,7 @@ * Bits 3-5 - process_id tag (AP mode FW) * Bits 6-7 - reserved */ -#define WL1271_RX_DESC_STATUS_MASK 0x07 +#define WL1271_RX_DESC_STATUS_MASK 0x03 #define WL1271_RX_DESC_SUCCESS 0x00 #define WL1271_RX_DESC_DECRYPT_FAIL 0x01 @@ -121,10 +121,7 @@ struct wl1271_rx_descriptor { u8 snr; __le32 timestamp; u8 packet_class; - union { - u8 process_id; /* STA FW */ - u8 hlid; /* AP FW */ - } __packed; + u8 hlid; u8 pad_len; u8 reserved; } __packed; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index f4973366a88b..23ce7aaeb4c4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -276,9 +276,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; } - if (wl->bss_type != BSS_TYPE_AP_BSS) { - desc->aid = hlid; + desc->hlid = hlid; + if (wl->bss_type != BSS_TYPE_AP_BSS) { /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ @@ -287,7 +287,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else rate_idx = ACX_TX_BASIC_RATE; } else { - desc->hlid = hlid; switch (hlid) { case WL1271_AP_GLOBAL_HLID: rate_idx = ACX_TX_AP_MODE_MGMT_RATE; @@ -375,7 +374,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) hlid = wl1271_tx_get_hlid(skb); else - hlid = TX_HW_DEFAULT_AID; + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + hlid = wl->sta_hlid; + else + hlid = wl->dev_hlid; + + if (hlid == WL12XX_INVALID_LINK_ID) { + wl1271_error("invalid hlid. dropping skb 0x%p", skb); + return -EINVAL; + } ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 5d719b5a3d1d..b712d7b058a8 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -29,9 +29,6 @@ #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 -/* The chipset reference driver states, that the "aid" value 1 - * is for infra-BSS, but is still always used */ -#define TX_HW_DEFAULT_AID 1 #define TX_HW_ATTR_SAVE_RETRIES BIT(0) #define TX_HW_ATTR_HEADER_PAD BIT(1) @@ -116,12 +113,8 @@ struct wl1271_tx_hw_descr { u8 id; /* The packet TID value (as User-Priority) */ u8 tid; - union { - /* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */ - u8 aid; - /* AP - host link ID (HLID) */ - u8 hlid; - } __packed; + /* host link ID (HLID) */ + u8 hlid; u8 reserved; } __packed; @@ -133,7 +126,8 @@ enum wl1271_tx_hw_res_status { TX_TIMEOUT = 4, TX_KEY_NOT_FOUND = 5, TX_PEER_NOT_FOUND = 6, - TX_SESSION_MISMATCH = 7 + TX_SESSION_MISMATCH = 7, + TX_LINK_NOT_VALID = 8, }; struct wl1271_tx_hw_res_descr { diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ab46664969ec..93e689d1f46a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -159,7 +159,7 @@ extern u32 wl12xx_debug_level; #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 -#define ACX_TX_DESCRIPTORS 32 +#define ACX_TX_DESCRIPTORS 16 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) From 154037d1681caaff7d33521b84017ee58b396438 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:12 +0300 Subject: [PATCH 015/129] wl12xx: change max/default template size The max template size was increased in the new fw. However, we should use the max size only when needed, as it consumes some of the chip's memory. Thus, by default initialize the templates to the default size. Initialize to the maximum size only when required. Use WL1271_CMD_TEMPL_DFLT_SIZE instead of some of the predefined structs, as some of them didn't account for additional IEs that might be added to the template. Delete structs defintions not used after these changes. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.h | 3 ++- drivers/net/wireless/wl12xx/init.c | 18 ++++++---------- drivers/net/wireless/wl12xx/main.c | 2 +- drivers/net/wireless/wl12xx/wl12xx_80211.h | 25 ---------------------- 4 files changed, 10 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 16e0a877bf57..6950759172f0 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -172,7 +172,8 @@ enum cmd_templ { /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 -#define WL1271_CMD_TEMPL_MAX_SIZE 252 +#define WL1271_CMD_TEMPL_DFLT_SIZE 252 +#define WL1271_CMD_TEMPL_MAX_SIZE 548 #define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 76e6f37b87ad..683c8d128551 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -39,13 +39,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) /* send empty templates for fw memory reservation */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, + WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, + NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -70,15 +70,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, - sizeof - (struct wl12xx_probe_resp_template), + WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, - sizeof - (struct wl12xx_beacon_template), + WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -92,7 +90,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, i, + WL1271_CMD_TEMPL_DFLT_SIZE, i, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -191,15 +189,13 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl) * reserve memory for later. */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, - sizeof - (struct wl12xx_probe_resp_template), + WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, - sizeof - (struct wl12xx_beacon_template), + WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7b0b7c34ef76..1389c5cba343 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4266,7 +4266,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) * should be the maximum length possible for a template, without * the IEEE80211 header of the template */ - wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - + wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - sizeof(struct ieee80211_header); /* make sure all our channels fit in the scanned_ch bitmask */ diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index f334ea081722..f7971d3b0898 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -105,18 +105,6 @@ struct wl12xx_ie_country { /* Templates */ -struct wl12xx_beacon_template { - struct ieee80211_header header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; - struct wl12xx_ie_ds_params ds_params; - struct wl12xx_ie_country country; -} __packed; - struct wl12xx_null_data_template { struct ieee80211_header header; } __packed; @@ -146,19 +134,6 @@ struct wl12xx_arp_rsp_template { __be32 target_ip; } __packed; - -struct wl12xx_probe_resp_template { - struct ieee80211_header header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; - struct wl12xx_ie_ds_params ds_params; - struct wl12xx_ie_country country; -} __packed; - struct wl12xx_disconn_template { struct ieee80211_header header; __le16 disconn_reason; From f42bd2cbf1d5ff4b161ad2c59ff12d66558c8374 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:13 +0300 Subject: [PATCH 016/129] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap Use ACX_BEACON_FILTER_OPT for both station and ap roles (use the generic wl1271_acx_beacon_filter_opt() instead of wl1271_acx_set_ap_beacon_filter() ). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 25 ------------------------- drivers/net/wireless/wl12xx/acx.h | 9 --------- drivers/net/wireless/wl12xx/init.c | 2 +- drivers/net/wireless/wl12xx/main.c | 4 ++-- 4 files changed, 3 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index dfb1cbb35acd..968d2197ac81 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1660,31 +1660,6 @@ out: return ret; } -int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable) -{ - struct acx_ap_beacon_filter *acx = NULL; - int ret; - - wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) - return -ENOMEM; - - acx->enable = enable ? 1 : 0; - - ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT, - acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("acx set ap beacon filter failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - int wl1271_acx_fm_coex(struct wl1271 *wl) { struct wl1271_acx_fm_coex *acx; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 67258a15de21..3aec410634e7 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1096,13 +1096,6 @@ struct wl1271_acx_inconnection_sta { u8 padding1[2]; } __packed; -struct acx_ap_beacon_filter { - struct acx_header header; - - u8 enable; - u8 pad[3]; -} __packed; - /* * ACX_FM_COEX_CFG * set the FM co-existence parameters. @@ -1177,7 +1170,6 @@ enum { ACX_TID_CFG = 0x001A, ACX_PS_RX_STREAMING = 0x001B, ACX_BEACON_FILTER_OPT = 0x001F, - ACX_AP_BEACON_FILTER_OPT = 0x0020, ACX_NOISE_HIST = 0x0021, ACX_HDK_VERSION = 0x0022, /* ??? */ ACX_PD_THRESHOLD = 0x0023, @@ -1301,7 +1293,6 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); -int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); int wl1271_acx_fm_coex(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 683c8d128551..3a6660901c33 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -469,7 +469,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl) * when operating as AP we want to receive external beacons for * configuring ERP protection. */ - ret = wl1271_acx_set_ap_beacon_filter(wl, false); + ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1389c5cba343..d683bca9b308 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1639,7 +1639,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl) if (ret < 0) goto out_unlock; - ret = wl1271_acx_set_ap_beacon_filter(wl, true); + ret = wl1271_acx_beacon_filter_opt(wl, true); wl1271_ps_elp_sleep(wl); out_unlock: @@ -1677,7 +1677,7 @@ static void wl1271_configure_resume(struct wl1271 *wl) wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, wl->basic_rate, true); } else if (is_ap) { - wl1271_acx_set_ap_beacon_filter(wl, false); + wl1271_acx_beacon_filter_opt(wl, false); } wl1271_ps_elp_sleep(wl); From fa6ad9f0f34b0754ce7551866b33587f077a2a51 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:14 +0300 Subject: [PATCH 017/129] wl12xx: add set_rate_mgmt_params acx Configure rate management parameters on hw init Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 42 ++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/acx.h | 25 ++++++++++++++++++ drivers/net/wireless/wl12xx/conf.h | 20 ++++++++++++++ drivers/net/wireless/wl12xx/init.c | 4 +++ drivers/net/wireless/wl12xx/main.c | 21 +++++++++++++++ 5 files changed, 112 insertions(+) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 968d2197ac81..a784ba6a8ef6 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1699,3 +1699,45 @@ out: kfree(acx); return ret; } + +int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl) +{ + struct wl12xx_acx_set_rate_mgmt_params *acx = NULL; + struct conf_rate_policy_settings *conf = &wl->conf.rate; + int ret; + + wl1271_debug(DEBUG_ACX, "acx set rate mgmt params"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) + return -ENOMEM; + + acx->index = ACX_RATE_MGMT_ALL_PARAMS; + acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score); + acx->per_add = cpu_to_le16(conf->per_add); + acx->per_th1 = cpu_to_le16(conf->per_th1); + acx->per_th2 = cpu_to_le16(conf->per_th2); + acx->max_per = cpu_to_le16(conf->max_per); + acx->inverse_curiosity_factor = conf->inverse_curiosity_factor; + acx->tx_fail_low_th = conf->tx_fail_low_th; + acx->tx_fail_high_th = conf->tx_fail_high_th; + acx->per_alpha_shift = conf->per_alpha_shift; + acx->per_add_shift = conf->per_add_shift; + acx->per_beta1_shift = conf->per_beta1_shift; + acx->per_beta2_shift = conf->per_beta2_shift; + acx->rate_check_up = conf->rate_check_up; + acx->rate_check_down = conf->rate_check_down; + memcpy(acx->rate_retry_policy, conf->rate_retry_policy, + sizeof(acx->rate_retry_policy)); + + ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS, + acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx set rate mgmt params failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 3aec410634e7..6909bc535a5d 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1155,6 +1155,30 @@ struct wl1271_acx_fm_coex { u8 swallow_clk_diff; } __packed; +#define ACX_RATE_MGMT_ALL_PARAMS 0xff +struct wl12xx_acx_set_rate_mgmt_params { + struct acx_header header; + + u8 index; /* 0xff to configure all params */ + u8 padding1; + __le16 rate_retry_score; + __le16 per_add; + __le16 per_th1; + __le16 per_th2; + __le16 max_per; + u8 inverse_curiosity_factor; + u8 tx_fail_low_th; + u8 tx_fail_high_th; + u8 per_alpha_shift; + u8 per_add_shift; + u8 per_beta1_shift; + u8 per_beta2_shift; + u8 rate_check_up; + u8 rate_check_down; + u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; + u8 padding2[2]; +} __packed; + enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -1294,5 +1318,6 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_fm_coex(struct wl1271 *wl); +int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 6080e01d92c6..30ee7d304bcc 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1309,6 +1309,25 @@ struct conf_fwlog { u8 threshold; }; +#define ACX_RATE_MGMT_NUM_OF_RATES 13 +struct conf_rate_policy_settings { + u16 rate_retry_score; + u16 per_add; + u16 per_th1; + u16 per_th2; + u16 max_per; + u8 inverse_curiosity_factor; + u8 tx_fail_low_th; + u8 tx_fail_high_th; + u8 per_alpha_shift; + u8 per_add_shift; + u8 per_beta1_shift; + u8 per_beta2_shift; + u8 rate_check_up; + u8 rate_check_down; + u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; +}; + struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; @@ -1326,6 +1345,7 @@ struct conf_drv_settings { struct conf_fm_coex fm_coex; struct conf_rx_streaming_settings rx_streaming; struct conf_fwlog fwlog; + struct conf_rate_policy_settings rate; u8 hci_io_ds; }; diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 3a6660901c33..1bc246f42a65 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -715,6 +715,10 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + ret = wl12xx_acx_set_rate_mgmt_params(wl); + if (ret < 0) + goto out_free_memmap; + /* Configure initiator BA sessions policies */ ret = wl1271_set_ba_policies(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d683bca9b308..3db191de3f51 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -379,6 +379,27 @@ static struct conf_drv_settings default_conf = { .threshold = 0, }, .hci_io_ds = HCI_IO_DS_6MA, + .rate = { + .rate_retry_score = 32000, + .per_add = 8192, + .per_th1 = 2048, + .per_th2 = 4096, + .max_per = 8100, + .inverse_curiosity_factor = 5, + .tx_fail_low_th = 4, + .tx_fail_high_th = 10, + .per_alpha_shift = 4, + .per_add_shift = 13, + .per_beta1_shift = 10, + .per_beta2_shift = 8, + .rate_check_up = 2, + .rate_check_down = 12, + .rate_retry_policy = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + }, + }, }; static char *fwlog_param; From f4df1bd525e027aa1975e00f87a420aec7bef4e0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:15 +0300 Subject: [PATCH 018/129] wl12xx: add system_hlid system_hlid is a const hlid (always 0), used by the fw and driver for packets which are not bound to specific role (e.g. dynamic memory packets). indicate it as always allocated. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 9 ++++++- drivers/net/wireless/wl12xx/tx.c | 40 +++++++++++++++++----------- drivers/net/wireless/wl12xx/tx.h | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 ++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3db191de3f51..e4081e222184 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1491,7 +1491,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) q = wl1271_tx_get_queue(mapping); if (wl->bss_type == BSS_TYPE_AP_BSS) - hlid = wl1271_tx_get_hlid(skb); + hlid = wl12xx_tx_get_hlid_ap(wl, skb); spin_lock_irqsave(&wl->wl_lock, flags); @@ -2069,6 +2069,9 @@ deinit: memset(wl->roles_map, 0, sizeof(wl->roles_map)); memset(wl->links_map, 0, sizeof(wl->links_map)); + /* The system link is always allocated */ + __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); + /* * this is performed after the cancel_work calls and the associated * mutex_lock, so that wl1271_op_add_interface does not accidentally @@ -4407,6 +4410,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_security_seq = 0; wl->tx_security_last_seq_lsb = 0; wl->role_id = WL12XX_INVALID_ROLE_ID; + wl->system_hlid = WL12XX_SYSTEM_HLID; wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->dev_role_id = WL12XX_INVALID_ROLE_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; @@ -4415,6 +4419,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->fwlog_size = 0; init_waitqueue_head(&wl->fwlog_waitq); + /* The system link is always allocated */ + __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); + memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 23ce7aaeb4c4..ffdaf97854cb 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -132,7 +132,12 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) } #endif -u8 wl1271_tx_get_hlid(struct sk_buff *skb) +static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) +{ + return wl->dummy_packet == skb; +} + +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) { struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); @@ -145,6 +150,9 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) } else { struct ieee80211_hdr *hdr; + if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + return wl->system_hlid; + hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_mgmt(hdr->frame_control)) return WL1271_AP_GLOBAL_HLID; @@ -153,6 +161,20 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) } } +static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) +{ + if (wl12xx_is_dummy_packet(wl, skb)) + return wl->system_hlid; + + if (wl->bss_type == BSS_TYPE_AP_BSS) + return wl12xx_tx_get_hlid_ap(wl, skb); + + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + return wl->sta_hlid; + else + return wl->dev_hlid; +} + static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length) { @@ -221,11 +243,6 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, return ret; } -static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) -{ - return wl->dummy_packet == skb; -} - static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control, u8 hlid) @@ -371,14 +388,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, } } - if (wl->bss_type == BSS_TYPE_AP_BSS) - hlid = wl1271_tx_get_hlid(skb); - else - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) - hlid = wl->sta_hlid; - else - hlid = wl->dev_hlid; - + hlid = wl1271_tx_get_hlid(wl, skb); if (hlid == WL12XX_INVALID_LINK_ID) { wl1271_error("invalid hlid. dropping skb 0x%p", skb); return -EINVAL; @@ -564,7 +574,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) if (wl12xx_is_dummy_packet(wl, skb)) { set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); } else if (wl->bss_type == BSS_TYPE_AP_BSS) { - u8 hlid = wl1271_tx_get_hlid(skb); + u8 hlid = wl1271_tx_get_hlid(wl, skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index b712d7b058a8..7da35c0e411b 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -210,7 +210,7 @@ void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); u32 wl1271_tx_min_rate_get(struct wl1271 *wl); -u8 wl1271_tx_get_hlid(struct sk_buff *skb); +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 93e689d1f46a..089304d874d5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -141,6 +141,7 @@ extern u32 wl12xx_debug_level; #define WL12XX_MAX_LINKS 8 #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff +#define WL12XX_SYSTEM_HLID 0 #define WL1271_AP_GLOBAL_HLID 0 #define WL1271_AP_BROADCAST_HLID 1 #define WL1271_AP_STA_HLID_START 2 @@ -395,6 +396,7 @@ struct wl1271 { int channel; u8 role_id; u8 dev_role_id; + u8 system_hlid; u8 sta_hlid; u8 dev_hlid; From a7cba38471bd457db8c536c94073673f41ef66f4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:16 +0300 Subject: [PATCH 019/129] wl12xx: add ROC/CROC commands Add structs and functions to support the ROC/CROC commands. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 73 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/cmd.h | 16 +++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index e29343ed6ea2..1b04102144e6 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1481,3 +1481,76 @@ out_free: out: return ret; } + +static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) +{ + struct wl12xx_cmd_roc *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id); + + if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->role_id = role_id; + cmd->channel = wl->channel; + switch (wl->band) { + case IEEE80211_BAND_2GHZ: + cmd->band = RADIO_BAND_2_4GHZ; + break; + case IEEE80211_BAND_5GHZ: + cmd->band = RADIO_BAND_5GHZ; + break; + default: + wl1271_error("roc - unknown band: %d", (int)wl->band); + ret = -EINVAL; + goto out_free; + } + + + ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send ROC command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) +{ + struct wl12xx_cmd_croc *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + cmd->role_id = role_id; + + ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd, + sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send ROC command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 6950759172f0..80b02ed0e3f2 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -565,6 +565,22 @@ struct wl12xx_cmd_set_peer_state { u8 padding[2]; } __packed; +struct wl12xx_cmd_roc { + struct wl1271_cmd_header header; + + u8 role_id; + u8 channel; + u8 band; + u8 padding; +}; + +struct wl12xx_cmd_croc { + struct wl1271_cmd_header header; + + u8 role_id; + u8 padding[3]; +}; + enum wl12xx_ssid_type { WL12XX_SSID_TYPE_PUBLIC = 0, WL12XX_SSID_TYPE_HIDDEN = 1, From 79ebec76be4e7c2ebed9fb0b9510d10d599ed63e Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:18 +0300 Subject: [PATCH 020/129] wl12xx: handle dummy packet event also in ap mode Allow handling of DUMMY_PACKET_EVENT_ID also in ap mode. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 2 +- drivers/net/wireless/wl12xx/tx.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 431ceae6c1c8..0bd7b020a420 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -291,7 +291,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_stop_ba_event(wl, mbox->rx_ba_allowed); } - if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { + if ((vector & DUMMY_PACKET_EVENT_ID)) { wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); if (wl->vif) wl1271_tx_dummy_packet(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index ffdaf97854cb..a2dbbadd58f0 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -821,10 +821,14 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) total[i] = 0; while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); - info = IEEE80211_SKB_CB(skb); - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - ieee80211_tx_status_ni(wl->hw, skb); + + if (!wl12xx_is_dummy_packet(wl, skb)) { + info = IEEE80211_SKB_CB(skb); + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; + ieee80211_tx_status_ni(wl->hw, skb); + } + total[i]++; } } From 251c177f886027fbce494202e44935762f103137 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:17 +0300 Subject: [PATCH 021/129] wl12xx: replace dummy_join with ROC/CROC commands The ROC command asks the fw stay on the channel of the given hlid. it currently has 2 primary functions: 1. Allow tx/rx from the device role. In order to tx/rx packets while the stations is not associated (e.g. auth req/resp), the device role has to be used, along with ROC on its link. Keep the logic similiar to the one used in dummy_join. However, since we can't scan while we ROC, we add CROC before starting a scan, and ROC again (if needed) on scan complete. 2. Keeping the antenna for a specific link. We ROC until the connection was completed (after EAPOLs exchange) in order to prevent BT coex operations from taking the antenna and failing the connection (after this stage, psm can be used). During association, we ROC on the station role, and then CROC the device role, thus assuring being ROC during all the connection process. Delete the WL1271_FLAG_JOINED flag, and use a roc bitmap to indicate what roles are currently ROCed. Add wl12xx_roc/croc functions in order to wrap the roc/croc commands while taking care of the roc bitmap. The current ROC/CROC state-machine is a bit complicated. In the future we'll probably want to use wpa_supplicant to control the ROC during connection. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 39 ++++++++ drivers/net/wireless/wl12xx/cmd.h | 2 + drivers/net/wireless/wl12xx/main.c | 144 +++++++++++++++++++++------ drivers/net/wireless/wl12xx/scan.c | 20 ++-- drivers/net/wireless/wl12xx/tx.c | 13 +++ drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 6 files changed, 182 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 1b04102144e6..c620a9d4939c 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1554,3 +1554,42 @@ out_free: out: return ret; } + +int wl12xx_roc(struct wl1271 *wl, u8 role_id) +{ + int ret = 0; + + if (WARN_ON(test_bit(role_id, wl->roc_map))) + return 0; + + ret = wl12xx_cmd_roc(wl, role_id); + if (ret < 0) + goto out; + + ret = wl1271_cmd_wait_for_event(wl, + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); + if (ret < 0) { + wl1271_error("cmd roc event completion error"); + goto out; + } + + __set_bit(role_id, wl->roc_map); +out: + return ret; +} + +int wl12xx_croc(struct wl1271 *wl, u8 role_id) +{ + int ret = 0; + + if (WARN_ON(!test_bit(role_id, wl->roc_map))) + return 0; + + ret = wl12xx_cmd_croc(wl, role_id); + if (ret < 0) + goto out; + + __clear_bit(role_id, wl->roc_map); +out: + return ret; +} diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 80b02ed0e3f2..5cf92e256641 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -71,6 +71,8 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); int wl12xx_cmd_set_peer_state(struct wl1271 *wl); +int wl12xx_roc(struct wl1271 *wl, u8 role_id); +int wl12xx_croc(struct wl1271 *wl, u8 role_id); int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_config_fwlog(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e4081e222184..57b10e98730e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -440,6 +440,8 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (ret < 0) return ret; + wl12xx_croc(wl, wl->role_id); + wl1271_info("Association completed."); return 0; } @@ -2068,6 +2070,7 @@ deinit: wl->dev_role_id = WL12XX_INVALID_ROLE_ID; memset(wl->roles_map, 0, sizeof(wl->roles_map)); memset(wl->links_map, 0, sizeof(wl->links_map)); + memset(wl->roc_map, 0, sizeof(wl->roc_map)); /* The system link is always allocated */ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); @@ -2110,25 +2113,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } -static int wl1271_dummy_join(struct wl1271 *wl) -{ - int ret = 0; - /* we need to use a dummy BSSID for now */ - static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, - 0xad, 0xbe, 0xef }; - - memcpy(wl->bssid, dummy_bssid, ETH_ALEN); - - ret = wl12xx_cmd_role_start_sta(wl); - if (ret < 0) - goto out; - - set_bit(WL1271_FLAG_JOINED, &wl->flags); - -out: - return ret; -} - static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; @@ -2152,8 +2136,6 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) if (ret < 0) goto out; - set_bit(WL1271_FLAG_JOINED, &wl->flags); - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) goto out; @@ -2193,7 +2175,6 @@ static int wl1271_unjoin(struct wl1271 *wl) if (ret < 0) goto out; - clear_bit(WL1271_FLAG_JOINED, &wl->flags); memset(wl->bssid, 0, ETH_ALEN); /* reset TX security counters on a clean disconnect */ @@ -2212,13 +2193,29 @@ static void wl1271_set_band_rate(struct wl1271 *wl) wl->basic_rate_set = wl->conf.tx.basic_rate_5; } +static bool wl12xx_is_roc(struct wl1271 *wl) +{ + u8 role_id; + + role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES); + if (role_id >= WL12XX_MAX_ROLES) + return false; + + return true; +} + static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) { int ret; if (idle) { - if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { - ret = wl1271_unjoin(wl); + /* no need to croc if we weren't busy (e.g. during boot) */ + if (wl12xx_is_roc(wl)) { + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + + ret = wl12xx_cmd_role_stop_dev(wl); if (ret < 0) goto out; } @@ -2244,7 +2241,11 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) ieee80211_sched_scan_stopped(wl->hw); } - ret = wl1271_dummy_join(wl); + ret = wl12xx_cmd_role_start_dev(wl); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wl->dev_role_id); if (ret < 0) goto out; clear_bit(WL1271_FLAG_IDLE, &wl->flags); @@ -2324,11 +2325,34 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_warning("rate policy for channel " "failed %d", ret); - if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + if (wl12xx_is_roc(wl)) { + /* roaming */ + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out_sleep; + } ret = wl1271_join(wl, false); if (ret < 0) wl1271_warning("cmd join on channel " "failed %d", ret); + } else { + /* + * change the ROC channel. do it only if we are + * not idle. otherwise, CROC will be called + * anyway. + */ + if (wl12xx_is_roc(wl) && + !(conf->flags & IEEE80211_CONF_IDLE)) { + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out_sleep; + + ret = wl12xx_roc(wl, wl->dev_role_id); + if (ret < 0) + wl1271_warning("roc failed %d", + ret); + } } } } @@ -2784,10 +2808,20 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; + /* cancel ROC before scanning */ + if (wl12xx_is_roc(wl)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + /* don't allow scanning right now */ + ret = -EBUSY; + goto out_sleep; + } + wl12xx_croc(wl, wl->dev_role_id); + wl12xx_cmd_role_stop_dev(wl); + } + ret = wl1271_scan(hw->priv, ssid, len, req); - +out_sleep: wl1271_ps_elp_sleep(wl); - out: mutex_unlock(&wl->mutex); @@ -3311,7 +3345,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, bool was_assoc = !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); - clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); + bool was_ifup = + !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, + &wl->flags); wl->aid = 0; /* free probe-request template */ @@ -3338,8 +3374,32 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* restore the bssid filter and go to dummy bssid */ if (was_assoc) { + u32 conf_flags = wl->hw->conf.flags; + /* + * we might have to disable roc, if there was + * no IF_OPER_UP notification. + */ + if (!was_ifup) { + ret = wl12xx_croc(wl, wl->role_id); + if (ret < 0) + goto out; + } + /* + * (we also need to disable roc in case of + * roaming on the same channel. until we will + * have a better flow...) + */ + if (test_bit(wl->dev_role_id, wl->roc_map)) { + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + } + wl1271_unjoin(wl); - wl1271_dummy_join(wl); + if (!(conf_flags & IEEE80211_CONF_IDLE)) { + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); + } } } } @@ -3400,7 +3460,29 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wl1271_warning("cmd join failed %d", ret); goto out; } - wl1271_check_operstate(wl, ieee80211_get_operstate(vif)); + + /* ROC until connected (after EAPOL exchange) */ + if (!is_ibss) { + ret = wl12xx_roc(wl, wl->role_id); + if (ret < 0) + goto out; + + wl1271_check_operstate(wl, + ieee80211_get_operstate(vif)); + } + /* + * stop device role if started (we might already be in + * STA role). TODO: make it better. + */ + if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) { + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + + ret = wl12xx_cmd_role_stop_dev(wl); + if (ret < 0) + goto out; + } } out: diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 54a4e75a37fe..653091a38dce 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -33,6 +33,7 @@ void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; + int ret; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, scan_complete_work); @@ -50,21 +51,28 @@ void wl1271_scan_complete_work(struct work_struct *work) wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; - ieee80211_scan_completed(wl->hw, false); - /* restore hardware connection monitoring template */ + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + 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_ps_elp_sleep(wl); - } + /* restore hardware connection monitoring template */ + wl1271_cmd_build_ap_probe_req(wl, wl->probereq); + } else { + /* restore remain on channel */ + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); } + wl1271_ps_elp_sleep(wl); if (wl->scan.failed) { wl1271_info("Scan completed due to error."); wl12xx_queue_recovery_work(wl); } + ieee80211_scan_completed(wl->hw, false); + out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index a2dbbadd58f0..057db6f86bee 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -78,6 +78,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, struct sk_buff *skb) { struct ieee80211_hdr *hdr; + int ret; hdr = (struct ieee80211_hdr *)(skb->data + sizeof(struct wl1271_tx_hw_descr)); @@ -91,6 +92,18 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (!ieee80211_is_auth(hdr->frame_control)) return 0; + if (wl->dev_hlid != WL12XX_INVALID_LINK_ID) + goto out; + + wl1271_debug(DEBUG_CMD, "starting device role for roaming"); + ret = wl12xx_cmd_role_start_dev(wl); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wl->dev_role_id); + if (ret < 0) + goto out; +out: return 0; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 089304d874d5..a136795352c8 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -319,7 +319,6 @@ struct wl1271_ap_key { enum wl12xx_flags { WL1271_FLAG_STA_ASSOCIATED, - WL1271_FLAG_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, @@ -402,6 +401,7 @@ struct wl1271 { unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; + unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; struct wl1271_acx_mem_map *target_mem_map; From 3be4112cb2c53fcda85fb408aea9a6f94075683b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:19 +0300 Subject: [PATCH 022/129] wl12xx: update BT coex configuration params The BT coex params api have been changed. Update it, and init coex for both sta and ap. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 40 +--- drivers/net/wireless/wl12xx/acx.h | 16 +- drivers/net/wireless/wl12xx/conf.h | 350 ++++++++++------------------- drivers/net/wireless/wl12xx/init.c | 5 +- drivers/net/wireless/wl12xx/main.c | 165 +++++--------- 5 files changed, 193 insertions(+), 383 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index a784ba6a8ef6..d783fce45613 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -528,13 +528,13 @@ out: return ret; } -int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) +int wl12xx_acx_sg_cfg(struct wl1271 *wl) { - struct acx_sta_bt_wlan_coex_param *param; + struct acx_bt_wlan_coex_param *param; struct conf_sg_settings *c = &wl->conf.sg; int i, ret; - wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); + wl1271_debug(DEBUG_ACX, "acx sg cfg"); param = kzalloc(sizeof(*param), GFP_KERNEL); if (!param) { @@ -543,38 +543,8 @@ int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) } /* BT-WLAN coext parameters */ - for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) - param->params[i] = cpu_to_le32(c->sta_params[i]); - param->param_idx = CONF_SG_PARAMS_ALL; - - ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); - if (ret < 0) { - wl1271_warning("failed to set sg config: %d", ret); - goto out; - } - -out: - kfree(param); - return ret; -} - -int wl1271_acx_ap_sg_cfg(struct wl1271 *wl) -{ - struct acx_ap_bt_wlan_coex_param *param; - struct conf_sg_settings *c = &wl->conf.sg; - int i, ret; - - wl1271_debug(DEBUG_ACX, "acx sg ap cfg"); - - param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) { - ret = -ENOMEM; - goto out; - } - - /* BT-WLAN coext parameters */ - for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++) - param->params[i] = cpu_to_le32(c->ap_params[i]); + for (i = 0; i < CONF_SG_PARAMS_MAX; i++) + param->params[i] = cpu_to_le32(c->params[i]); param->param_idx = CONF_SG_PARAMS_ALL; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 6909bc535a5d..5b3fabde0afe 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -302,23 +302,14 @@ struct acx_bt_wlan_coex { u8 pad[3]; } __packed; -struct acx_sta_bt_wlan_coex_param { +struct acx_bt_wlan_coex_param { struct acx_header header; - __le32 params[CONF_SG_STA_PARAMS_MAX]; + __le32 params[CONF_SG_PARAMS_MAX]; u8 param_idx; u8 padding[3]; } __packed; -struct acx_ap_bt_wlan_coex_param { - struct acx_header header; - - __le32 params[CONF_SG_AP_PARAMS_MAX]; - u8 param_idx; - u8 padding[3]; -} __packed; - - struct acx_dco_itrim_params { struct acx_header header; @@ -1269,8 +1260,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); -int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); -int wl1271_acx_ap_sg_cfg(struct wl1271 *wl); +int wl12xx_acx_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); int wl1271_acx_aid(struct wl1271 *wl, u16 aid); diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 30ee7d304bcc..a7c147838ab8 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -99,40 +99,75 @@ enum { enum { /* - * PER threshold in PPM of the BT voice + * Configure the min and max time BT gains the antenna + * in WLAN / BT master basic rate * - * Range: 0 - 10000000 + * Range: 0 - 255 (ms) */ - CONF_SG_BT_PER_THRESHOLD = 0, + CONF_SG_ACL_BT_MASTER_MIN_BR = 0, + CONF_SG_ACL_BT_MASTER_MAX_BR, /* - * Number of consequent RX_ACTIVE activities to override BT voice - * frames to ensure WLAN connection + * Configure the min and max time BT gains the antenna + * in WLAN / BT slave basic rate * - * Range: 0 - 100 + * Range: 0 - 255 (ms) */ - CONF_SG_HV3_MAX_OVERRIDE, + CONF_SG_ACL_BT_SLAVE_MIN_BR, + CONF_SG_ACL_BT_SLAVE_MAX_BR, /* - * Defines the PER threshold of the BT voice + * Configure the min and max time BT gains the antenna + * in WLAN / BT master EDR * - * Range: 0 - 65000 + * Range: 0 - 255 (ms) */ - CONF_SG_BT_NFS_SAMPLE_INTERVAL, + CONF_SG_ACL_BT_MASTER_MIN_EDR, + CONF_SG_ACL_BT_MASTER_MAX_EDR, /* - * Defines the load ratio of BT + * Configure the min and max time BT gains the antenna + * in WLAN / BT slave EDR * - * Range: 0 - 100 (%) + * Range: 0 - 255 (ms) */ - CONF_SG_BT_LOAD_RATIO, + CONF_SG_ACL_BT_SLAVE_MIN_EDR, + CONF_SG_ACL_BT_SLAVE_MAX_EDR, /* - * Defines whether the SG will force WLAN host to enter/exit PSM + * The maximum time WLAN can gain the antenna + * in WLAN PSM / BT master/slave BR * - * Range: 1 - SG can force, 0 - host handles PSM + * Range: 0 - 255 (ms) */ - CONF_SG_AUTO_PS_MODE, + CONF_SG_ACL_WLAN_PS_MASTER_BR, + CONF_SG_ACL_WLAN_PS_SLAVE_BR, + + /* + * The maximum time WLAN can gain the antenna + * in WLAN PSM / BT master/slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_ACL_WLAN_PS_MASTER_EDR, + CONF_SG_ACL_WLAN_PS_SLAVE_EDR, + + /* TODO: explain these values */ + CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR, + CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR, + CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR, + CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR, + CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR, + CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR, + CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR, + CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR, + + CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR, + CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR, + CONF_SG_ACL_PASSIVE_SCAN_BT_BR, + CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR, + CONF_SG_ACL_PASSIVE_SCAN_BT_EDR, + CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR, /* * Compensation percentage of probe requests when scan initiated @@ -150,6 +185,50 @@ enum { */ CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, + /* + * Compensation percentage of WLAN active scan window if initiated + * during BT A2DP + * + * Range: 0 - 1000 (%) + */ + CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT A2DP BR + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT A2DP EDR + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT voice + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, + + /* TODO: explain these values */ + CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN, + CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN, + CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN, + + /* + * Defines whether the SG will force WLAN host to enter/exit PSM + * + * Range: 1 - SG can force, 0 - host handles PSM + */ + CONF_SG_STA_FORCE_PS_IN_BT_SCO, + /* * Defines antenna configuration (single/dual antenna) * @@ -158,7 +237,7 @@ enum { CONF_SG_ANTENNA_CONFIGURATION, /* - * The threshold (percent) of max consequtive beacon misses before + * The threshold (percent) of max consecutive beacon misses before * increasing priority of beacon reception. * * Range: 0 - 100 (%) @@ -166,87 +245,11 @@ enum { CONF_SG_BEACON_MISS_PERCENT, /* - * The rate threshold below which receiving a data frame from the AP - * will increase the priority of the data frame above BT traffic. + * Protection time of the DHCP procedure. * - * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 + * Range: 0 - 100000 (ms) */ - CONF_SG_RATE_ADAPT_THRESH, - - /* - * Not used currently. - * - * Range: 0 - */ - CONF_SG_RATE_ADAPT_SNR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN PSM / BT master basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, - CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, - - /* - * The time after it expires no new WLAN trigger frame is trasmitted - * in WLAN PSM / BT master basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN PSM / BT slave basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, - CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, - - /* - * The time after it expires no new WLAN trigger frame is trasmitted - * in WLAN PSM / BT slave basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN PSM / BT master EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, - CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, - - /* - * The time after it expires no new WLAN trigger frame is trasmitted - * in WLAN PSM / BT master EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN PSM / BT slave EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, - CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, - - /* - * The time after it expires no new WLAN trigger frame is trasmitted - * in WLAN PSM / BT slave EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, + CONF_SG_DHCP_TIME, /* * RX guard time before the beginning of a new BT voice frame during @@ -273,6 +276,16 @@ enum { */ CONF_SG_ADAPTIVE_RXT_TXT, + /* TODO: explain this value */ + CONF_SG_GENERAL_USAGE_BIT_MAP, + + /* + * Number of consecutive BT voice frames not interrupted by WLAN + * + * Range: 0 - 100 + */ + CONF_SG_HV3_MAX_SERVED, + /* * The used WLAN legacy service period during active BT ACL link * @@ -287,152 +300,35 @@ enum { */ CONF_SG_UPSD_TIMEOUT, - /* - * Configure the min and max time BT gains the antenna - * in WLAN Active / BT master EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, - CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, + CONF_SG_CONSECUTIVE_CTS_THRESHOLD, + CONF_SG_STA_RX_WINDOW_AFTER_DTIM, + CONF_SG_STA_CONNECTION_PROTECTION_TIME, - /* - * The maximum time WLAN can gain the antenna for - * in WLAN Active / BT master EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, + /* AP params */ + CONF_AP_BEACON_MISS_TX, + CONF_AP_RX_WINDOW_AFTER_BEACON, + CONF_AP_BEACON_WINDOW_INTERVAL, + CONF_AP_CONNECTION_PROTECTION_TIME, + CONF_AP_BT_ACL_VAL_BT_SERVE_TIME, + CONF_AP_BT_ACL_VAL_WL_SERVE_TIME, - /* - * Configure the min and max time BT gains the antenna - * in WLAN Active / BT slave EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, - CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, - - /* - * The maximum time WLAN can gain the antenna for - * in WLAN Active / BT slave EDR - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN Active / BT basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, - CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, - - /* - * The maximum time WLAN can gain the antenna for - * in WLAN Active / BT basic rate - * - * Range: 0 - 255 (ms) - */ - CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, - - /* - * Compensation percentage of WLAN passive scan window if initiated - * during BT voice - * - * Range: 0 - 1000 (%) - */ - CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, - - /* - * Compensation percentage of WLAN passive scan window if initiated - * during BT A2DP - * - * Range: 0 - 1000 (%) - */ - CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, - - /* - * Fixed time ensured for BT traffic to gain the antenna during WLAN - * passive scan. - * - * Range: 0 - 1000 ms - */ - CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, - - /* - * Fixed time ensured for WLAN traffic to gain the antenna during WLAN - * passive scan. - * - * Range: 0 - 1000 ms - */ - CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, - - /* - * Number of consequent BT voice frames not interrupted by WLAN - * - * Range: 0 - 100 - */ - CONF_SG_HV3_MAX_SERVED, - - /* - * Protection time of the DHCP procedure. - * - * Range: 0 - 100000 (ms) - */ - CONF_SG_DHCP_TIME, - - /* - * Compensation percentage of WLAN active scan window if initiated - * during BT A2DP - * - * Range: 0 - 1000 (%) - */ - CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, CONF_SG_TEMP_PARAM_1, CONF_SG_TEMP_PARAM_2, CONF_SG_TEMP_PARAM_3, CONF_SG_TEMP_PARAM_4, CONF_SG_TEMP_PARAM_5, - - /* - * AP beacon miss - * - * Range: 0 - 255 - */ - CONF_SG_AP_BEACON_MISS_TX, - - /* - * AP RX window length - * - * Range: 0 - 50 - */ - CONF_SG_RX_WINDOW_LENGTH, - - /* - * AP connection protection time - * - * Range: 0 - 5000 - */ - CONF_SG_AP_CONNECTION_PROTECTION_TIME, - CONF_SG_TEMP_PARAM_6, CONF_SG_TEMP_PARAM_7, CONF_SG_TEMP_PARAM_8, CONF_SG_TEMP_PARAM_9, CONF_SG_TEMP_PARAM_10, - CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, - CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1, - + CONF_SG_PARAMS_MAX, CONF_SG_PARAMS_ALL = 0xff }; struct conf_sg_settings { - u32 sta_params[CONF_SG_STA_PARAMS_MAX]; - u32 ap_params[CONF_SG_AP_PARAMS_MAX]; + u32 params[CONF_SG_PARAMS_MAX]; u8 state; }; @@ -913,7 +809,7 @@ struct conf_conn_settings { struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT]; /* - * The number of consequtive beacons to lose, before the firmware + * The number of consecutive beacons to lose, before the firmware * becomes out of synch. * * Range: u32 @@ -951,7 +847,7 @@ struct conf_conn_settings { u8 rx_broadcast_in_ps; /* - * Consequtive PS Poll failures before sending event to driver + * Consecutive PS Poll failures before sending event to driver * * Range: u8 */ diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 1bc246f42a65..47d87aaa63a7 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -277,10 +277,7 @@ int wl1271_init_pta(struct wl1271 *wl) { int ret; - if (wl->bss_type == BSS_TYPE_AP_BSS) - ret = wl1271_acx_ap_sg_cfg(wl); - else - ret = wl1271_acx_sta_sg_cfg(wl); + ret = wl12xx_acx_sg_cfg(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 57b10e98730e..1774a6672314 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -52,110 +52,67 @@ static struct conf_drv_settings default_conf = { .sg = { - .sta_params = { - [CONF_SG_BT_PER_THRESHOLD] = 7500, - [CONF_SG_HV3_MAX_OVERRIDE] = 0, - [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, - [CONF_SG_BT_LOAD_RATIO] = 200, - [CONF_SG_AUTO_PS_MODE] = 1, - [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, - [CONF_SG_ANTENNA_CONFIGURATION] = 0, - [CONF_SG_BEACON_MISS_PERCENT] = 60, - [CONF_SG_RATE_ADAPT_THRESH] = 12, - [CONF_SG_RATE_ADAPT_SNR] = 0, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, - [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, - /* Note: with UPSD, this should be 4 */ - [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, - [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, - /* Note: with UPDS, this should be 15 */ - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, - /* Note: with UPDS, this should be 50 */ - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, - /* Note: with UPDS, this should be 10 */ - [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, - [CONF_SG_RXT] = 1200, - [CONF_SG_TXT] = 1000, - [CONF_SG_ADAPTIVE_RXT_TXT] = 1, - [CONF_SG_PS_POLL_TIMEOUT] = 10, - [CONF_SG_UPSD_TIMEOUT] = 10, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, - [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, - [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, - [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, - [CONF_SG_HV3_MAX_SERVED] = 6, - [CONF_SG_DHCP_TIME] = 5000, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, - }, - .ap_params = { - [CONF_SG_BT_PER_THRESHOLD] = 7500, - [CONF_SG_HV3_MAX_OVERRIDE] = 0, - [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, - [CONF_SG_BT_LOAD_RATIO] = 50, - [CONF_SG_AUTO_PS_MODE] = 1, - [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, - [CONF_SG_ANTENNA_CONFIGURATION] = 0, - [CONF_SG_BEACON_MISS_PERCENT] = 60, - [CONF_SG_RATE_ADAPT_THRESH] = 64, - [CONF_SG_RATE_ADAPT_SNR] = 1, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, - [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, - [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, - [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, - [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, - [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, - [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, - [CONF_SG_RXT] = 1200, - [CONF_SG_TXT] = 1000, - [CONF_SG_ADAPTIVE_RXT_TXT] = 1, - [CONF_SG_PS_POLL_TIMEOUT] = 10, - [CONF_SG_UPSD_TIMEOUT] = 10, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, - [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, - [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, - [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, - [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, - [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, - [CONF_SG_HV3_MAX_SERVED] = 6, - [CONF_SG_DHCP_TIME] = 5000, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, - [CONF_SG_TEMP_PARAM_1] = 0, - [CONF_SG_TEMP_PARAM_2] = 0, - [CONF_SG_TEMP_PARAM_3] = 0, - [CONF_SG_TEMP_PARAM_4] = 0, - [CONF_SG_TEMP_PARAM_5] = 0, - [CONF_SG_AP_BEACON_MISS_TX] = 3, - [CONF_SG_RX_WINDOW_LENGTH] = 6, - [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, - [CONF_SG_TEMP_PARAM_6] = 1, + .params = { + [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, + [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, + [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, + [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, + [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, + [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, + [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, + [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, + [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, + [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, + [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, + [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, + [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, + [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, + [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, + [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, + [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, + [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, + [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, + [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, + [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, + [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, + [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, + [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, + [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, + [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, + /* active scan params */ + [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, + /* passive scan params */ + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, + /* passive scan in dual antenna params */ + [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, + [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, + [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, + /* general params */ + [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, + [CONF_SG_ANTENNA_CONFIGURATION] = 0, + [CONF_SG_BEACON_MISS_PERCENT] = 60, + [CONF_SG_DHCP_TIME] = 5000, + [CONF_SG_RXT] = 1200, + [CONF_SG_TXT] = 1000, + [CONF_SG_ADAPTIVE_RXT_TXT] = 1, + [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, + [CONF_SG_HV3_MAX_SERVED] = 6, + [CONF_SG_PS_POLL_TIMEOUT] = 10, + [CONF_SG_UPSD_TIMEOUT] = 10, + [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, + [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, + [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, + /* AP params */ + [CONF_AP_BEACON_MISS_TX] = 3, + [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, + [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, + [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, + [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, + [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, }, .state = CONF_SG_PROTECTIVE, }, From 712e9bf750c5d0db63040c5695dacf38aed4f42c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:20 +0300 Subject: [PATCH 023/129] wl12xx: fix session counter Increment the session counter on every wl12xx_cmd_role_start_sta() command. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 12 +++++++++++- drivers/net/wireless/wl12xx/main.c | 6 +----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index c620a9d4939c..7c5d73845361 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -458,6 +458,16 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) *hlid = WL12XX_INVALID_LINK_ID; } +static int wl12xx_get_new_session_id(struct wl1271 *wl) +{ + if (wl->session_counter >= SESSION_COUNTER_MAX) + wl->session_counter = 0; + + wl->session_counter++; + + return wl->session_counter; +} + int wl12xx_cmd_role_start_dev(struct wl1271 *wl) { struct wl12xx_cmd_role_start *cmd; @@ -580,7 +590,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl) goto out_free; } cmd->sta.hlid = wl->sta_hlid; - cmd->sta.session = wl->session_counter; + cmd->sta.session = wl12xx_get_new_session_id(wl); cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1774a6672314..157c46237d9f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2187,11 +2187,6 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) goto out; set_bit(WL1271_FLAG_IDLE, &wl->flags); } else { - /* increment the session counter */ - wl->session_counter++; - if (wl->session_counter >= SESSION_COUNTER_MAX) - wl->session_counter = 0; - /* The current firmware only supports sched_scan in idle */ if (wl->sched_scanning) { wl1271_scan_sched_scan_stop(wl); @@ -4453,6 +4448,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->dev_role_id = WL12XX_INVALID_ROLE_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; + wl->session_counter = 0; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); wl->fwlog_size = 0; From e51ae9be2e313b63a43f1f93578d9a71d38a77ea Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:21 +0300 Subject: [PATCH 024/129] wl12xx: use dynamic hlids for AP-mode Using hlid=0 in AP mode is a bug. Dynamically allocate HLIDs. Set the "first sta hlid" as 3. This will have to be changed when multiple vifs will be supported. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 27 +++++++++++++++++++++++---- drivers/net/wireless/wl12xx/main.c | 9 +++++++-- drivers/net/wireless/wl12xx/tx.c | 17 ++++++----------- drivers/net/wireless/wl12xx/wl12xx.h | 13 ++++++++++--- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 7c5d73845361..025fb14184d6 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -682,11 +682,19 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) goto out; } + ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid); + if (ret < 0) + goto out_free; + + ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid); + if (ret < 0) + goto out_free_global; + cmd->role_id = wl->role_id; cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); cmd->ap.bss_index = WL1271_AP_BSS_INDEX; - cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID; - cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID; + cmd->ap.global_hlid = wl->ap_global_hlid; + cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; @@ -713,9 +721,17 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role start ap"); - goto out_free; + goto out_free_bcast; } + goto out_free; + +out_free_bcast: + wl12xx_free_link(wl, &wl->ap_bcast_hlid); + +out_free_global: + wl12xx_free_link(wl, &wl->ap_global_hlid); + out_free: kfree(cmd); @@ -744,6 +760,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) goto out_free; } + wl12xx_free_link(wl, &wl->ap_bcast_hlid); + wl12xx_free_link(wl, &wl->ap_global_hlid); + out_free: kfree(cmd); @@ -1253,7 +1272,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, if (!cmd) return -ENOMEM; - if (hlid == WL1271_AP_BROADCAST_HLID) { + if (hlid == wl->ap_bcast_hlid) { if (key_type == KEY_WEP) lid_type = WEP_DEFAULT_LID_TYPE; else diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 157c46237d9f..ea150b5ff9f5 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1972,8 +1972,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl1271_ps_elp_sleep(wl); } deinit: + /* clear all hlids (except system_hlid) */ wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; /* * this must be before the cancel_work calls below, so that the work @@ -2538,7 +2541,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) if (wep_key_added) { ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, - WL1271_AP_BROADCAST_HLID); + wl->ap_bcast_hlid); if (ret < 0) goto out; } @@ -2563,7 +2566,7 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, wl_sta = (struct wl1271_station *)sta->drv_priv; hlid = wl_sta->hlid; } else { - hlid = WL1271_AP_BROADCAST_HLID; + hlid = wl->ap_bcast_hlid; } if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { @@ -4449,6 +4452,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->dev_role_id = WL12XX_INVALID_ROLE_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->session_counter = 0; + wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); wl->fwlog_size = 0; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 057db6f86bee..1240f4094a8b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -38,7 +38,7 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) if (is_ap) ret = wl12xx_cmd_set_default_wep_key(wl, id, - WL1271_AP_BROADCAST_HLID); + wl->ap_bcast_hlid); else ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid); @@ -168,9 +168,9 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_mgmt(hdr->frame_control)) - return WL1271_AP_GLOBAL_HLID; + return wl->ap_global_hlid; else - return WL1271_AP_BROADCAST_HLID; + return wl->ap_bcast_hlid; } } @@ -317,17 +317,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else rate_idx = ACX_TX_BASIC_RATE; } else { - switch (hlid) { - case WL1271_AP_GLOBAL_HLID: + if (hlid == wl->ap_global_hlid) rate_idx = ACX_TX_AP_MODE_MGMT_RATE; - break; - case WL1271_AP_BROADCAST_HLID: + else if (hlid == wl->ap_bcast_hlid) rate_idx = ACX_TX_AP_MODE_BCST_RATE; - break; - default: + else rate_idx = ac; - break; - } } tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index a136795352c8..1313dc5b855e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -141,10 +141,15 @@ extern u32 wl12xx_debug_level; #define WL12XX_MAX_LINKS 8 #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff + +/* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 -#define WL1271_AP_GLOBAL_HLID 0 -#define WL1271_AP_BROADCAST_HLID 1 -#define WL1271_AP_STA_HLID_START 2 + +/* + * TODO: we currently don't support multirole. remove + * this constant from the code when we do. + */ +#define WL1271_AP_STA_HLID_START 3 /* * When in AP-mode, we allow (at least) this number of mem-blocks @@ -398,6 +403,8 @@ struct wl1271 { u8 system_hlid; u8 sta_hlid; u8 dev_hlid; + u8 ap_global_hlid; + u8 ap_bcast_hlid; unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; From 0f9c8250e10a16f48f82ffda3a5a7cb9e7b4a9ee Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 17 Aug 2011 10:45:49 +0300 Subject: [PATCH 025/129] wl12xx: re-enable block ack session support Incorporate interface changes for HT support. Add ba_bitmap field to the wl1271_link struct, to indicate activate RX BA sessions (for AP mode). Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 66 ++++-------- drivers/net/wireless/wl12xx/acx.h | 82 +++++---------- drivers/net/wireless/wl12xx/cmd.h | 1 + drivers/net/wireless/wl12xx/conf.h | 9 +- drivers/net/wireless/wl12xx/init.c | 37 ++----- drivers/net/wireless/wl12xx/main.c | 146 +++++++++++++++++++-------- drivers/net/wireless/wl12xx/wl12xx.h | 6 ++ 7 files changed, 177 insertions(+), 170 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index d783fce45613..ecbceb6f1ea9 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1323,19 +1323,15 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, goto out; } - /* Allow HT Operation ? */ if (allow_ht_operation) { - ht_capabilites = - WL1271_ACX_FW_CAP_HT_OPERATION; - if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) - ht_capabilites |= - WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; - if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) - ht_capabilites |= - WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; - if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) - ht_capabilites |= - WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; + /* no need to translate capabilities - use the spec values */ + ht_capabilites = ht_cap->cap; + + /* + * this bit is not employed by the spec but only by FW to + * indicate peer HT support + */ + ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION; /* get data from A-MPDU parameters field */ acx->ampdu_max_length = ht_cap->ampdu_factor; @@ -1392,14 +1388,12 @@ out: } /* Configure BA session initiator/receiver parameters setting in the FW. */ -int wl1271_acx_set_ba_session(struct wl1271 *wl, - enum ieee80211_back_parties direction, - u8 tid_index, u8 policy) +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) { - struct wl1271_acx_ba_session_policy *acx; + struct wl1271_acx_ba_initiator_policy *acx; int ret; - wl1271_debug(DEBUG_ACX, "acx ba session setting"); + wl1271_debug(DEBUG_ACX, "acx ba initiator policy"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { @@ -1407,33 +1401,18 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, goto out; } - /* ANY role */ - acx->role_id = 0xff; - acx->tid = tid_index; - acx->enable = policy; - acx->ba_direction = direction; - - switch (direction) { - case WLAN_BACK_INITIATOR: - acx->win_size = wl->conf.ht.tx_ba_win_size; - acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; - break; - case WLAN_BACK_RECIPIENT: - acx->win_size = RX_BA_WIN_SIZE; - acx->inactivity_timeout = 0; - break; - default: - wl1271_error("Incorrect acx command id=%x\n", direction); - ret = -EINVAL; - goto out; - } + /* set for the current role */ + acx->role_id = wl->role_id; + acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap; + acx->win_size = wl->conf.ht.tx_ba_win_size; + acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; ret = wl1271_cmd_configure(wl, - ACX_BA_SESSION_POLICY_CFG, + ACX_BA_SESSION_INIT_POLICY, acx, sizeof(*acx)); if (ret < 0) { - wl1271_warning("acx ba session setting failed: %d", ret); + wl1271_warning("acx ba initiator policy failed: %d", ret); goto out; } @@ -1443,8 +1422,8 @@ out: } /* setup BA session receiver setting in the FW. */ -int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, - bool enable) +int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, + u16 ssn, bool enable, u8 peer_hlid) { struct wl1271_acx_ba_receiver_setup *acx; int ret; @@ -1457,11 +1436,10 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, goto out; } - /* Single link for now */ - acx->link_id = 1; + acx->hlid = peer_hlid; acx->tid = tid_index; acx->enable = enable; - acx->win_size = 0; + acx->win_size = wl->conf.ht.rx_ba_win_size; acx->ssn = ssn; ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx, diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 5b3fabde0afe..82c9271b4e84 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -899,6 +899,10 @@ struct wl1271_acx_rssi_snr_avg_weights { u8 snr_data; }; + +/* special capability bit (not employed by the 802.11n spec) */ +#define WL12XX_HT_CAP_HT_OPERATION BIT(16) + /* * ACX_PEER_HT_CAP * Configure HT capabilities - declare the capabilities of the peer @@ -907,19 +911,7 @@ struct wl1271_acx_rssi_snr_avg_weights { struct wl1271_acx_ht_capabilities { struct acx_header header; - /* - * bit 0 - Allow HT Operation - * bit 1 - Allow Greenfield format in TX - * bit 2 - Allow Short GI in TX - * bit 3 - Allow L-SIG TXOP Protection in TX - * bit 4 - Allow HT Control fields in TX. - * Note, driver will still leave space for HT control in packets - * regardless of the value of this field. FW will be responsible - * to drop the HT field from any frame when this Bit set to 0. - * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD. - * Exact policy setting for this feature is TBD. - * Note, this bit can only be set to 1 if bit 3 is set to 1. - */ + /* bitmask of capability bits supported by the peer */ __le32 ht_capabilites; /* Indicates to which link these capabilities apply. */ @@ -937,15 +929,6 @@ struct wl1271_acx_ht_capabilities { u8 padding; } __packed; -/* HT Capabilites Fw Bit Mask Mapping */ -#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0) -#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1) -#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2) -#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3) -#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4) -#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5) - - /* * ACX_HT_BSS_OPERATION * Configure HT capabilities - AP rules for behavior in the BSS. @@ -979,57 +962,48 @@ struct wl1271_acx_ht_information { u8 padding[2]; } __packed; -#define RX_BA_WIN_SIZE 8 +#define RX_BA_MAX_SESSIONS 2 -struct wl1271_acx_ba_session_policy { +struct wl1271_acx_ba_initiator_policy { struct acx_header header; - /* - * Specifies role Id, Range 0-7, 0xFF means ANY role. - * Future use. For now this field is irrelevant - */ + + /* Specifies role Id, Range 0-7, 0xFF means ANY role. */ u8 role_id; + /* - * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id. - * Not applicable if Role Id is set to ANY. + * Per TID setting for allowing TX BA. Set a bit to 1 to allow + * TX BA sessions for the corresponding TID. */ - u8 link_id; - - u8 tid; - - u8 enable; + u8 tid_bitmap; /* Windows size in number of packets */ - u16 win_size; + u8 win_size; - /* - * As initiator inactivity timeout in time units(TU) of 1024us. - * As receiver reserved - */ + u8 padding1[1]; + + /* As initiator inactivity timeout in time units(TU) of 1024us */ u16 inactivity_timeout; - /* Initiator = 1/Receiver = 0 */ - u8 ba_direction; - - u8 padding[3]; + u8 padding[2]; } __packed; struct wl1271_acx_ba_receiver_setup { struct acx_header header; - /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */ - u8 link_id; + /* Specifies link id, range 0-31 */ + u8 hlid; u8 tid; u8 enable; - u8 padding[1]; - /* Windows size in number of packets */ - u16 win_size; + u8 win_size; /* BA session starting sequence number. RANGE 0-FFF */ u16 ssn; + + u8 padding[2]; } __packed; struct wl1271_acx_fw_tsf_information { @@ -1218,7 +1192,7 @@ enum { ACX_RSSI_SNR_WEIGHTS = 0x0052, ACX_KEEP_ALIVE_MODE = 0x0053, ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, - ACX_BA_SESSION_POLICY_CFG = 0x0055, + ACX_BA_SESSION_INIT_POLICY = 0x0055, ACX_BA_SESSION_RX_SETUP = 0x0056, ACX_PEER_HT_CAP = 0x0057, ACX_HT_BSS_OPERATION = 0x0058, @@ -1297,11 +1271,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, bool allow_ht_operation); int wl1271_acx_set_ht_information(struct wl1271 *wl, u16 ht_operation_mode); -int wl1271_acx_set_ba_session(struct wl1271 *wl, - enum ieee80211_back_parties direction, - u8 tid_index, u8 policy); -int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, - bool enable); +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); +int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, + u16 ssn, bool enable, u8 peer_hlid); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 5cf92e256641..8b32a57e1cc6 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -208,6 +208,7 @@ enum { CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ CMD_STATUS_TEMPLATE_OOM = 23, + CMD_STATUS_NO_RX_BA_SESSION = 24, MAX_COMMAND_STATUS = 0xff }; diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index a7c147838ab8..76b5c6233da4 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -557,6 +557,9 @@ struct conf_tx_ac_category { #define CONF_TX_MAX_TID_COUNT 8 +/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */ +#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F + enum { CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/ @@ -1095,8 +1098,12 @@ struct conf_rf_settings { }; struct conf_ht_setting { - u16 tx_ba_win_size; + u8 rx_ba_win_size; + u8 tx_ba_win_size; u16 inactivity_timeout; + + /* bitmap of enabled TIDs for TX BA sessions */ + u8 tx_ba_tid_bitmap; }; struct conf_memory_settings { diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 47d87aaa63a7..a374c2112be3 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -529,41 +529,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl) return 0; } -static void wl1271_check_ba_support(struct wl1271 *wl) -{ - /* validate FW cose ver x.x.x.50-60.x */ - if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) && - (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) { - wl->ba_support = true; - return; - } - - wl->ba_support = false; -} - static int wl1271_set_ba_policies(struct wl1271 *wl) { - u8 tid_index; - int ret = 0; - /* Reset the BA RX indicators */ wl->ba_rx_bitmap = 0; wl->ba_allowed = true; + wl->ba_rx_session_count = 0; - /* validate that FW support BA */ - wl1271_check_ba_support(wl); + /* BA is supported in STA/AP modes */ + if (wl->bss_type != BSS_TYPE_AP_BSS && + wl->bss_type != BSS_TYPE_STA_BSS) { + wl->ba_support = false; + return 0; + } - if (wl->ba_support) - /* 802.11n initiator BA session setting */ - for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT; - ++tid_index) { - ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR, - tid_index, true); - if (ret < 0) - break; - } + wl->ba_support = true; - return ret; + /* 802.11n initiator BA session setting */ + return wl12xx_acx_set_ba_initiator_policy(wl); } int wl1271_chip_specific_init(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index ea150b5ff9f5..934f5731fd73 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -286,8 +286,10 @@ static struct conf_drv_settings default_conf = { }, }, .ht = { + .rx_ba_win_size = 8, .tx_ba_win_size = 64, .inactivity_timeout = 10000, + .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, }, .mem_wl127x = { .num_stations = 1, @@ -3191,9 +3193,12 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } } - rcu_read_lock(); - sta = ieee80211_find_sta(vif, bss_conf->bssid); - if (sta) { + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!sta) + goto sta_not_found; + /* save the supp_rates of the ap */ sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; if (sta->ht_cap.ht_supported) @@ -3201,38 +3206,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); sta_ht_cap = sta->ht_cap; sta_exists = true; - } - rcu_read_unlock(); - if (sta_exists) { - /* handle new association with HT and HT information change */ - if ((changed & BSS_CHANGED_HT) && - (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, - true); - if (ret < 0) { - wl1271_warning("Set ht cap true failed %d", - ret); - goto out; - } - ret = wl1271_acx_set_ht_information(wl, - bss_conf->ht_operation_mode); - if (ret < 0) { - wl1271_warning("Set ht information failed %d", - ret); - goto out; - } - } - /* handle new association without HT and disassociation */ - else if (changed & BSS_CHANGED_ASSOC) { - ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, - false); - if (ret < 0) { - wl1271_warning("Set ht cap false failed %d", - ret); - goto out; - } - } +sta_not_found: + rcu_read_unlock(); } if ((changed & BSS_CHANGED_ASSOC)) { @@ -3440,6 +3416,41 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } } + /* Handle new association with HT. Do this only after join. */ + if (sta_exists) { + if ((changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, + true); + if (ret < 0) { + wl1271_warning("Set ht cap true failed %d", + ret); + goto out; + } + } + /* handle new association without HT and disassociation */ + else if (changed & BSS_CHANGED_ASSOC) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, + false); + if (ret < 0) { + wl1271_warning("Set ht cap false failed %d", + ret); + goto out; + } + } + } + + /* Handle HT information change. Only after join. */ + if (sta_exists && (changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_information(wl, + bss_conf->ht_operation_mode); + if (ret < 0) { + wl1271_warning("Set ht information failed %d", ret); + goto out; + } + } + out: return; } @@ -3623,6 +3634,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) __clear_bit(id, wl->ap_hlid_map); memset(wl->links[hlid].addr, 0, ETH_ALEN); + wl->links[hlid].ba_bitmap = 0; wl1271_tx_reset_link_queues(wl, hlid); __clear_bit(hlid, &wl->ap_ps_map); __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); @@ -3725,6 +3737,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; int ret; + u8 hlid, *ba_bitmap; + + wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, + tid); + + /* sanity check - the fields in FW are only 8bits wide */ + if (WARN_ON(tid > 0xFF)) + return -ENOTSUPP; mutex_lock(&wl->mutex); @@ -3733,6 +3753,20 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, goto out; } + if (wl->bss_type == BSS_TYPE_STA_BSS) { + hlid = wl->sta_hlid; + ba_bitmap = &wl->ba_rx_bitmap; + } else if (wl->bss_type == BSS_TYPE_AP_BSS) { + struct wl1271_station *wl_sta; + + wl_sta = (struct wl1271_station *)sta->drv_priv; + hlid = wl_sta->hlid; + ba_bitmap = &wl->links[hlid].ba_bitmap; + } else { + ret = -EINVAL; + goto out; + } + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -3742,20 +3776,46 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if ((wl->ba_support) && (wl->ba_allowed)) { - ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn, - true); - if (!ret) - wl->ba_rx_bitmap |= BIT(tid); - } else { + if (!wl->ba_support || !wl->ba_allowed) { ret = -ENOTSUPP; + break; + } + + if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) { + ret = -EBUSY; + wl1271_error("exceeded max RX BA sessions"); + break; + } + + if (*ba_bitmap & BIT(tid)) { + ret = -EINVAL; + wl1271_error("cannot enable RX BA session on active " + "tid: %d", tid); + break; + } + + ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true, + hlid); + if (!ret) { + *ba_bitmap |= BIT(tid); + wl->ba_rx_session_count++; } break; case IEEE80211_AMPDU_RX_STOP: - ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false); - if (!ret) - wl->ba_rx_bitmap &= ~BIT(tid); + if (!(*ba_bitmap & BIT(tid))) { + ret = -EINVAL; + wl1271_error("no active RX BA session on tid: %d", + tid); + break; + } + + ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false, + hlid); + if (!ret) { + *ba_bitmap &= ~BIT(tid); + wl->ba_rx_session_count--; + } break; /* diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 1313dc5b855e..487c3c7e0273 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -355,6 +355,9 @@ struct wl1271_link { u8 prev_freed_blks; u8 addr[ETH_ALEN]; + + /* bitmap of TIDs where RX BA sessions are active for this link */ + u8 ba_bitmap; }; struct wl1271 { @@ -609,6 +612,9 @@ struct wl1271 { /* Platform limitations */ unsigned int platform_quirks; + + /* number of currently active RX BA sessions */ + int ba_rx_session_count; }; struct wl1271_station { From b67476ef1a6417b92d3bb52510ceee266cd9ea1e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:23 +0300 Subject: [PATCH 026/129] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode After adding a station, call wl12xx_cmd_set_peer_state(). This is required for 11n support. Change wl12xx_cmd_set_peer_state() prototype to get hlid as param. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 6 +++--- drivers/net/wireless/wl12xx/cmd.h | 2 +- drivers/net/wireless/wl12xx/main.c | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 025fb14184d6..d655e629677c 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1321,12 +1321,12 @@ out: return ret; } -int wl12xx_cmd_set_peer_state(struct wl1271 *wl) +int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) { struct wl12xx_cmd_set_peer_state *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", wl->sta_hlid); + wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1334,7 +1334,7 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl) goto out; } - cmd->hlid = wl->sta_hlid; + cmd->hlid = hlid; cmd->state = WL1271_CMD_STA_STATE_CONNECTED; ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 8b32a57e1cc6..740d27edd02d 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -70,7 +70,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); -int wl12xx_cmd_set_peer_state(struct wl1271 *wl); +int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); int wl12xx_roc(struct wl1271 *wl, u8 role_id); int wl12xx_croc(struct wl1271 *wl, u8 role_id); int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 934f5731fd73..27333d1afd0d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -395,7 +395,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) return 0; - ret = wl12xx_cmd_set_peer_state(wl); + ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid); if (ret < 0) return ret; @@ -3676,6 +3676,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + ret = wl12xx_cmd_set_peer_state(wl, hlid); + if (ret < 0) + goto out_sleep; + out_sleep: wl1271_ps_elp_sleep(wl); From b42f068baab96a899bb5488ad9f0e72b14743ec5 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:24 +0300 Subject: [PATCH 027/129] wl12xx: don't remove key if hlid was already deleted If hlid was already removed, there is no need to remove its key (it might cause a fw crash, as the key is invalid). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d655e629677c..261807b45ab5 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1203,6 +1203,10 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, struct wl1271_cmd_set_keys *cmd; int ret = 0; + /* hlid might have already been deleted */ + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) + return 0; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; From 31cd3aed29ca7ebcdaa2570a891a3fab75fe35f6 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:25 +0300 Subject: [PATCH 028/129] wl12xx: add wl12xx_cmd_role_start_ibss() Add wl12xx_cmd_role_start_ibss() implementation and defintion. This function is used in order to start the IBSS role. Stopping the IBSS is done by using the same api as stop STA, so there is no need for a separate function. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 62 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/cmd.h | 1 + 2 files changed, 63 insertions(+) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 261807b45ab5..d8c391681041 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -617,6 +617,7 @@ out: return ret; } +/* use this function to stop ibss as well */ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) { struct wl12xx_cmd_role_stop *cmd; @@ -770,6 +771,67 @@ out: return ret; } +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) +{ + struct wl12xx_cmd_role_start *cmd; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); + + cmd->role_id = wl->role_id; + if (wl->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wl->channel; + cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->ibss.dtim_interval = bss_conf->dtim_period; + cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; + cmd->ibss.ssid_len = wl->ssid_len; + memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); + memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wl->rate_set); + + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->sta_hlid); + if (ret) + goto out_free; + } + cmd->ibss.hlid = wl->sta_hlid; + cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " + "basic_rate_set: 0x%x, remote_rates: 0x%x", + wl->role_id, cmd->sta.hlid, cmd->sta.session, + wl->basic_rate_set, wl->rate_set); + + wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error. */ + wl12xx_free_link(wl, &wl->sta_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + /** * send test command to firmware diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 740d27edd02d..22c2f373dd04 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -44,6 +44,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl); int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); int wl12xx_cmd_role_start_ap(struct wl1271 *wl); int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); From 227e81e18422851901b9de11c5955d292c4a47fc Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:26 +0300 Subject: [PATCH 029/129] wl12xx: support IBSS vif type Start IBSS role when the interface type is IBSS. As with sta role, use the dev role until the role is started. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 33 +++++++++++++++++++++++----- drivers/net/wireless/wl12xx/scan.c | 9 +++++++- drivers/net/wireless/wl12xx/tx.c | 3 ++- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 27333d1afd0d..e280d9d7911b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1770,6 +1770,9 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) case BSS_TYPE_STA_BSS: return WL1271_ROLE_STA; + case BSS_TYPE_IBSS: + return WL1271_ROLE_IBSS; + default: wl1271_error("invalid bss_type: %d", wl->bss_type); } @@ -1848,7 +1851,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto power_off; - if (wl->bss_type == BSS_TYPE_STA_BSS) { + if (wl->bss_type == BSS_TYPE_STA_BSS || + wl->bss_type == BSS_TYPE_IBSS) { /* * The device role is a special role used for * rx and tx frames prior to association (as @@ -2078,6 +2082,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; + bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); /* * One of the side effects of the JOIN command is that is clears @@ -2094,7 +2099,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) if (set_assoc) set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); - ret = wl12xx_cmd_role_start_sta(wl); + if (is_ibss) + ret = wl12xx_cmd_role_start_ibss(wl); + else + ret = wl12xx_cmd_role_start_sta(wl); if (ret < 0) goto out; @@ -3128,6 +3136,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, { bool do_join = false, set_assoc = false; bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + bool ibss_joined = false; u32 sta_rate_set = 0; int ret; struct ieee80211_sta *sta; @@ -3141,14 +3150,28 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, goto out; } - if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss) + if (changed & BSS_CHANGED_IBSS) { + if (bss_conf->ibss_joined) { + set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags); + ibss_joined = true; + } else { + if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, + &wl->flags)) { + wl1271_unjoin(wl); + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); + } + } + } + + if ((changed & BSS_CHANGED_BEACON_INT) && ibss_joined) do_join = true; /* Need to update the SSID (for filtering etc) */ - if ((changed & BSS_CHANGED_BEACON) && is_ibss) + if ((changed & BSS_CHANGED_BEACON) && ibss_joined) do_join = true; - if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) { + if ((changed & BSS_CHANGED_BEACON_ENABLED) && ibss_joined) { wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", bss_conf->enable_beacon ? "enabled" : "disabled"); diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 653091a38dce..7229eaa89018 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -34,6 +34,7 @@ void wl1271_scan_complete_work(struct work_struct *work) struct delayed_work *dwork; struct wl1271 *wl; int ret; + bool is_sta, is_ibss; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, scan_complete_work); @@ -59,7 +60,13 @@ void wl1271_scan_complete_work(struct work_struct *work) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { /* restore hardware connection monitoring template */ wl1271_cmd_build_ap_probe_req(wl, wl->probereq); - } else { + } + + /* return to ROC if needed */ + is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); + is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || + (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) { /* restore remain on channel */ wl12xx_cmd_role_start_dev(wl); wl12xx_roc(wl, wl->dev_role_id); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 1240f4094a8b..8fdffd08d492 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -182,7 +182,8 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) if (wl->bss_type == BSS_TYPE_AP_BSS) return wl12xx_tx_get_hlid_ap(wl, skb); - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) return wl->sta_hlid; else return wl->dev_hlid; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 487c3c7e0273..416d68ed95cf 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -324,6 +324,7 @@ struct wl1271_ap_key { enum wl12xx_flags { WL1271_FLAG_STA_ASSOCIATED, + WL1271_FLAG_IBSS_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, From 0b932ab9f156488a56577873b638ecb1e65fa8d7 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:27 +0300 Subject: [PATCH 030/129] wl12xx: AP-mode - set STA HT capabilities when adding a STA In addition, set global HT operation mode via ACX_HT_BSS_OPERATION when a change is detected by usermode Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 10 +++++---- drivers/net/wireless/wl12xx/acx.h | 2 +- drivers/net/wireless/wl12xx/main.c | 34 ++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index ecbceb6f1ea9..e047594794aa 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1309,13 +1309,15 @@ out: int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, - bool allow_ht_operation) + bool allow_ht_operation, u8 hlid) { struct wl1271_acx_ht_capabilities *acx; int ret = 0; u32 ht_capabilites = 0; - wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); + wl1271_debug(DEBUG_ACX, "acx ht capabilities setting " + "sta supp: %d sta cap: %d", ht_cap->ht_supported, + ht_cap->cap); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { @@ -1323,7 +1325,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, goto out; } - if (allow_ht_operation) { + if (allow_ht_operation && ht_cap->ht_supported) { /* no need to translate capabilities - use the spec values */ ht_capabilites = ht_cap->cap; @@ -1338,7 +1340,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, acx->ampdu_min_spacing = ht_cap->ampdu_density; } - acx->hlid = wl->sta_hlid; + acx->hlid = hlid; acx->ht_capabilites = cpu_to_le32(ht_capabilites); ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 82c9271b4e84..758c596f62f6 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1268,7 +1268,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, - bool allow_ht_operation); + bool allow_ht_operation, u8 hlid); int wl1271_acx_set_ht_information(struct wl1271 *wl, u16 ht_operation_mode); int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e280d9d7911b..0a0b4b634bd4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3124,6 +3124,18 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); if (ret < 0) goto out; + + /* Handle HT information change */ + if ((changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_information(wl, + bss_conf->ht_operation_mode); + if (ret < 0) { + wl1271_warning("Set ht information failed %d", ret); + goto out; + } + } + out: return; } @@ -3439,12 +3451,14 @@ sta_not_found: } } - /* Handle new association with HT. Do this only after join. */ + /* Handle new association with HT. Do this after join. */ if (sta_exists) { if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, - true); + ret = wl1271_acx_set_ht_capabilities(wl, + &sta_ht_cap, + true, + wl->sta_hlid); if (ret < 0) { wl1271_warning("Set ht cap true failed %d", ret); @@ -3453,8 +3467,10 @@ sta_not_found: } /* handle new association without HT and disassociation */ else if (changed & BSS_CHANGED_ASSOC) { - ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, - false); + ret = wl1271_acx_set_ht_capabilities(wl, + &sta_ht_cap, + false, + wl->sta_hlid); if (ret < 0) { wl1271_warning("Set ht cap false failed %d", ret); @@ -3463,8 +3479,8 @@ sta_not_found: } } - /* Handle HT information change. Only after join. */ - if (sta_exists && (changed & BSS_CHANGED_HT) && + /* Handle HT information change. Done after join. */ + if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { ret = wl1271_acx_set_ht_information(wl, bss_conf->ht_operation_mode); @@ -3703,6 +3719,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid); + if (ret < 0) + goto out_sleep; + out_sleep: wl1271_ps_elp_sleep(wl); From 99d5ad7b9ccedee4a9ff8e24688c7c20e428cd21 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:28 +0300 Subject: [PATCH 031/129] wl12xx: AP-mode - configure STA HT rates on join When a new STA joins the BSS, configure the HT rates it supports to the FW. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d8c391681041..d3e938012ac2 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1415,10 +1415,12 @@ out_free: out: return ret; } + int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) { struct wl12xx_cmd_add_peer *cmd; int ret; + u32 sta_rates; wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); @@ -1437,8 +1439,12 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) cmd->hlid = hlid; cmd->wmm = sta->wme ? 1 : 0; - cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, - sta->supp_rates[wl->band])); + sta_rates = sta->supp_rates[wl->band]; + if (sta->ht_cap.ht_supported) + sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; + + cmd->supported_rates = + cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates)); wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates); From 1a8adb67f9c37cad9539dd9dcb289ce1411680fc Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:29 +0300 Subject: [PATCH 032/129] wl12xx: AP-mode - configure HT rate support to the FW Unconditionally configure HT rate support to the FW on all ACs when starting the AP. When 11n support is disabled by usermode (hostapd), each STA joining the AP will appear as a non-HT STA. This will stop us from accidentally transmitting using MCS rates. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/conf.h | 5 +++++ drivers/net/wireless/wl12xx/init.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 76b5c6233da4..82f205c43342 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -441,6 +441,11 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_54MBPS) +#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 | \ + CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 | \ + CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 | \ + CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \ + CONF_HW_BIT_RATE_MCS_7) /* * Default rates for management traffic when operating in AP mode. This diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index a374c2112be3..b13bebea95e0 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -515,6 +515,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl) else supported_rates = CONF_TX_AP_ENABLED_RATES; + /* unconditionally enable HT rates */ + supported_rates |= CONF_TX_MCS_RATES; + /* configure unicast TX rate classes */ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { rc.enabled_rates = supported_rates; From 7f97b487c4a9634afc008a76ff26268147d7ee8e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:30 +0300 Subject: [PATCH 033/129] wl12xx: use ap_bcast_hlid for recorded keys when the key was recorded, wl->ap_bcast_hlid was invalid (since the role wasn't started), so when configuring the key we need to use the current ap_bcast_hlid. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0a0b4b634bd4..360e33ed3ddb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2533,14 +2533,19 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) bool wep_key_added = false; for (i = 0; i < MAX_NUM_KEYS; i++) { + u8 hlid; if (wl->recorded_ap_keys[i] == NULL) break; key = wl->recorded_ap_keys[i]; + hlid = key->hlid; + if (hlid == WL12XX_INVALID_LINK_ID) + hlid = wl->ap_bcast_hlid; + ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, key->id, key->key_type, key->key_size, key->key, - key->hlid, key->tx_seq_32, + hlid, key->tx_seq_32, key->tx_seq_16); if (ret < 0) goto out; From 010d3d30a218fba961bd3d250a59b0ce9d5278f3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:31 +0300 Subject: [PATCH 034/129] wl12xx: don't remove key if hlid was already deleted When wep key was removed after disconnection, sta_hlid was invalid, and it resulted in a fw crash. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 360e33ed3ddb..c917f69f0069 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2625,6 +2625,11 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr)) return 0; + /* don't remove key if hlid was already deleted */ + if (action == KEY_REMOVE && + wl->sta_hlid == WL12XX_INVALID_LINK_ID) + return 0; + ret = wl1271_cmd_set_sta_key(wl, action, id, key_type, key_size, key, addr, tx_seq_32, From bf54e301671a6ece6c94550294dc7faf14158cd3 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:32 +0300 Subject: [PATCH 035/129] wl12xx: track freed packets in FW by AC Track the number of freed packets in each AC when receiving an interrupt from the FW. This paves the way for tracking allocated packets per AC. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 16 +++++++++++++++- drivers/net/wireless/wl12xx/tx.c | 2 ++ drivers/net/wireless/wl12xx/wl12xx.h | 8 ++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c917f69f0069..09cecb336d53 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -814,6 +814,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; int avail, freed_blocks; + int i; wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); @@ -824,6 +825,15 @@ static void wl12xx_fw_status(struct wl1271 *wl, status->drv_rx_counter, status->tx_results_counter); + for (i = 0; i < NUM_TX_QUEUES; i++) { + /* prevent wrap-around in freed-packets counter */ + wl->tx_allocated_pkts -= + (status->tx_released_pkts[i] - + wl->tx_pkts_freed[i]) & 0xff; + + wl->tx_pkts_freed[i] = status->tx_released_pkts[i]; + } + freed_blocks = le32_to_cpu(status->total_released_blks) - wl->tx_blocks_freed; wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); @@ -1934,7 +1944,7 @@ out: static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { - int ret; + int ret, i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2050,6 +2060,10 @@ deinit: wl->tx_blocks_freed = 0; + wl->tx_allocated_pkts = 0; + for (i = 0; i < NUM_TX_QUEUES; i++) + wl->tx_pkts_freed[i] = 0; + wl1271_debugfs_reset(wl); kfree(wl->fw_status); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8fdffd08d492..7dd6d8b94f64 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -242,6 +242,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, wl->tx_blocks_available -= total_blocks; wl->tx_allocated_blocks += total_blocks; + wl->tx_allocated_pkts++; + if (wl->bss_type == BSS_TYPE_AP_BSS) wl->links[hlid].allocated_blks += total_blocks; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 416d68ed95cf..24b40251535b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -268,8 +268,8 @@ struct wl12xx_fw_status { /* Size (in Memory Blocks) of TX pool */ __le32 tx_total; - /* Cumulative counter of released mem-blocks per AC */ - u8 tx_released_blks[NUM_TX_QUEUES]; + /* Cumulative counter of released packets per AC */ + u8 tx_released_pkts[NUM_TX_QUEUES]; /* Cumulative counter of freed MBs per HLID */ u8 tx_lnk_free_blks[WL12XX_MAX_LINKS]; @@ -422,6 +422,10 @@ struct wl1271 { u32 tx_allocated_blocks; u32 tx_results_count; + /* Accounting for allocated / available Tx packets in HW */ + u32 tx_pkts_freed[NUM_TX_QUEUES]; + u32 tx_allocated_pkts; + /* Transmitted TX packets counter for chipset interface */ u32 tx_packets_count; From 742246f8bc16c3a1a556c68ca2fabca162d14c24 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:33 +0300 Subject: [PATCH 036/129] wl12xx: schedule TX packets according to FW packet occupancy When selecting packets for transmission, prefer the ACs that are least occupied in the FW. When packets for multiple ACs are present in the FW, it decides which to transmit according to WMM QoS parameters. With these changes, lower priority ACs should not be starved when higher priority traffic is present. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 4 ++ drivers/net/wireless/wl12xx/main.c | 7 +-- drivers/net/wireless/wl12xx/tx.c | 71 ++++++++++++++++++--------- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 3102652c7625..d59354f53702 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -340,6 +340,10 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_blocks_available); DRIVER_STATE_PRINT_INT(tx_allocated_blocks); + DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); + DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]); + DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]); + DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]); DRIVER_STATE_PRINT_INT(tx_frames_cnt); DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); DRIVER_STATE_PRINT_INT(tx_queue_count[0]); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 09cecb336d53..027b6742a151 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -827,7 +827,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, for (i = 0; i < NUM_TX_QUEUES; i++) { /* prevent wrap-around in freed-packets counter */ - wl->tx_allocated_pkts -= + wl->tx_allocated_pkts[i] -= (status->tx_released_pkts[i] - wl->tx_pkts_freed[i]) & 0xff; @@ -2060,9 +2060,10 @@ deinit: wl->tx_blocks_freed = 0; - wl->tx_allocated_pkts = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) + for (i = 0; i < NUM_TX_QUEUES; i++) { wl->tx_pkts_freed[i] = 0; + wl->tx_allocated_pkts[i] = 0; + } wl1271_debugfs_reset(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7dd6d8b94f64..ccbcd0a4d2bf 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -205,7 +205,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 len; u32 total_blocks; - int id, ret = -EBUSY; + int id, ret = -EBUSY, ac; /* we use 1 spare block */ u32 spare_blocks = 1; @@ -242,7 +242,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, wl->tx_blocks_available -= total_blocks; wl->tx_allocated_blocks += total_blocks; - wl->tx_allocated_pkts++; + ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + wl->tx_allocated_pkts[ac]++; if (wl->bss_type == BSS_TYPE_AP_BSS) wl->links[hlid].allocated_blks += total_blocks; @@ -485,21 +486,45 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl) } } +static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, + struct sk_buff_head *queues) +{ + int i, q = -1, ac; + u32 min_pkts = 0xffffffff; + + /* + * Find a non-empty ac where: + * 1. There are packets to transmit + * 2. The FW has the least allocated blocks + * + * We prioritize the ACs according to VO>VI>BE>BK + */ + for (i = 0; i < NUM_TX_QUEUES; i++) { + ac = wl1271_tx_get_queue(i); + if (!skb_queue_empty(&queues[ac]) && + (wl->tx_allocated_pkts[ac] < min_pkts)) { + q = ac; + min_pkts = wl->tx_allocated_pkts[q]; + } + } + + if (q == -1) + return NULL; + + return &queues[q]; +} + static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) { struct sk_buff *skb = NULL; unsigned long flags; + struct sk_buff_head *queue; - skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); - if (skb) + queue = wl1271_select_queue(wl, wl->tx_queue); + if (!queue) goto out; - skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); - if (skb) - goto out; - skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); - if (skb) - goto out; - skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); + + skb = skb_dequeue(queue); out: if (skb) { @@ -517,6 +542,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) struct sk_buff *skb = NULL; unsigned long flags; int i, h, start_hlid; + struct sk_buff_head *queue; /* start from the link after the last one */ start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; @@ -525,21 +551,20 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) for (i = 0; i < AP_MAX_LINKS; i++) { h = (start_hlid + i) % AP_MAX_LINKS; - skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]); + /* only consider connected stations */ + if (h >= WL1271_AP_STA_HLID_START && + !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) + continue; + + queue = wl1271_select_queue(wl, wl->links[h].tx_queue); + if (!queue) + continue; + + skb = skb_dequeue(queue); if (skb) - goto out; - skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]); - if (skb) - goto out; - skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]); - if (skb) - goto out; - skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]); - if (skb) - goto out; + break; } -out: if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->last_tx_hlid = h; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 24b40251535b..6118df5b742d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -424,7 +424,7 @@ struct wl1271 { /* Accounting for allocated / available Tx packets in HW */ u32 tx_pkts_freed[NUM_TX_QUEUES]; - u32 tx_allocated_pkts; + u32 tx_allocated_pkts[NUM_TX_QUEUES]; /* Transmitted TX packets counter for chipset interface */ u32 tx_packets_count; From bdf91cfae66dd76a093c75cac8f6ada12fd21b83 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:34 +0300 Subject: [PATCH 037/129] wl12xx: handle wrap-around overflow in released Tx blocks FW counter When the FW Tx released blocks counter wraps around, we should correct our calculation of released blocks. Otherwise we add a large negative figure to our driver freed blocks counter Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 027b6742a151..0fa3a2281ddb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -834,8 +834,15 @@ static void wl12xx_fw_status(struct wl1271 *wl, wl->tx_pkts_freed[i] = status->tx_released_pkts[i]; } - freed_blocks = le32_to_cpu(status->total_released_blks) - - wl->tx_blocks_freed; + /* prevent wrap-around in total blocks counter */ + if (likely(wl->tx_blocks_freed <= + le32_to_cpu(status->total_released_blks))) + freed_blocks = le32_to_cpu(status->total_released_blks) - + wl->tx_blocks_freed; + else + freed_blocks = 0x100000000LL - wl->tx_blocks_freed + + le32_to_cpu(status->total_released_blks); + wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); wl->tx_allocated_blocks -= freed_blocks; From 769d7ac62d328ff2c126fdee461b7d46e7ea89f4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:36 +0300 Subject: [PATCH 038/129] wl12xx: don't wait for disconnection event Sometimes the fw doesn't send the DISCONNECT_EVENT_COMPLETE_ID on station role stop, so don't wait for it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d3e938012ac2..817bc183bc83 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -644,12 +644,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) goto out_free; } - ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); - if (ret < 0) { - wl1271_error("cmd role stop sta event completion error"); - goto out_free; - } - wl12xx_free_link(wl, &wl->sta_hlid); out_free: From 9b17f1b371c5aa5179b3e5392bc22132a3371da4 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:35 +0300 Subject: [PATCH 039/129] wl12xx: enable AP advanced functionality This adjusts FW TX block allocation for connected stations in PS. Firmware congestion is measured in allocated packets instead of blocks. Allow a link in PS to queue up to 2 packets to the FW. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 54 ++++++++++++++-------------- drivers/net/wireless/wl12xx/ps.c | 4 +-- drivers/net/wireless/wl12xx/tx.c | 19 +++++----- drivers/net/wireless/wl12xx/wl12xx.h | 25 +++++++------ 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0fa3a2281ddb..ad0b5a163b9d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -755,8 +755,7 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -#if 0 -static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks) +static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) { bool fw_ps; @@ -768,21 +767,29 @@ static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks) /* * Wake up from high level PS if the STA is asleep with too little - * blocks in FW or if the STA is awake. + * packets in FW or if the STA is awake. */ - if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS) + if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) wl1271_ps_link_end(wl, hlid); /* Start high-level PS if the STA is asleep with enough blocks in FW */ - else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) + else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) wl1271_ps_link_start(wl, hlid, true); } -static void wl1271_irq_update_links_status(struct wl1271 *wl, - struct wl1271_fw_ap_status *status) +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) +{ + int id = hlid - WL1271_AP_STA_HLID_START; + return test_bit(id, wl->ap_hlid_map); +} + +static void wl12xx_irq_update_links_status(struct wl1271 *wl, + struct wl12xx_fw_status *status) { u32 cur_fw_ps_map; - u8 hlid; + u8 hlid, cnt; + + /* TODO: also use link_fast_bitmap here */ cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); if (wl->ap_fw_ps_map != cur_fw_ps_map) { @@ -795,18 +802,20 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, } for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { - u8 cnt = status->tx_lnk_free_blks[hlid] - - wl->links[hlid].prev_freed_blks; + if (!wl1271_is_active_sta(wl, hlid)) + continue; - wl->links[hlid].prev_freed_blks = - status->tx_lnk_free_blks[hlid]; - wl->links[hlid].allocated_blks -= cnt; + cnt = status->tx_lnk_free_pkts[hlid] - + wl->links[hlid].prev_freed_pkts; - wl1271_irq_ps_regulate_link(wl, hlid, - wl->links[hlid].allocated_blks); + wl->links[hlid].prev_freed_pkts = + status->tx_lnk_free_pkts[hlid]; + wl->links[hlid].allocated_pkts -= cnt; + + wl12xx_irq_ps_regulate_link(wl, hlid, + wl->links[hlid].allocated_pkts); } } -#endif static void wl12xx_fw_status(struct wl1271 *wl, struct wl12xx_fw_status *status) @@ -865,11 +874,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* for AP update num of allocated TX blocks per link and ps status */ - if (wl->bss_type == BSS_TYPE_AP_BSS) { -#if 0 - wl1271_irq_update_links_status(wl, status); -#endif - } + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl12xx_irq_update_links_status(wl, status); /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -3711,12 +3717,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); } -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -{ - int id = hlid - WL1271_AP_STA_HLID_START; - return test_bit(id, wl->ap_hlid_map); -} - static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 3548377ab9c2..4b720b1b9f65 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -226,8 +226,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) if (test_bit(hlid, &wl->ap_ps_map)) return; - wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d " - "clean_queues %d", hlid, wl->links[hlid].allocated_blks, + wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d " + "clean_queues %d", hlid, wl->links[hlid].allocated_pkts, clean_queues); rcu_read_lock(); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index ccbcd0a4d2bf..0f1578577b1a 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -123,27 +123,25 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, wl1271_acx_set_inconnection_sta(wl, hdr->addr1); } -#if 0 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) { bool fw_ps; - u8 tx_blks; + u8 tx_pkts; /* only regulate station links */ if (hlid < WL1271_AP_STA_HLID_START) return; fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); - tx_blks = wl->links[hlid].allocated_blks; + tx_pkts = wl->links[hlid].allocated_pkts; /* * if in FW PS and there is enough data in FW we can put the link * into high-level PS and clean out its TX queues. */ - if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) + if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) wl1271_ps_link_start(wl, hlid, true); } -#endif static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) { @@ -245,8 +243,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->links[hlid].allocated_blks += total_blocks; + if (wl->bss_type == BSS_TYPE_AP_BSS && + hlid >= WL1271_AP_STA_HLID_START) + wl->links[hlid].allocated_pkts++; ret = 0; @@ -414,9 +413,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); -#if 0 wl1271_tx_regulate_link(wl, hlid); -#endif } else { wl1271_tx_update_filters(wl, skb); } @@ -888,8 +885,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) if (wl->bss_type == BSS_TYPE_AP_BSS) { for (i = 0; i < AP_MAX_LINKS; i++) { wl1271_tx_reset_link_queues(wl, i); - wl->links[i].allocated_blks = 0; - wl->links[i].prev_freed_blks = 0; + wl->links[i].allocated_pkts = 0; + wl->links[i].prev_freed_pkts = 0; } wl->last_tx_hlid = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 6118df5b742d..61a7c2163ea2 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -152,15 +152,14 @@ extern u32 wl12xx_debug_level; #define WL1271_AP_STA_HLID_START 3 /* - * When in AP-mode, we allow (at least) this number of mem-blocks + * When in AP-mode, we allow (at least) this number of packets * to be transmitted to FW for a STA in PS-mode. Only when packets are * present in the FW buffers it will wake the sleeping STA. We want to put * enough packets for the driver to transmit all of its buffered data before - * the STA goes to sleep again. But we don't want to take too much mem-blocks + * the STA goes to sleep again. But we don't want to take too much memory * as it might hurt the throughput of active STAs. - * The number of blocks (18) is enough for 2 large packets. */ -#define WL1271_PS_STA_MAX_BLOCKS (2 * 9) +#define WL1271_PS_STA_MAX_PACKETS 2 #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 @@ -237,8 +236,12 @@ struct wl1271_stats { #define AP_MAX_STATIONS 5 -/* Broadcast and Global links + links to stations */ -#define AP_MAX_LINKS (AP_MAX_STATIONS + 2) +/* Broadcast and Global links + system link + links to stations */ +/* + * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all + * the places that use this. + */ +#define AP_MAX_LINKS (AP_MAX_STATIONS + 3) /* FW status registers */ struct wl12xx_fw_status { @@ -271,8 +274,8 @@ struct wl12xx_fw_status { /* Cumulative counter of released packets per AC */ u8 tx_released_pkts[NUM_TX_QUEUES]; - /* Cumulative counter of freed MBs per HLID */ - u8 tx_lnk_free_blks[WL12XX_MAX_LINKS]; + /* Cumulative counter of freed packets per HLID */ + u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; /* Cumulative counter of released Voice memory blocks */ u8 tx_voice_released_blks; @@ -351,9 +354,9 @@ struct wl1271_link { /* AP-mode - TX queue per AC in link */ struct sk_buff_head tx_queue[NUM_TX_QUEUES]; - /* accounting for allocated / available TX blocks in FW */ - u8 allocated_blks; - u8 prev_freed_blks; + /* accounting for allocated / freed packets in FW */ + u8 allocated_pkts; + u8 prev_freed_pkts; u8 addr[ETH_ALEN]; From cf42039f33c8c7c12f19390661eb00ba47b96f91 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:37 +0300 Subject: [PATCH 040/129] wl12xx: set the AP-started flag only after setting keys This fix eliminates a potential race between starting the AP role and setting encryption keys. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index ad0b5a163b9d..a23b394291f2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3140,12 +3140,12 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if (ret < 0) goto out; - set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); - wl1271_debug(DEBUG_AP, "started AP"); - ret = wl1271_ap_init_hwenc(wl); if (ret < 0) goto out; + + set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); + wl1271_debug(DEBUG_AP, "started AP"); } } else { if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { From 04216da393e1f6653cc99a58f2fa48d0dde417c0 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:38 +0300 Subject: [PATCH 041/129] wl12xx: AP-mode - prevent Tx to stale/invalid stations Don't pollute the queues with Tx directed to invalid stations. This can happen during recovery. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a23b394291f2..b06ff0b25de1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -779,7 +779,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) { - int id = hlid - WL1271_AP_STA_HLID_START; + int id; + + /* global/broadcast "stations" are always active */ + if (hlid < WL1271_AP_STA_HLID_START) + return true; + + id = hlid - WL1271_AP_STA_HLID_START; return test_bit(id, wl->ap_hlid_map); } @@ -1493,6 +1499,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) /* queue the packet */ if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (!wl1271_is_active_sta(wl, hlid)) { + wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", + hlid, q); + dev_kfree_skb(skb); + goto out; + } + wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); } else { @@ -1508,6 +1521,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags)) ieee80211_queue_work(wl->hw, &wl->tx_work); +out: spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -3695,7 +3709,7 @@ static int wl1271_allocate_sta(struct wl1271 *wl, } wl_sta = (struct wl1271_station *)sta->drv_priv; - __set_bit(id, wl->ap_hlid_map); + set_bit(id, wl->ap_hlid_map); wl_sta->hlid = WL1271_AP_STA_HLID_START + id; *hlid = wl_sta->hlid; memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); @@ -3709,7 +3723,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) return; - __clear_bit(id, wl->ap_hlid_map); + clear_bit(id, wl->ap_hlid_map); memset(wl->links[hlid].addr, 0, ETH_ALEN); wl->links[hlid].ba_bitmap = 0; wl1271_tx_reset_link_queues(wl, hlid); From 04b4d69c89593d907d81a4aa33e4e42a632fe436 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 14 Aug 2011 13:17:39 +0300 Subject: [PATCH 042/129] wl12xx: fix tx_queue_count spurious increment Only increment the queue count after actually queuing the skb. This avoids a spurious increment is case of dropped packets. Also move the Tx-watermark checking code after the packet is enqueued. This makes the count more accurate - it includes the just-queued packet. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b06ff0b25de1..82f4408e89ad 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1485,18 +1485,6 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_lock_irqsave(&wl->wl_lock, flags); - wl->tx_queue_count[q]++; - - /* - * The workqueue is slow to process the tx_queue and we need stop - * the queue here, otherwise the queue will get too long. - */ - if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { - wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); - ieee80211_stop_queue(wl->hw, mapping); - set_bit(q, &wl->stopped_queues_map); - } - /* queue the packet */ if (wl->bss_type == BSS_TYPE_AP_BSS) { if (!wl1271_is_active_sta(wl, hlid)) { @@ -1512,6 +1500,18 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) skb_queue_tail(&wl->tx_queue[q], skb); } + wl->tx_queue_count[q]++; + + /* + * The workqueue is slow to process the tx_queue and we need stop + * the queue here, otherwise the queue will get too long. + */ + if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { + wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); + ieee80211_stop_queue(wl->hw, mapping); + set_bit(q, &wl->stopped_queues_map); + } + /* * The chip specific setup must run before the first TX packet - * before that, the tx_work will not be initialized! From b38de31ffa870323c4f6957904303477c88fe905 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 7 Jun 2011 22:36:14 +0200 Subject: [PATCH 043/129] net/mac80211/debugfs: Convert to kstrou8_from_user This patch replaces the code for getting an number from a userspace buffer by a simple call to kstrou8_from_user. This makes it easier to read and less error prone. Since the old buffer was only 10 bytes long and the value is masked by a nibble-mask anyway, we don't need to use kstrtoul but rather kstrtou8. Kernel Version: v3.0-rc2 Signed-off-by: Peter Huewe Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 186e02f7cc32..267ed45ef6a2 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -195,20 +195,12 @@ static ssize_t uapsd_queues_write(struct file *file, size_t count, loff_t *ppos) { struct ieee80211_local *local = file->private_data; - unsigned long val; - char buf[10]; - size_t len; + u8 val; int ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - - ret = strict_strtoul(buf, 0, &val); - + ret = kstrtou8_from_user(user_buf, count, 0, &val); if (ret) - return -EINVAL; + return ret; if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) return -ERANGE; From 817a53d9866ab4118e2dd17a9ffe80700eac40ac Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 24 Aug 2011 15:12:41 -0400 Subject: [PATCH 044/129] mac80211: refactor skb copy to failq in mesh_path_move_to_queue This seems a bit less awkward... Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 3c2bcb2de844..ede4f5242e0b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -307,14 +307,14 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, while (num_skbs--) { skb = __skb_dequeue(&failq); - if (copy) + if (copy) { cp_skb = skb_copy(skb, GFP_ATOMIC); + if (cp_skb) + __skb_queue_tail(&failq, cp_skb); + } prepare_for_gate(skb, gate_mpath->dst, gate_mpath); __skb_queue_tail(&gateq, skb); - - if (copy && cp_skb) - __skb_queue_tail(&failq, cp_skb); } spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); From 4a711a8559adbf8639d445d8bf195fc929680d11 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 25 Aug 2011 17:07:24 +0200 Subject: [PATCH 045/129] cfg80211: document wiphy->registered Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 88112ca59c8e..eb2659aefd97 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1792,6 +1792,7 @@ struct wiphy_wowlan_support { * @debugfsdir: debugfs directory used for this wiphy, will be renamed * automatically on wiphy renames * @dev: (virtual) struct device for this wiphy + * @registered: helps synchronize suspend/resume with wiphy unregister * @wext: wireless extension handlers * @priv: driver private data (sized according to wiphy_new() parameter) * @interface_modes: bitmask of interfaces types valid for this wiphy, From 397e5d5b93ba99ad3dc56f1e294f487e77d2daa8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 25 Aug 2011 21:33:48 +0200 Subject: [PATCH 046/129] ath9k: add missing AR9340 in ath_mac_bb_names AR9340 is not listed in ath_mac_bb_names, which leads to such a message: ieee80211 phy0: Atheros AR???? Rev:0 mem=0xb8100000, irq=2 Signed-off-by: Florian Fainelli Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a0d1147844fb..7bfc8f65a67d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2754,6 +2754,7 @@ static struct { { AR_SREV_VERSION_9271, "9271" }, { AR_SREV_VERSION_9300, "9300" }, { AR_SREV_VERSION_9330, "9330" }, + { AR_SREV_VERSION_9340, "9340" }, { AR_SREV_VERSION_9485, "9485" }, }; From 1cda0fd6096355ad4b0d99b691c2f9ca3198d745 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 25 Aug 2011 23:47:35 +0200 Subject: [PATCH 047/129] p54: Use do_div for 64-bit division to fix 32-bit kernels Use the do_div macro for 64-bit division. Otherwise, the module will reference __udivdi3 under 32-bit kernels, which is not allowed in kernel space. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 44a3bd4b0f43..2b97a89e7ff8 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -582,10 +583,13 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) if (chan) { struct survey_info *survey = &priv->survey[chan->hw_value]; survey->noise = clamp_t(s8, priv->noise, -128, 127); - survey->channel_time = priv->survey_raw.active / 1024; - survey->channel_time_tx = priv->survey_raw.tx / 1024; - survey->channel_time_busy = priv->survey_raw.cca / 1024 + - survey->channel_time_tx; + survey->channel_time = priv->survey_raw.active; + survey->channel_time_tx = priv->survey_raw.tx; + survey->channel_time_busy = priv->survey_raw.tx + + priv->survey_raw.cca; + do_div(survey->channel_time, 1024); + do_div(survey->channel_time_tx, 1024); + do_div(survey->channel_time_busy, 1024); } tmp = p54_find_and_unlink_skb(priv, hdr->req_id); From 9976f62e7c4e77248b84a35ab0e87e6bc4682ca0 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 26 Aug 2011 11:10:01 +0530 Subject: [PATCH 048/129] ath9k: use appropriate debug mask in the Rx path of the driver it would be better to use ATH_DBG_ANY rather than ATH_DBG_XMIT for printing debug messages Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ad5f9bd2f0b9..800e9ee7e035 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -937,7 +937,7 @@ static int ath9k_process_rate(struct ath_common *common, * No valid hardware bitrate found -- we should not get here * because hardware has already validated this frame as OK. */ - ath_dbg(common, ATH_DBG_XMIT, + ath_dbg(common, ATH_DBG_ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", rx_stats->rs_rate); From 107021c4ce105c9c9d5406dfc4b1fe0f2aa86455 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 26 Aug 2011 11:19:57 +0530 Subject: [PATCH 049/129] ath9k: minor cleanup in ani removed a function declaration, removed a variable, renamed a variable Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 2 +- drivers/net/wireless/ath/ath9k/ani.h | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index bfb6481f01f9..d969a11e3425 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -643,7 +643,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) listenTime = ath_hw_get_listen_time(common); if (listenTime <= 0) { - ah->stats.ast_ani_lneg++; + ah->stats.ast_ani_lneg_or_lzero++; ath9k_ani_restart(ah); return false; } diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index dbab5b9ce494..a547005572e7 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -148,8 +148,7 @@ struct ar5416Stats { u32 ast_ani_ofdmerrs; u32 ast_ani_cckerrs; u32 ast_ani_reset; - u32 ast_ani_lzero; - u32 ast_ani_lneg; + u32 ast_ani_lneg_or_lzero; u32 avgbrssi; struct ath9k_mib_stats ast_mibstats; }; @@ -159,7 +158,5 @@ void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); -int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, - struct ath9k_channel *chan); #endif /* ANI_H */ From b39488a9bd00c520e46682bf75ba484aadc82af7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:33 -0700 Subject: [PATCH 050/129] iwlagn: Rename iwlcore prefix There are number of functions with "iwlcore_" prefix which not feels right, rename those to "iwl_". No functional changes by making the renames. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 1 - 10 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 54d931d614fb..3e1cdd36caef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -179,7 +179,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -200,7 +200,7 @@ static struct iwl_lib_ops iwl2030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 339de88d9ae2..850f9242a165 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -272,7 +272,7 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -294,7 +294,7 @@ static struct iwl_lib_ops iwl6030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index b8347db850e7..c62ddc2a31bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -195,7 +195,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, } static void -iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, +iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *txp, s8 max_txpower_avg) { @@ -235,7 +235,7 @@ iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ ? # x " " : "") -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) +void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) { struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; int idx, entries; @@ -294,6 +294,6 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; - iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); + iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a895a099d086..0fc123799d4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -369,7 +369,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, +static int iwl_verify_inst_sparse(struct iwl_priv *priv, struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; @@ -427,7 +427,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, */ static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) { - if (!iwlcore_verify_inst_sparse(priv, &img->code)) { + if (!iwl_verify_inst_sparse(priv, &img->code)) { IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 33894dde1ae3..7f50d9d6f7cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3459,7 +3459,7 @@ static int iwl_init_drv(struct iwl_priv *priv) goto err; } - ret = iwlcore_init_geos(priv); + ret = iwl_init_geos(priv); if (ret) { IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; @@ -3477,7 +3477,7 @@ err: static void iwl_uninit_drv(struct iwl_priv *priv) { iwl_calib_free_results(priv); - iwlcore_free_geos(priv); + iwl_free_geos(priv); iwl_free_channel_map(priv); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index df2960ae92aa..a2f2f2896112 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -287,7 +287,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) } /* eeprom */ -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); +void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); /* notification wait support */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e269987cd64c..e1c5f5988fef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -51,7 +51,7 @@ const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ -static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, +static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_info, enum ieee80211_band band) { @@ -107,9 +107,9 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, } /** - * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom + * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -int iwlcore_init_geos(struct iwl_priv *priv) +int iwl_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; @@ -146,7 +146,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, + iwl_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_5GHZ); sband = &priv->bands[IEEE80211_BAND_2GHZ]; @@ -156,7 +156,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, + iwl_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_2GHZ); priv->ieee_channels = channels; @@ -228,9 +228,9 @@ int iwlcore_init_geos(struct iwl_priv *priv) } /* - * iwlcore_free_geos - undo allocations in iwlcore_init_geos + * iwl_free_geos - undo allocations in iwl_init_geos */ -void iwlcore_free_geos(struct iwl_priv *priv) +void iwl_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 42bcb469d32c..9c2b3f89870f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -429,8 +429,8 @@ void iwl_clear_isr_stats(struct iwl_priv *priv); /***************************************************** * GEOS ******************************************************/ -int iwlcore_init_geos(struct iwl_priv *priv); -void iwlcore_free_geos(struct iwl_priv *priv); +int iwl_init_geos(struct iwl_priv *priv); +void iwl_free_geos(struct iwl_priv *priv); /*************** DRIVER STATUS FUNCTIONS *****/ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 19d31a5e32e5..c790f7f2ffaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -226,7 +226,7 @@ static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) +static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) { u32 otpgp; int nvm_type; @@ -431,7 +431,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); + priv->nvm_device_type = iwl_get_nvm_type(priv, hw_rev); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e4bf8ac5e64e..e2b5e0ea5d9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -301,7 +301,6 @@ void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); -int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); From f293bd1aeab7c4937c1688bd346c3910f7c73de0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:34 -0700 Subject: [PATCH 051/129] iwlagn: remove out-dated comments Portion of iwl_cfg comments is not correct anymore, remove it. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9c2b3f89870f..2c8b4a513a12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -222,16 +222,7 @@ struct iwl_ht_params { * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. The firmware's API version will be - * stored in @iwl_priv, enabling the driver to make runtime changes based - * on firmware version used. - * - * For example, - * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { - * Driver interacts with Firmware API version >= 2. - * } else { - * Driver interacts with Firmware API version 1. - * } + * it has a supported API version. * * The ideal usage of this infrastructure is to treat a new ucode API * release as a new hardware revision. From a294b96f25f2d436c90ca54d91e13461696cbcd4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:35 -0700 Subject: [PATCH 052/129] iwlagn: use iwl_get_debug_level instead of iwl_debug_level The latter may return incomplete information. For example, if one switched IWL_DL_TX on through sysfs, IWL_DL_TX bit would have been set in priv->debug_level, but since iwl_alloc_traffic_mem looked at iwl_debug_level only, it wouldn't have allocated the tx_traffic buffer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e1c5f5988fef..0d8fd5b0cd7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1398,7 +1398,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) { u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - if (iwl_debug_level & IWL_DL_TX) { + if (iwl_get_debug_level(priv) & IWL_DL_TX) { if (!priv->tx_traffic) { priv->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1406,7 +1406,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) return -ENOMEM; } } - if (iwl_debug_level & IWL_DL_RX) { + if (iwl_get_debug_level(priv) & IWL_DL_RX) { if (!priv->rx_traffic) { priv->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1433,7 +1433,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_debug_level & IWL_DL_TX))) + if (likely(!(iwl_get_debug_level(priv) & IWL_DL_TX))) return; if (!priv->tx_traffic) @@ -1457,7 +1457,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_debug_level & IWL_DL_RX))) + if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) return; if (!priv->rx_traffic) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ec1485b2d3fe..08fc2b2cc516 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -915,7 +915,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt, q->read_ptr, q->write_ptr); } - if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { + if (priv->tx_traffic && (iwl_get_debug_level(priv) & IWL_DL_TX)) { ptr = priv->tx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n", priv->tx_traffic_idx); @@ -938,7 +938,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, "read: %u, write: %u\n", rxq->read, rxq->write); - if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { + if (priv->rx_traffic && (iwl_get_debug_level(priv) & IWL_DL_RX)) { ptr = priv->rx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n", priv->rx_traffic_idx); From 48f20d354e729afcfb29ff41aca7583ebb94613d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:36 -0700 Subject: [PATCH 053/129] iwlagn: introduce iwl-shared.h It will hold declaration of functions and forward declaration of struct that are used by several layers. This will allow modules not to include iwl_priv. iwl_bus and iwl_trans are still visible to all. All the layers share the module parameters, move the struct to iwl-shared.h. Also add all module parameters to iwl_mod_params instead of having them as global static. This includes * debug_level * ant_coupling * bt_ch_announce * wanted_ucode_alternative Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-2000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 32 ++++--- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 - drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- drivers/net/wireless/iwlwifi/iwl-core.h | 24 ----- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 9 +- drivers/net/wireless/iwlwifi/iwl-led.c | 1 + drivers/net/wireless/iwlwifi/iwl-pci.c | 5 +- drivers/net/wireless/iwlwifi/iwl-power.c | 1 + drivers/net/wireless/iwlwifi/iwl-rx.c | 1 + drivers/net/wireless/iwlwifi/iwl-shared.h | 100 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 1 + 18 files changed, 140 insertions(+), 48 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-shared.h diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ccdbed567171..4314c61c40bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -43,6 +43,7 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" +#include "iwl-shared.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 6 diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 3e1cdd36caef..e623870c0fe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -44,6 +44,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" +#include "iwl-shared.h" /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 6 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a9adee5634d8..c79f1f7830b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -46,6 +46,7 @@ #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-trans.h" +#include "iwl-shared.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 850f9242a165..bf84fa697209 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -45,6 +45,7 @@ #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-trans.h" +#include "iwl-shared.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 4edb6cfc5488..dd95f47854d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -40,6 +40,7 @@ #include "iwl-agn.h" #include "iwl-sta.h" #include "iwl-trans.h" +#include "iwl-shared.h" static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) { @@ -609,6 +610,8 @@ struct iwl_mod_params iwlagn_mod_params = { .bt_coex_active = true, .no_sleep_autoadjust = true, .power_level = IWL_POWER_INDEX_1, + .bt_ch_announce = 1, + .wanted_ucode_alternative = 1, /* the rest are 0 by default */ }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index d562e9359d97..2829bf843d0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -31,6 +31,7 @@ #include "iwl-agn-calib.h" #include "iwl-helpers.h" #include "iwl-trans.h" +#include "iwl-shared.h" static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7f50d9d6f7cf..cb8a9f9a22df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -51,6 +51,7 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" +#include "iwl-shared.h" #include "iwl-bus.h" #include "iwl-trans.h" @@ -79,9 +80,6 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); -static int iwlagn_ant_coupling; -static bool iwlagn_bt_ch_announce = 1; - void iwl_update_chain_flags(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; @@ -818,8 +816,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, return 0; } -static int iwlagn_wanted_ucode_alternative = 1; - static int iwlagn_load_firmware(struct iwl_priv *priv, const struct firmware *ucode_raw, struct iwlagn_firmware_pieces *pieces, @@ -829,7 +825,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, struct iwl_ucode_tlv *tlv; size_t len = ucode_raw->size; const u8 *data; - int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; + int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; + int tmp; u64 alternatives; u32 tlv_len; enum iwl_ucode_tlv_type tlv_type; @@ -1619,7 +1616,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, } /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_bt_ch_announce; + priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; #ifdef CONFIG_IWLWIFI_DEBUG if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) @@ -3618,11 +3615,12 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) /* is antenna coupling more than 35dB ? */ priv->bt_ant_couple_ok = - (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? - true : false; + (iwlagn_mod_params.ant_coupling > + IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? + true : false; /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_bt_ch_announce; + priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", (priv->bt_ch_announce) ? "On" : "Off"); @@ -3863,7 +3861,8 @@ module_exit(iwl_exit); module_init(iwl_init); #ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); +module_param_named(debug, iwlagn_mod_params.debug_level, uint, + S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif @@ -3879,16 +3878,19 @@ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); -module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, - S_IRUGO); +module_param_named(ucode_alternative, + iwlagn_mod_params.wanted_ucode_alternative, + int, S_IRUGO); MODULE_PARM_DESC(ucode_alternative, "specify ucode alternative to use from ucode file"); -module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); +module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling, + int, S_IRUGO); MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); +module_param_named(bt_ch_inhibition, iwlagn_mod_params.bt_ch_announce, + bool, S_IRUGO); MODULE_PARM_DESC(bt_ch_inhibition, "Disable BT channel inhibition (default: enable)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a2f2f2896112..ea2a5fe8da8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -108,8 +108,6 @@ extern struct iwl_cfg iwl105_bgn_cfg; extern struct iwl_cfg iwl135_bg_cfg; extern struct iwl_cfg iwl135_bgn_cfg; -extern struct iwl_mod_params iwlagn_mod_params; - extern struct ieee80211_ops iwlagn_hw_ops; int iwl_reset_ict(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0d8fd5b0cd7c..6c11f0dce0d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -42,11 +42,10 @@ #include "iwl-sta.h" #include "iwl-agn.h" #include "iwl-helpers.h" +#include "iwl-shared.h" #include "iwl-agn.h" #include "iwl-trans.h" -u32 iwl_debug_level; - const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2c8b4a513a12..fe46d0f71362 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -101,23 +101,6 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; -struct iwl_mod_params { - int sw_crypto; /* def: 0 = using hardware encryption */ - int num_of_queues; /* def: HW dependent */ - int disable_11n; /* def: 0 = 11n capabilities enabled */ - int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ - int antenna; /* def: 0 = both antennas (use diversity) */ - int restart_fw; /* def: 1 = restart firmware */ - bool plcp_check; /* def: true = enable plcp health check */ - bool ack_check; /* def: false = disable ack health check */ - bool wd_disable; /* def: false = enable stuck queue check */ - bool bt_coex_active; /* def: true = enable bt coex */ - int led_mode; /* def: 0 = system default */ - bool no_sleep_autoadjust; /* def: true = disable autoadjust */ - bool power_save; /* def: false = disable power save */ - int power_level; /* def: 1 = power level */ -}; - /* * @max_ll_items: max number of OTP blocks * @shadow_ram_support: shadow support for OTP memory @@ -389,13 +372,6 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval); -#ifdef CONFIG_PM -int iwl_suspend(struct iwl_priv *priv); -int iwl_resume(struct iwl_priv *priv); -#endif /* !CONFIG_PM */ - -int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); -void __devexit iwl_remove(struct iwl_priv * priv); /***************************************************** * Error Handling Debugging diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f9a407e40aff..0869eaa1308e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -30,7 +30,6 @@ #define __iwl_debug_h__ struct iwl_priv; -extern u32 iwl_debug_level; #define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) #define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index dd34c7c502fa..d0e65c82cce3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -50,6 +50,7 @@ #include "iwl-agn-tt.h" #include "iwl-bus.h" #include "iwl-trans.h" +#include "iwl-shared.h" #define DRV_NAME "iwlagn" @@ -1513,7 +1514,7 @@ struct iwl_priv { #ifdef CONFIG_IWLWIFI_DEBUG /* debugging info */ u32 debug_level; /* per device debugging will override global - iwl_debug_level if set */ + iwlagn_mod_params.debug_level if set */ #endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS /* debugfs */ @@ -1562,6 +1563,8 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) clear_bit(txq_id, &priv->txq_ctx_active_msk); } +extern struct iwl_mod_params iwlagn_mod_params; + #ifdef CONFIG_IWLWIFI_DEBUG /* * iwl_get_debug_level: Return active debug level for device @@ -1575,12 +1578,12 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv) if (priv->debug_level) return priv->debug_level; else - return iwl_debug_level; + return iwlagn_mod_params.debug_level; } #else static inline u32 iwl_get_debug_level(struct iwl_priv *priv) { - return iwl_debug_level; + return iwlagn_mod_params.debug_level; } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 1a5252d8ca73..d8049febe047 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -40,6 +40,7 @@ #include "iwl-agn.h" #include "iwl-io.h" #include "iwl-trans.h" +#include "iwl-shared.h" /* Throughput OFF time(ms) ON time (ms) * >300 25 25 diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 69d4ec467dca..a2441dd2fd50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -64,8 +64,11 @@ #include #include "iwl-bus.h" +#include "iwl-shared.h" #include "iwl-agn.h" -#include "iwl-core.h" + +/* TODO: iwl_set_bit and friends should be implemented in bus layer + * this would allow us not to include iwl-io.h here */ #include "iwl-io.h" /* PCI registers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index cd64df05f9ed..b60e692a4765 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -43,6 +43,7 @@ #include "iwl-debug.h" #include "iwl-power.h" #include "iwl-trans.h" +#include "iwl-shared.h" /* * Setting power level allows the card to go to sleep when not busy. diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8e314003b63a..8b3a08958cc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -40,6 +40,7 @@ #include "iwl-helpers.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" +#include "iwl-shared.h" /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h new file mode 100644 index 000000000000..5d48d059fcd8 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_shared_h__ +#define __iwl_shared_h__ + +struct iwl_cfg; +struct iwl_priv; + +extern struct iwl_mod_params iwlagn_mod_params; + +struct iwl_mod_params { + int sw_crypto; /* def: 0 = using hardware encryption */ + int num_of_queues; /* def: HW dependent */ + int disable_11n; /* def: 0 = 11n capabilities enabled */ + int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ + int antenna; /* def: 0 = both antennas (use diversity) */ + int restart_fw; /* def: 1 = restart firmware */ + bool plcp_check; /* def: true = enable plcp health check */ + bool ack_check; /* def: false = disable ack health check */ + bool wd_disable; /* def: false = enable stuck queue check */ + bool bt_coex_active; /* def: true = enable bt coex */ + int led_mode; /* def: 0 = system default */ + bool no_sleep_autoadjust; /* def: true = disable autoadjust */ + bool power_save; /* def: false = disable power save */ + int power_level; /* def: 1 = power level */ + u32 debug_level; /* levels are IWL_DL_* */ + int ant_coupling; + bool bt_ch_announce; + int wanted_ucode_alternative; +}; + +#ifdef CONFIG_PM +int iwl_suspend(struct iwl_priv *priv); +int iwl_resume(struct iwl_priv *priv); +#endif /* !CONFIG_PM */ + +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); +void __devexit iwl_remove(struct iwl_priv * priv); + +#endif /* #__iwl_shared_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 3001bfb46e25..e4a70fed8cf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -68,6 +68,7 @@ /*TODO remove uneeded includes when the transport layer tx_free will be here */ #include "iwl-agn.h" #include "iwl-core.h" +#include "iwl-shared.h" static int iwl_trans_rx_alloc(struct iwl_priv *priv) { From cac988a682d45d07276fef1cc1e035ef86d39849 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:37 -0700 Subject: [PATCH 054/129] iwlagn: introduce struct iwl-shared - known by all layers This struct will hold pointers to all the layers, so that every layer will find the pointers it needs when calling another layer. Note that the drv_data set to struct device is now a pointer to struct iwl_shared. This solves of bug that I introduced in iwlagn: simplify the bus architecture Bug description: sysfs gets the the driver data from struct device. Till the aforementioned patch, dev_get_drvdata would return iwl_priv. After the patch, dev_get_drvdata return iwl_bus which is buggy since the sysfs handlers rely on this value, and sysfs handlers need iwl_priv. Now, dev_get_drvdata return iwl-shared. Since we have pointers to all the layers in iwl_shared, every layer will be able to get the pointer it needs: bus layer will gets iwl_bus from the PCI suspend callbacks, and the sysfs handlers will get the iwl_priv they need. In order to keep good encapsulation, we need to avoid to dereference iwl_priv from a different layer. This is why instead of including iwl-dev.h from iwl-shared.h, I added a forward declaration to iwl_priv. Moreover we keep type safety while providing encapsulation. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++++++++----- drivers/net/wireless/iwlwifi/iwl-bus.h | 12 ++++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl-pci.c | 26 +++++++++++------------ drivers/net/wireless/iwlwifi/iwl-shared.h | 16 ++++++++++++++ 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cb8a9f9a22df..39e7bdbc9ff9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -473,14 +473,15 @@ static void iwl_bg_tx_flush(struct work_struct *work) static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); + struct iwl_shared *shrd = dev_get_drvdata(d); + return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd->priv)); } static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_shared *shrd = dev_get_drvdata(d); + struct iwl_priv *priv = shrd->priv; unsigned long val; int ret; @@ -506,7 +507,8 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = dev_get_drvdata(d); + struct iwl_shared *shrd = dev_get_drvdata(d); + struct iwl_priv *priv = shrd->priv; if (!iwl_is_alive(priv)) return -EAGAIN; @@ -3603,7 +3605,10 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) priv = hw->priv; priv->bus = bus; - bus_set_drv_data(priv->bus, priv); + priv->shrd = &priv->_shrd; + priv->shrd->bus = bus; + priv->shrd->priv = priv; + bus_set_drv_data(priv->bus, priv->shrd); /* At this point both hw and priv are allocated. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index f3ee1c0c004c..a69800485c5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -63,13 +63,14 @@ #ifndef __iwl_pci_h__ #define __iwl_pci_h__ +struct iwl_shared; struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations * @get_pm_support: must returns true if the bus can go to sleep * @apm_config: will be called during the config of the APM configuration - * @set_drv_data: set the drv_data pointer to the bus layer + * @set_drv_data: set the shared data pointer to the bus layer * @get_hw_id: prints the hw_id in the provided buffer * @write8: write a byte to register at offset ofs * @write32: write a dword to register at offset ofs @@ -78,7 +79,7 @@ struct iwl_bus; struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus); - void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); + void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd); void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); @@ -87,9 +88,9 @@ struct iwl_bus_ops { struct iwl_bus { /* Common data to all buses */ - void *drv_data; /* driver's context */ struct device *dev; struct iwl_bus_ops *ops; + struct iwl_shared *shrd; unsigned int irq; @@ -108,9 +109,10 @@ static inline void bus_apm_config(struct iwl_bus *bus) bus->ops->apm_config(bus); } -static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) +static inline void bus_set_drv_data(struct iwl_bus *bus, + struct iwl_shared *shrd) { - bus->ops->set_drv_data(bus, drv_data); + bus->ops->set_drv_data(bus, shrd); } static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d0e65c82cce3..85295b0201bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1210,6 +1210,10 @@ struct iwl_testmode_trace { struct iwl_priv { + /*data shared among all the driver's layers */ + struct iwl_shared _shrd; + struct iwl_shared *shrd; + /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index a2441dd2fd50..3b7efd7fee3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -123,21 +123,21 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(bus->drv_data, CSR_GIO_REG, + iwl_set_bit(priv(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(bus->drv_data, CSR_GIO_REG, + iwl_clear_bit(priv(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } } -static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) +static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd) { - bus->drv_data = drv_data; - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); + bus->shrd = shrd; + pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd); } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -496,12 +496,12 @@ static void iwl_pci_down(struct iwl_bus *bus) static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_priv *priv = pci_get_drvdata(pdev); - void *bus_specific = priv->bus->bus_specific; + struct iwl_shared *shrd = pci_get_drvdata(pdev); + struct iwl_bus *bus = shrd->bus; - iwl_remove(priv); + iwl_remove(shrd->priv); - iwl_pci_down(bus_specific); + iwl_pci_down(bus); } #ifdef CONFIG_PM @@ -509,20 +509,20 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_shared *shrd = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_suspend(priv); + return iwl_suspend(shrd->priv); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_shared *shrd = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if @@ -535,7 +535,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(priv); + return iwl_resume(shrd->priv); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 5d48d059fcd8..32744a72a6ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -64,6 +64,7 @@ #define __iwl_shared_h__ struct iwl_cfg; +struct iwl_bus; struct iwl_priv; extern struct iwl_mod_params iwlagn_mod_params; @@ -89,6 +90,21 @@ struct iwl_mod_params { int wanted_ucode_alternative; }; +/** + * struct iwl_shared - shared fields for all the layers of the driver + * + * @bus: pointer to the bus layer data + * @priv: pointer to the upper layer data + */ +struct iwl_shared { + struct iwl_bus *bus; + struct iwl_priv *priv; +}; + +/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ +#define priv(_m) ((_m)->shrd->priv) +#define bus(_m) ((_m)->shrd->bus) + #ifdef CONFIG_PM int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); From 8f470ce31de1a9dfe6b53e0967eaa7e72b741714 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:38 -0700 Subject: [PATCH 055/129] iwlagn: debug_level moves to struct iwl_shared This will allow all the modules to look at it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++---- drivers/net/wireless/iwlwifi/iwl-core.c | 10 +++---- drivers/net/wireless/iwlwifi/iwl-debug.h | 6 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 29 ------------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 28 ++++++++++++++++++ .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 6 ++-- 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 39e7bdbc9ff9..637c5427e3d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -474,7 +474,7 @@ static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_shared *shrd = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd->priv)); + return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd)); } static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, @@ -489,9 +489,9 @@ static ssize_t store_debug_level(struct device *d, if (ret) IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); else { - priv->debug_level = val; + shrd->dbg_level_dev = val; if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, + IWL_ERR(shrd->priv, "Not enough memory to generate traffic log\n"); } return strnlen(buf, count); @@ -1621,7 +1621,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; #ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) + if (!(iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else @@ -1641,7 +1641,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, if (!*buf) return -ENOMEM; } - if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { + if ((iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) || full_log) { /* * if uCode has wrapped back to top of log, * start at the oldest entry, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6c11f0dce0d1..2b3d0526e965 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -931,7 +931,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) iwl_dump_fh(priv, NULL, false); iwl_dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) + if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) iwl_print_rx_config_cmd(priv, &priv->contexts[IWL_RXON_CTX_BSS]); #endif @@ -1397,7 +1397,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) { u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - if (iwl_get_debug_level(priv) & IWL_DL_TX) { + if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) { if (!priv->tx_traffic) { priv->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1405,7 +1405,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) return -ENOMEM; } } - if (iwl_get_debug_level(priv) & IWL_DL_RX) { + if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) { if (!priv->rx_traffic) { priv->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1432,7 +1432,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv) & IWL_DL_TX))) + if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX))) return; if (!priv->tx_traffic) @@ -1456,7 +1456,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) + if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX))) return; if (!priv->rx_traffic) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 0869eaa1308e..225ae720c7d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -45,7 +45,7 @@ do { \ #ifdef CONFIG_IWLWIFI_DEBUG #define IWL_DEBUG(__priv, level, fmt, args...) \ do { \ - if (iwl_get_debug_level(__priv) & (level)) \ + if (iwl_get_debug_level(__priv->shrd) & (level)) \ dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ @@ -53,7 +53,7 @@ do { \ #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ do { \ - if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \ + if ((iwl_get_debug_level(__priv->shrd) & (level)) && net_ratelimit())\ dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ @@ -61,7 +61,7 @@ do { \ #define iwl_print_hex_dump(priv, level, p, len) \ do { \ - if (iwl_get_debug_level(priv) & level) \ + if (iwl_get_debug_level(priv->shrd) & level) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 08fc2b2cc516..c798c6805b66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -915,7 +915,8 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt, q->read_ptr, q->write_ptr); } - if (priv->tx_traffic && (iwl_get_debug_level(priv) & IWL_DL_TX)) { + if (priv->tx_traffic && + (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { ptr = priv->tx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n", priv->tx_traffic_idx); @@ -938,7 +939,8 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, "read: %u, write: %u\n", rxq->read, rxq->write); - if (priv->rx_traffic && (iwl_get_debug_level(priv) & IWL_DL_RX)) { + if (priv->rx_traffic && + (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { ptr = priv->rx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n", priv->rx_traffic_idx); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 85295b0201bf..e01caf7a1f12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1514,12 +1514,6 @@ struct iwl_priv { s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ s8 tx_power_next; - -#ifdef CONFIG_IWLWIFI_DEBUG - /* debugging info */ - u32 debug_level; /* per device debugging will override global - iwlagn_mod_params.debug_level if set */ -#endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS /* debugfs */ u16 tx_traffic_idx; @@ -1569,29 +1563,6 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) extern struct iwl_mod_params iwlagn_mod_params; -#ifdef CONFIG_IWLWIFI_DEBUG -/* - * iwl_get_debug_level: Return active debug level for device - * - * Using sysfs it is possible to set per device debug level. This debug - * level will be used if set, otherwise the global debug level which can be - * set via module parameter is used. - */ -static inline u32 iwl_get_debug_level(struct iwl_priv *priv) -{ - if (priv->debug_level) - return priv->debug_level; - else - return iwlagn_mod_params.debug_level; -} -#else -static inline u32 iwl_get_debug_level(struct iwl_priv *priv) -{ - return iwlagn_mod_params.debug_level; -} -#endif - - static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, int txq_id, int idx) { diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 32744a72a6ac..a7c0315472e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -93,10 +93,16 @@ struct iwl_mod_params { /** * struct iwl_shared - shared fields for all the layers of the driver * + * @dbg_level_dev: dbg level set per device. Prevails on + * iwlagn_mod_params.debug_level if set (!= 0) * @bus: pointer to the bus layer data * @priv: pointer to the upper layer data */ struct iwl_shared { +#ifdef CONFIG_IWLWIFI_DEBUG + u32 dbg_level_dev; +#endif /* CONFIG_IWLWIFI_DEBUG */ + struct iwl_bus *bus; struct iwl_priv *priv; }; @@ -105,6 +111,28 @@ struct iwl_shared { #define priv(_m) ((_m)->shrd->priv) #define bus(_m) ((_m)->shrd->bus) +#ifdef CONFIG_IWLWIFI_DEBUG +/* + * iwl_get_debug_level: Return active debug level for device + * + * Using sysfs it is possible to set per device debug level. This debug + * level will be used if set, otherwise the global debug level which can be + * set via module parameter is used. + */ +static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) +{ + if (shrd->dbg_level_dev) + return shrd->dbg_level_dev; + else + return iwlagn_mod_params.debug_level; +} +#else +static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) +{ + return iwlagn_mod_params.debug_level; +} +#endif + #ifdef CONFIG_PM int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 474860290404..846db8fdbf6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -515,7 +515,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) inta = priv->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { + if (iwl_get_debug_level(priv->shrd) & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", @@ -544,7 +544,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " @@ -845,7 +845,7 @@ static irqreturn_t iwl_isr(int irq, void *data) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); From d618912417fbce4f6514fe1cbef7df2e73bdb6c2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:39 -0700 Subject: [PATCH 056/129] iwlagn: hw_params moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 36 +++++----- drivers/net/wireless/iwlwifi/iwl-2000.c | 38 +++++------ drivers/net/wireless/iwlwifi/iwl-5000.c | 62 ++++++++--------- drivers/net/wireless/iwlwifi/iwl-6000.c | 38 +++++------ drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 21 +++--- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 66 ++++++++++--------- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 12 ++-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 48 +++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 30 ++++----- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 54 +-------------- drivers/net/wireless/iwlwifi/iwl-prph.h | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 51 ++++++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 11 ++-- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 20 +++--- drivers/net/wireless/iwlwifi/iwl-trans.c | 24 +++---- 19 files changed, 278 insertions(+), 262 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4314c61c40bb..bd0ce3993b52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -77,8 +77,8 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; - priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 1000 series */ @@ -128,43 +128,43 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.scd_bc_tbls_size = + hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; + hw_params(priv).scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWLAGN_STATION_COUNT; + hw_params(priv).tfd_size = sizeof(struct iwl_tfd); + hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; + hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); + hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - priv->hw_params.rx_chains_num = 1; + hw_params(priv).rx_chains_num = 1; else - priv->hw_params.rx_chains_num = + hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; + hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; iwl1000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - priv->hw_params.sens = &iwl1000_sensitivity; - priv->hw_params.calib_init_cfg = + hw_params(priv).sens = &iwl1000_sensitivity; + hw_params(priv).calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); - priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e623870c0fe7..1a36edf05ee4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -79,8 +79,8 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; - priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; + hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 2000 series */ @@ -125,44 +125,44 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.scd_bc_tbls_size = + hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; + hw_params(priv).scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWLAGN_STATION_COUNT; + hw_params(priv).tfd_size = sizeof(struct iwl_tfd); + hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; + hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); + hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - priv->hw_params.rx_chains_num = 1; + hw_params(priv).rx_chains_num = 1; else - priv->hw_params.rx_chains_num = + hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; + hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; iwl2000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - priv->hw_params.sens = &iwl2000_sensitivity; - priv->hw_params.calib_init_cfg = + hw_params(priv).sens = &iwl2000_sensitivity; + hw_params(priv).calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c79f1f7830b0..e073422edab4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -140,13 +140,13 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv) s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - iwl_temp_calib_to_offset(priv); - priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; + hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; } static void iwl5000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; } static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) @@ -156,38 +156,38 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.scd_bc_tbls_size = + hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; + hw_params(priv).scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWLAGN_STATION_COUNT; + hw_params(priv).tfd_size = sizeof(struct iwl_tfd); + hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; + hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; + hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; iwl5000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - priv->hw_params.sens = &iwl5000_sensitivity; - priv->hw_params.calib_init_cfg = + hw_params(priv).sens = &iwl5000_sensitivity; + hw_params(priv).calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); - priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -199,38 +199,38 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.scd_bc_tbls_size = + hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; + hw_params(priv).scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWLAGN_STATION_COUNT; + hw_params(priv).tfd_size = sizeof(struct iwl_tfd); + hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; + hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; + hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; iwl5150_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - priv->hw_params.sens = &iwl5150_sensitivity; - priv->hw_params.calib_init_cfg = + hw_params(priv).sens = &iwl5150_sensitivity; + hw_params(priv).calib_init_cfg = BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); - priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index bf84fa697209..e7be968b1784 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -75,8 +75,8 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; - priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; + hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } static void iwl6050_additional_nic_config(struct iwl_priv *priv) @@ -145,45 +145,45 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.scd_bc_tbls_size = + hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; + hw_params(priv).scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWLAGN_STATION_COUNT; + hw_params(priv).tfd_size = sizeof(struct iwl_tfd); + hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; + hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - priv->hw_params.rx_chains_num = 1; + hw_params(priv).rx_chains_num = 1; else - priv->hw_params.rx_chains_num = + hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; + hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; iwl6000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - priv->hw_params.sens = &iwl6000_sensitivity; - priv->hw_params.calib_init_cfg = + hw_params(priv).sens = &iwl6000_sensitivity; + hw_params(priv).calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 1789e3af8101..f0e38a14053a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -93,7 +93,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) }; for (i = 0; i < IWL_CALIB_MAX; i++) { - if ((BIT(i) & priv->hw_params.calib_init_cfg) && + if ((BIT(i) & hw_params(priv).calib_init_cfg) && priv->calib_results[i].buf) { hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; @@ -174,7 +174,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; + const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; data = &(priv->sensitivity_data); @@ -357,7 +357,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; + const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; data = &(priv->sensitivity_data); @@ -581,7 +581,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) int ret = 0; int i; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; + const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; if (priv->disable_sens_cal) return; @@ -821,21 +821,21 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * To be safe, simply mask out any chains that we know * are not on the device. */ - active_chains &= priv->hw_params.valid_rx_ant; + active_chains &= hw_params(priv).valid_rx_ant; num_tx_chains = 0; for (i = 0; i < NUM_RX_CHAINS; i++) { /* loops on all the bits of * priv->hw_setting.valid_tx_ant */ u8 ant_msk = (1 << i); - if (!(priv->hw_params.valid_tx_ant & ant_msk)) + if (!(hw_params(priv).valid_tx_ant & ant_msk)) continue; num_tx_chains++; if (data->disconn_array[i] == 0) /* there is a Tx antenna connected */ break; - if (num_tx_chains == priv->hw_params.tx_chains_num && + if (num_tx_chains == hw_params(priv).tx_chains_num && data->disconn_array[i]) { /* * If all chains are disconnected @@ -852,12 +852,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, } } - if (active_chains != priv->hw_params.valid_rx_ant && + if (active_chains != hw_params(priv).valid_rx_ant && active_chains != priv->chain_noise_data.active_chains) IWL_DEBUG_CALIB(priv, "Detected that not all antennas are connected! " "Connected: %#x, valid: %#x.\n", - active_chains, priv->hw_params.valid_rx_ant); + active_chains, + hw_params(priv).valid_rx_ant); /* Save for use within RXON, TX, SCAN commands, etc. */ data->active_chains = active_chains; @@ -1046,7 +1047,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) priv->cfg->bt_params->advanced_bt_coexist) { /* Disable disconnected antenna algorithm for advanced bt coex, assuming valid antennas are connected */ - data->active_chains = priv->hw_params.valid_rx_ant; + data->active_chains = hw_params(priv).valid_rx_ant; for (i = 0; i < NUM_RX_CHAINS; i++) if (!(data->active_chains & (1<disconn_array[i] = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index dd95f47854d4..048ccbae82f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -770,12 +770,12 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u16 rx_chain = 0; enum ieee80211_band band; u8 n_probes = 0; - u8 rx_ant = priv->hw_params.valid_rx_ant; + u8 rx_ant = hw_params(priv).valid_rx_ant; u8 rate; bool is_active = false; int chan_mod; u8 active_chains; - u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; + u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; int ret; lockdep_assert_held(&priv->mutex); @@ -965,7 +965,8 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) } /* MIMO is not used here, but value is required */ - rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; + rx_chain |= + hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; @@ -1101,7 +1102,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) int ret = 0; /* waiting for all the tx frames complete might take a while */ - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { if (cnt == priv->cmd_queue) continue; txq = &priv->txq[cnt]; @@ -1786,7 +1787,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (priv->chain_noise_data.active_chains) active_chains = priv->chain_noise_data.active_chains; else - active_chains = priv->hw_params.valid_rx_ant; + active_chains = hw_params(priv).valid_rx_ant; if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 1fa438e20f0a..3ca6e553fcd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -819,7 +819,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, if (num_of_ant(tbl->ant_type) > 1) tbl->ant_type = - first_antenna(priv->hw_params.valid_tx_ant); + first_antenna(hw_params(priv).valid_tx_ant); tbl->is_ht40 = 0; tbl->is_SGI = 0; @@ -1293,7 +1293,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (priv->hw_params.tx_chains_num < 2) + if (hw_params(priv).tx_chains_num < 2) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); @@ -1349,7 +1349,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (priv->hw_params.tx_chains_num < 3) + if (hw_params(priv).tx_chains_num < 3) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); @@ -1448,8 +1448,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 valid_tx_ant = hw_params(priv).valid_tx_ant; + u8 tx_chains_num = hw_params(priv).tx_chains_num; int ret = 0; u8 update_search_tbl_counter = 0; @@ -1459,14 +1459,16 @@ static int rs_move_legacy_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && tbl->action != IWL_LEGACY_SWITCH_SISO) tbl->action = IWL_LEGACY_SWITCH_SISO; @@ -1489,7 +1491,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_SISO; - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); } start_action = tbl->action; @@ -1623,8 +1626,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 valid_tx_ant = hw_params(priv).valid_tx_ant; + u8 tx_chains_num = hw_params(priv).tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1634,14 +1637,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; @@ -1658,7 +1663,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, /* configure as 1x1 if bt full concurrency */ if (priv->bt_full_concurrent) { - valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); + valid_tx_ant = + first_antenna(hw_params(priv).valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; } @@ -1794,8 +1800,8 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 valid_tx_ant = hw_params(priv).valid_tx_ant; + u8 tx_chains_num = hw_params(priv).tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1964,8 +1970,8 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 valid_tx_ant = hw_params(priv).valid_tx_ant; + u8 tx_chains_num = hw_params(priv).tx_chains_num; int ret; u8 update_search_tbl_counter = 0; @@ -2703,7 +2709,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = lq_sta->last_txrate_idx; - valid_tx_ant = priv->hw_params.valid_tx_ant; + valid_tx_ant = hw_params(priv).valid_tx_ant; if (!lq_sta->search_better_tbl) active_tbl = lq_sta->active_tbl; @@ -2886,15 +2892,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i /* These values will be overridden later */ lq_sta->lq.general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); + first_antenna(hw_params(priv).valid_tx_ant); lq_sta->lq.general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant & - ~first_antenna(priv->hw_params.valid_tx_ant); + hw_params(priv).valid_tx_ant & + ~first_antenna(hw_params(priv).valid_tx_ant); if (!lq_sta->lq.general_params.dual_stream_ant_msk) { lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { lq_sta->lq.general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant; + hw_params(priv).valid_tx_ant; } /* as default allow aggregation for all tids */ @@ -2940,7 +2946,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(priv->hw_params.valid_tx_ant); + first_antenna(hw_params(priv).valid_tx_ant); } /* How many times should we repeat the initial rate? */ @@ -2972,7 +2978,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv->bt_full_concurrent) valid_tx_ant = ANT_A; else - valid_tx_ant = priv->hw_params.valid_tx_ant; + valid_tx_ant = hw_params(priv).valid_tx_ant; } /* Fill rest of rate table */ @@ -3006,7 +3012,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(priv->hw_params.valid_tx_ant); + first_antenna(hw_params(priv).valid_tx_ant); } /* Indicate to uCode which entries might be MIMO. @@ -3097,7 +3103,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, u8 ant_sel_tx; priv = lq_sta->drv; - valid_tx_ant = priv->hw_params.valid_tx_ant; + valid_tx_ant = hw_params(priv).valid_tx_ant; if (lq_sta->dbg_fixed_rate) { ant_sel_tx = ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) @@ -3168,9 +3174,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, desc += sprintf(buff+desc, "fixed rate 0x%X\n", lq_sta->dbg_fixed_rate); desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", - (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", - (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", - (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); + (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "", + (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "", + (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : ""); desc += sprintf(buff+desc, "lq type %s\n", (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); if (is_Ht(tbl->lq_type)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 37e624095e40..f894bfb43da4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -63,23 +63,23 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) rate_flags |= RATE_MCS_CCK_MSK; - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << + rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) << RATE_MCS_ANT_POS; rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) link_cmd->rs_table[i].rate_n_flags = rate_n_flags; link_cmd->general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); + first_antenna(hw_params(priv).valid_tx_ant); link_cmd->general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant & - ~first_antenna(priv->hw_params.valid_tx_ant); + hw_params(priv).valid_tx_ant & + ~first_antenna(hw_params(priv).valid_tx_ant); if (!link_cmd->general_params.dual_stream_ant_msk) { link_cmd->general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { link_cmd->general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant; + hw_params(priv).valid_tx_ant; } link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 9bc26da62768..3e2a9040de1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -260,10 +260,10 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, priv->bt_full_concurrent) { /* operated as 1x1 in full concurrency mode */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - first_antenna(priv->hw_params.valid_tx_ant)); + first_antenna(hw_params(priv).valid_tx_ant)); } else priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - priv->hw_params.valid_tx_ant); + hw_params(priv).valid_tx_ant); rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* Set the rate in the TX cmd */ @@ -492,7 +492,7 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) { int txq_id; - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) return txq_id; return -1; @@ -864,7 +864,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= priv->hw_params.max_txq_num) { + if (scd_flow >= hw_params(priv).max_txq_num) { IWL_ERR(priv, "BUG_ON scd_flow is bigger than number of queues\n"); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 637c5427e3d0..e8177fb7ae2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -180,7 +180,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate = info->control.rates[0].idx; priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - priv->hw_params.valid_tx_ant); + hw_params(priv).valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* In mac80211, rates for 5 GHz start at 0 */ @@ -1149,25 +1149,25 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_data_size); /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > priv->hw_params.max_inst_size) { + if (pieces.inst_size > hw_params(priv).max_inst_size) { IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", pieces.inst_size); goto try_again; } - if (pieces.data_size > priv->hw_params.max_data_size) { + if (pieces.data_size > hw_params(priv).max_data_size) { IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", pieces.data_size); goto try_again; } - if (pieces.init_size > priv->hw_params.max_inst_size) { + if (pieces.init_size > hw_params(priv).max_inst_size) { IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", pieces.init_size); goto try_again; } - if (pieces.init_data_size > priv->hw_params.max_data_size) { + if (pieces.init_data_size > hw_params(priv).max_data_size) { IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", pieces.init_data_size); goto try_again; @@ -1681,9 +1681,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) if (priv->cfg->base_params->support_ct_kill_exit) { adv_cmd.critical_temperature_enter = - cpu_to_le32(priv->hw_params.ct_kill_threshold); + cpu_to_le32(hw_params(priv).ct_kill_threshold); adv_cmd.critical_temperature_exit = - cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); + cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, @@ -1692,14 +1692,13 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature enter is %d," - "exit is %d\n", - priv->hw_params.ct_kill_threshold, - priv->hw_params.ct_kill_exit_threshold); + "succeeded, critical temperature enter is %d," + "exit is %d\n", + hw_params(priv).ct_kill_threshold, + hw_params(priv).ct_kill_exit_threshold); } else { cmd.critical_temperature_R = - cpu_to_le32(priv->hw_params.ct_kill_threshold); + cpu_to_le32(hw_params(priv).ct_kill_threshold); ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, @@ -1708,9 +1707,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature is %d\n", - priv->hw_params.ct_kill_threshold); + "succeeded, " + "critical temperature is %d\n", + hw_params(priv).ct_kill_threshold); } } @@ -1808,8 +1807,9 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); } - if (priv->hw_params.calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); + if (hw_params(priv).calib_rt_cfg) + iwlagn_send_calib_cfg_rt(priv, + hw_params(priv).calib_rt_cfg); ieee80211_wake_queues(priv->hw); @@ -3548,14 +3548,16 @@ static u32 iwl_hw_detect(struct iwl_priv *priv) static int iwl_set_hw_params(struct iwl_priv *priv) { - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; + hw_params(priv).max_rxq_size = RX_QUEUE_SIZE; + hw_params(priv).max_rxq_log = RX_QUEUE_SIZE_LOG; if (iwlagn_mod_params.amsdu_size_8K) - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); + hw_params(priv).rx_page_order = + get_order(IWL_RX_BUF_SIZE_8K); else - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); + hw_params(priv).rx_page_order = + get_order(IWL_RX_BUF_SIZE_4K); - priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; + hw_params(priv).max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2b3d0526e965..2aeafa18579f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -55,8 +55,8 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, enum ieee80211_band band) { u16 max_bit_rate = 0; - u8 rx_chains_num = priv->hw_params.rx_chains_num; - u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 rx_chains_num = hw_params(priv).rx_chains_num; + u8 tx_chains_num = hw_params(priv).tx_chains_num; ht_info->cap = 0; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); @@ -68,7 +68,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; max_bit_rate = MAX_BIT_RATE_20_MHZ; - if (priv->hw_params.ht40_channel & BIT(band)) { + if (hw_params(priv).ht40_channel & BIT(band)) { ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ht_info->cap |= IEEE80211_HT_CAP_SGI_40; ht_info->mcs.rx_mask[4] = 0x01; @@ -359,7 +359,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else { beacon_int = iwl_adjust_beacon_interval(beacon_int, - priv->hw_params.max_beacon_itrvl * TIME_UNIT); + hw_params(priv).max_beacon_itrvl * TIME_UNIT); ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } @@ -1823,7 +1823,7 @@ void iwl_bg_watchdog(unsigned long data) /* monitor and check for other stuck queues */ if (iwl_is_any_associated(priv)) { - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { /* skip as we already checked the command queue */ if (cnt == priv->cmd_queue) continue; @@ -1864,12 +1864,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) quot = (usec / interval) & (iwl_beacon_time_mask_high(priv, - priv->hw_params.beacon_time_tsf_bits) >> - priv->hw_params.beacon_time_tsf_bits); + hw_params(priv).beacon_time_tsf_bits) >> + hw_params(priv).beacon_time_tsf_bits); rem = (usec % interval) & iwl_beacon_time_mask_low(priv, - priv->hw_params.beacon_time_tsf_bits); + hw_params(priv).beacon_time_tsf_bits); - return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; + return (quot << hw_params(priv).beacon_time_tsf_bits) + rem; } /* base is usually what we get from ucode with each received frame, @@ -1879,22 +1879,22 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval) { u32 base_low = base & iwl_beacon_time_mask_low(priv, - priv->hw_params.beacon_time_tsf_bits); + hw_params(priv).beacon_time_tsf_bits); u32 addon_low = addon & iwl_beacon_time_mask_low(priv, - priv->hw_params.beacon_time_tsf_bits); + hw_params(priv).beacon_time_tsf_bits); u32 interval = beacon_interval * TIME_UNIT; u32 res = (base & iwl_beacon_time_mask_high(priv, - priv->hw_params.beacon_time_tsf_bits)) + + hw_params(priv).beacon_time_tsf_bits)) + (addon & iwl_beacon_time_mask_high(priv, - priv->hw_params.beacon_time_tsf_bits)); + hw_params(priv).beacon_time_tsf_bits)); if (base_low > addon_low) res += base_low - addon_low; else if (base_low < addon_low) { res += interval + base_low - addon_low; - res += (1 << priv->hw_params.beacon_time_tsf_bits); + res += (1 << hw_params(priv).beacon_time_tsf_bits); } else - res += (1 << priv->hw_params.beacon_time_tsf_bits); + res += (1 << hw_params(priv).beacon_time_tsf_bits); return cpu_to_le32(res); } diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index c798c6805b66..43543e52d7b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -340,7 +340,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = file->private_data; struct iwl_station_entry *station; - int max_sta = priv->hw_params.max_stations; + int max_sta = hw_params(priv).max_stations; char *buf; int i, j, pos = 0; ssize_t ret; @@ -908,7 +908,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, return -ENOMEM; } pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { txq = &priv->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, @@ -1006,7 +1006,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, if (!buf) return -ENOMEM; - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { txq = &priv->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e01caf7a1f12..57445c22fcbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -648,54 +648,6 @@ struct iwl_sensitivity_ranges { #define CELSIUS_TO_KELVIN(x) ((x)+273) -/** - * struct iwl_hw_params - * @max_txq_num: Max # Tx queues supported - * @scd_bc_tbls_size: size of scheduler byte count tables - * @tfd_size: TFD size - * @tx/rx_chains_num: Number of TX/RX chains - * @valid_tx/rx_ant: usable antennas - * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) - * @max_rxq_log: Log-base-2 of max_rxq_size - * @rx_page_order: Rx buffer page order - * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR - * @max_stations: - * @ht40_channel: is 40MHz width possible in band 2.4 - * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) - * @sw_crypto: 0 for hw, 1 for sw - * @max_xxx_size: for ucode uses - * @ct_kill_threshold: temperature threshold - * @beacon_time_tsf_bits: number of valid tsf bits for beacon time - * @calib_init_cfg: setup initial calibrations for the hw - * @calib_rt_cfg: setup runtime calibrations for the hw - * @struct iwl_sensitivity_ranges: range of sensitivity values - */ -struct iwl_hw_params { - u8 max_txq_num; - u16 scd_bc_tbls_size; - u32 tfd_size; - u8 tx_chains_num; - u8 rx_chains_num; - u8 valid_tx_ant; - u8 valid_rx_ant; - u16 max_rxq_size; - u16 max_rxq_log; - u32 rx_page_order; - u8 max_stations; - u8 ht40_channel; - u8 max_beacon_itrvl; /* in 1024 ms */ - u32 max_inst_size; - u32 max_data_size; - u32 ct_kill_threshold; /* value in hw-dependent units */ - u32 ct_kill_exit_threshold; /* value in hw-dependent units */ - /* for 1000, 6000 series and up */ - u16 beacon_time_tsf_bits; - u32 calib_init_cfg; - u32 calib_rt_cfg; - const struct iwl_sensitivity_ranges *sens; -}; - - /****************************************************************************** * * Functions implemented in core module which are forward declared here @@ -1480,8 +1432,6 @@ struct iwl_priv { struct iwl_rxon_context *cur_rssi_ctx; bool bt_is_sco; - struct iwl_hw_params hw_params; - u32 inta_mask; struct workqueue_struct *workqueue; @@ -1639,11 +1589,11 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) { - __free_pages(page, priv->hw_params.rx_page_order); + __free_pages(page, hw_params(priv).rx_page_order); } static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) { - free_pages(page, priv->hw_params.rx_page_order); + free_pages(page, hw_params(priv).rx_page_order); } #endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 2f267b8aabbb..40f6dd4decff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -217,7 +217,7 @@ ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) #define SCD_QUEUECHAIN_SEL_ALL(priv) \ - (((1<<(priv)->hw_params.max_txq_num) - 1) &\ + (((1<cmd_queue))) #define SCD_BASE (PRPH_BASE + 0xa02c00) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 28e59319f581..bddb2daf31bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -343,7 +343,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, void iwl_init_scan_params(struct iwl_priv *priv) { - u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; + u8 ant_idx = fls(hw_params(priv).valid_tx_ant) - 1; if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a7c0315472e9..483785c3fb04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -66,6 +66,7 @@ struct iwl_cfg; struct iwl_bus; struct iwl_priv; +struct iwl_sensitivity_ranges; extern struct iwl_mod_params iwlagn_mod_params; @@ -90,6 +91,53 @@ struct iwl_mod_params { int wanted_ucode_alternative; }; +/** + * struct iwl_hw_params + * @max_txq_num: Max # Tx queues supported + * @scd_bc_tbls_size: size of scheduler byte count tables + * @tfd_size: TFD size + * @tx/rx_chains_num: Number of TX/RX chains + * @valid_tx/rx_ant: usable antennas + * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) + * @max_rxq_log: Log-base-2 of max_rxq_size + * @rx_page_order: Rx buffer page order + * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR + * @max_stations: + * @ht40_channel: is 40MHz width possible in band 2.4 + * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) + * @sw_crypto: 0 for hw, 1 for sw + * @max_xxx_size: for ucode uses + * @ct_kill_threshold: temperature threshold + * @beacon_time_tsf_bits: number of valid tsf bits for beacon time + * @calib_init_cfg: setup initial calibrations for the hw + * @calib_rt_cfg: setup runtime calibrations for the hw + * @struct iwl_sensitivity_ranges: range of sensitivity values + */ +struct iwl_hw_params { + u8 max_txq_num; + u16 scd_bc_tbls_size; + u32 tfd_size; + u8 tx_chains_num; + u8 rx_chains_num; + u8 valid_tx_ant; + u8 valid_rx_ant; + u16 max_rxq_size; + u16 max_rxq_log; + u32 rx_page_order; + u8 max_stations; + u8 ht40_channel; + u8 max_beacon_itrvl; /* in 1024 ms */ + u32 max_inst_size; + u32 max_data_size; + u32 ct_kill_threshold; /* value in hw-dependent units */ + u32 ct_kill_exit_threshold; /* value in hw-dependent units */ + /* for 1000, 6000 series and up */ + u16 beacon_time_tsf_bits; + u32 calib_init_cfg; + u32 calib_rt_cfg; + const struct iwl_sensitivity_ranges *sens; +}; + /** * struct iwl_shared - shared fields for all the layers of the driver * @@ -97,6 +145,7 @@ struct iwl_mod_params { * iwlagn_mod_params.debug_level if set (!= 0) * @bus: pointer to the bus layer data * @priv: pointer to the upper layer data + * @hw_params: see struct iwl_hw_params */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -105,11 +154,13 @@ struct iwl_shared { struct iwl_bus *bus; struct iwl_priv *priv; + struct iwl_hw_params hw_params; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ #define priv(_m) ((_m)->shrd->priv) #define bus(_m) ((_m)->shrd->bus) +#define hw_params(_m) ((_m)->shrd->hw_params) #ifdef CONFIG_IWLWIFI_DEBUG /* diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 1ef3b7106ad5..b5b0ff3d8890 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -251,7 +251,8 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, else if (is_broadcast_ether_addr(addr)) sta_id = ctx->bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { + for (i = IWL_STA_ID; + i < hw_params(priv).max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { sta_id = i; @@ -535,7 +536,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); spin_lock_irqsave(&priv->sta_lock, flags_spin); - for (i = 0; i < priv->hw_params.max_stations; i++) { + for (i = 0; i < hw_params(priv).max_stations; i++) { if (ctx && ctx->ctxid != priv->stations[i].ctxid) continue; @@ -576,7 +577,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); spin_lock_irqsave(&priv->sta_lock, flags_spin); - for (i = 0; i < priv->hw_params.max_stations; i++) { + for (i = 0; i < hw_params(priv).max_stations; i++) { if (ctx->ctxid != priv->stations[i].ctxid) continue; if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && @@ -589,7 +590,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } } - for (i = 0; i < priv->hw_params.max_stations; i++) { + for (i = 0; i < hw_params(priv).max_stations; i++) { if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { memcpy(&sta_cmd, &priv->stations[i].sta, sizeof(struct iwl_addsta_cmd)); @@ -686,7 +687,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) int i; spin_lock_irqsave(&priv->sta_lock, flags); - for (i = 0; i < priv->hw_params.max_stations; i++) { + for (i = 0; i < hw_params(priv).max_stations; i++) { if (!(priv->stations[i].used & IWL_STA_BCAST)) continue; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 846db8fdbf6c..52edd6a10c7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -265,16 +265,17 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) if (rxq->free_count > RX_LOW_WATERMARK) gfp_mask |= __GFP_NOWARN; - if (priv->hw_params.rx_page_order > 0) + if (hw_params(priv).rx_page_order > 0) gfp_mask |= __GFP_COMP; /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); + page = alloc_pages(gfp_mask, + hw_params(priv).rx_page_order); if (!page) { if (net_ratelimit()) IWL_DEBUG_INFO(priv, "alloc_pages failed, " - "order: %d\n", - priv->hw_params.rx_page_order); + "order: %d\n", + hw_params(priv).rx_page_order); if ((rxq->free_count <= RX_LOW_WATERMARK) && net_ratelimit()) @@ -293,7 +294,7 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, priv->hw_params.rx_page_order); + __free_pages(page, hw_params(priv).rx_page_order); return; } element = rxq->rx_used.next; @@ -306,7 +307,7 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) rxb->page = page; /* Get physical address of the RB */ rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, - PAGE_SIZE << priv->hw_params.rx_page_order, + PAGE_SIZE << hw_params(priv).rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); @@ -405,7 +406,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; dma_unmap_page(priv->bus->dev, rxb->page_dma, - PAGE_SIZE << priv->hw_params.rx_page_order, + PAGE_SIZE << hw_params(priv).rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); @@ -456,7 +457,8 @@ static void iwl_rx_handle(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, - 0, PAGE_SIZE << priv->hw_params.rx_page_order, + 0, PAGE_SIZE << + hw_params(priv).rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; @@ -610,7 +612,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - for (i = 0; i < priv->hw_params.max_txq_num; i++) + for (i = 0; i < hw_params(priv).max_txq_num; i++) iwl_txq_update_write_ptr(priv, &priv->txq[i]); priv->isr_stats.wakeup++; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index e4a70fed8cf8..92128383cae7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -120,7 +120,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, - PAGE_SIZE << priv->hw_params.rx_page_order, + PAGE_SIZE << hw_params(priv).rx_page_order, DMA_FROM_DEVICE); __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; @@ -285,7 +285,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; + size_t tfd_sz = hw_params(priv).tfd_size * TFD_QUEUE_SIZE_MAX; int i; if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) @@ -429,7 +429,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { - dma_free_coherent(dev, priv->hw_params.tfd_size * + dma_free_coherent(dev, hw_params(priv).tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); } @@ -459,7 +459,8 @@ static void iwl_trans_tx_free(struct iwl_priv *priv) /* Tx queues */ if (priv->txq) { - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; + txq_id < hw_params(priv).max_txq_num; txq_id++) iwl_tx_queue_free(priv, txq_id); } @@ -491,7 +492,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) } ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, - priv->hw_params.scd_bc_tbls_size); + hw_params(priv).scd_bc_tbls_size); if (ret) { IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); goto error; @@ -513,7 +514,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) } /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, @@ -556,7 +557,7 @@ static int iwl_tx_init(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, @@ -789,7 +790,8 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) a += 4) iwl_write_targ_mem(priv, a, 0); for (; a < priv->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(priv).max_txq_num); + a += 4) iwl_write_targ_mem(priv, a, 0); iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, @@ -811,7 +813,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) iwl_write_prph(priv, SCD_AGGR_SEL, 0); /* initiate the queues */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { + for (i = 0; i < hw_params(priv).max_txq_num; i++) { iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); iwl_write_targ_mem(priv, priv->scd_base_addr + @@ -828,7 +830,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) } iwl_write_prph(priv, SCD_INTERRUPT_MASK, - IWL_MASK(0, priv->hw_params.max_txq_num)); + IWL_MASK(0, hw_params(priv).max_txq_num)); /* Activate all Tx DMA/FIFO channels */ iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); @@ -908,7 +910,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) } /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) iwl_tx_queue_unmap(priv, txq_id); return 0; From cefeaa5fa0be02cd51968975fec9cfaf7973bb3a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:40 -0700 Subject: [PATCH 057/129] iwlagn: cmd_queue moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 --- drivers/net/wireless/iwlwifi/iwl-prph.h | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 3 +++ .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 23 ++++++++++--------- drivers/net/wireless/iwlwifi/iwl-trans.c | 8 +++---- 8 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 048ccbae82f0..6db90854048d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1103,7 +1103,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) /* waiting for all the tx frames complete might take a while */ for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - if (cnt == priv->cmd_queue) + if (cnt == priv->shrd->cmd_queue) continue; txq = &priv->txq[cnt]; q = &txq->q; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e8177fb7ae2c..e61c68958b8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1244,10 +1244,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; } else { priv->sta_key_max_num = STA_KEY_MAX_NUM; - priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2aeafa18579f..02b70dcb93c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1818,14 +1818,14 @@ void iwl_bg_watchdog(unsigned long data) return; /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, priv->cmd_queue)) + if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) return; /* monitor and check for other stuck queues */ if (iwl_is_any_associated(priv)) { for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { /* skip as we already checked the command queue */ - if (cnt == priv->cmd_queue) + if (cnt == priv->shrd->cmd_queue) continue; if (iwl_check_stuck_queue(priv, cnt)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 57445c22fcbc..19a0ea9f5045 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1237,9 +1237,6 @@ struct iwl_priv { /* microcode/device supports multiple contexts */ u8 valid_contexts; - /* command queue number */ - u8 cmd_queue; - /* max number of station keys */ u8 sta_key_max_num; diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 40f6dd4decff..bebdd828f324 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -218,7 +218,7 @@ #define SCD_QUEUECHAIN_SEL_ALL(priv) \ (((1<cmd_queue))) + (~(1<<(priv)->shrd->cmd_queue))) #define SCD_BASE (PRPH_BASE + 0xa02c00) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 483785c3fb04..05621746825a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -143,6 +143,7 @@ struct iwl_hw_params { * * @dbg_level_dev: dbg level set per device. Prevails on * iwlagn_mod_params.debug_level if set (!= 0) + * @cmd_queue: command queue number * @bus: pointer to the bus layer data * @priv: pointer to the upper layer data * @hw_params: see struct iwl_hw_params @@ -152,6 +153,8 @@ struct iwl_shared { u32 dbg_level_dev; #endif /* CONFIG_IWLWIFI_DEBUG */ + u8 cmd_queue; + struct iwl_bus *bus; struct iwl_priv *priv; struct iwl_hw_params hw_params; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index a6b2b1db0b1d..b751f52905c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -349,7 +349,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != priv->cmd_queue) + if (txq_id != priv->shrd->cmd_queue) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -526,7 +526,7 @@ int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, */ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->shrd->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -618,8 +618,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | - INDEX_TO_SEQ(q->write_ptr)); + out_cmd->hdr.sequence = + cpu_to_le16(QUEUE_TO_SEQ(priv->shrd->cmd_queue) | + INDEX_TO_SEQ(q->write_ptr)); /* and copy the data that needs to be copied */ @@ -638,7 +639,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, - q->write_ptr, idx, priv->cmd_queue); + q->write_ptr, idx, priv->shrd->cmd_queue); phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); @@ -752,17 +753,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) int cmd_index; struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->shrd->cmd_queue]; unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != priv->cmd_queue, + if (WARN(txq_id != priv->shrd->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, priv->cmd_queue, sequence, - priv->txq[priv->cmd_queue].q.read_ptr, - priv->txq[priv->cmd_queue].q.write_ptr)) { + txq_id, priv->shrd->cmd_queue, sequence, + priv->txq[priv->shrd->cmd_queue].q.read_ptr, + priv->txq[priv->shrd->cmd_queue].q.write_ptr)) { iwl_print_hex_error(priv, pkt, 32); return; } @@ -1002,7 +1003,7 @@ cancel: * in later, it will possibly set an invalid * address (cmd->meta.source). */ - priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= + priv->txq[priv->shrd->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 92128383cae7..7a689df99496 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -311,7 +311,7 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (txq_id != priv->cmd_queue) { + if (txq_id != priv->shrd->cmd_queue) { txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { @@ -515,7 +515,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { - slots_num = (txq_id == priv->cmd_queue) ? + slots_num = (txq_id == priv->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, txq_id); @@ -558,7 +558,7 @@ static int iwl_tx_init(struct iwl_priv *priv) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { - slots_num = (txq_id == priv->cmd_queue) ? + slots_num = (txq_id == priv->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, txq_id); @@ -841,7 +841,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0); + iwl_trans_set_wr_ptrs(priv, priv->shrd->cmd_queue, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); From 74e28e44095e30ffd2d0258e4fe91826a15247e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:41 -0700 Subject: [PATCH 058/129] iwlagn: workqueue moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 -- drivers/net/wireless/iwlwifi/iwl-rx.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-scan.c | 11 ++++++----- drivers/net/wireless/iwlwifi/iwl-shared.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 2 +- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 6db90854048d..355a81cca18b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -388,7 +388,7 @@ void iwl_check_abort_status(struct iwl_priv *priv, if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { IWL_ERR(priv, "Tx flush command to flush out all frames\n"); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->tx_flush); + queue_work(priv->shrd->workqueue, &priv->tx_flush); } } @@ -1620,7 +1620,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; /* schedule to send runtime bt_config */ - queue_work(priv->workqueue, &priv->bt_runtime_config); + queue_work(priv->shrd->workqueue, &priv->bt_runtime_config); } } @@ -1664,7 +1664,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = coex->bt_status; - queue_work(priv->workqueue, + queue_work(priv->shrd->workqueue, &priv->bt_traffic_change_work); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3ca6e553fcd2..6812409a57c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -893,7 +893,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); - queue_work(priv->workqueue, &priv->bt_full_concurrency); + queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index f501d742984c..2c5558a82b81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -569,7 +569,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); - queue_work(priv->workqueue, &priv->ct_enter); + queue_work(priv->shrd->workqueue, &priv->ct_enter); } void iwl_tt_exit_ct_kill(struct iwl_priv *priv) @@ -578,7 +578,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); - queue_work(priv->workqueue, &priv->ct_exit); + queue_work(priv->shrd->workqueue, &priv->ct_exit); } static void iwl_bg_tt_work(struct work_struct *work) @@ -604,7 +604,7 @@ void iwl_tt_handler(struct iwl_priv *priv) return; IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); - queue_work(priv->workqueue, &priv->tt_work); + queue_work(priv->shrd->workqueue, &priv->tt_work); } /* Thermal throttling initialization diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e61c68958b8c..a3e2ef4d3443 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2286,7 +2286,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) iwl_down(priv); - flush_workqueue(priv->workqueue); + flush_workqueue(priv->shrd->workqueue); /* User space software may expect getting rfkill changes * even if interface is down */ @@ -3340,7 +3340,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) static void iwl_setup_deferred_work(struct iwl_priv *priv) { - priv->workqueue = create_singlethread_workqueue(DRV_NAME); + priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME); init_waitqueue_head(&priv->wait_command_queue); @@ -3746,8 +3746,8 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) return 0; out_destroy_workqueue: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; + destroy_workqueue(priv->shrd->workqueue); + priv->shrd->workqueue = NULL; iwl_uninit_drv(priv); out_free_eeprom: iwl_eeprom_free(priv); @@ -3808,13 +3808,13 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_eeprom_free(priv); /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); + flush_workqueue(priv->shrd->workqueue); /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes - * priv->workqueue... so we can't take down the workqueue + * priv->shrd->workqueue... so we can't take down the workqueue * until now... */ - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; + destroy_workqueue(priv->shrd->workqueue); + priv->shrd->workqueue = NULL; iwl_free_traffic_mem(priv); trans_free(&priv->trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 02b70dcb93c3..b62ccd7acb4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -894,7 +894,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) if (iwlagn_mod_params.restart_fw) { IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); - queue_work(priv->workqueue, &priv->restart); + queue_work(priv->shrd->workqueue, &priv->restart); } else IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Detected FW error, but not restarting\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 19a0ea9f5045..67e422b730e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1431,8 +1431,6 @@ struct iwl_priv { u32 inta_mask; - struct workqueue_struct *workqueue; - struct work_struct restart; struct work_struct scan_completed; struct work_struct rx_replenish; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8b3a08958cc8..c8af4549a0f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -150,7 +150,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - queue_work(priv->workqueue, &priv->beacon_update); + queue_work(priv->shrd->workqueue, &priv->beacon_update); } /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ @@ -487,7 +487,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwl_rx_calc_noise(priv); - queue_work(priv->workqueue, &priv->run_time_calib_work); + queue_work(priv->shrd->workqueue, &priv->run_time_calib_work); } if (priv->cfg->lib->temperature && change) priv->cfg->lib->temperature(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index bddb2daf31bd..6610b1d687c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -160,7 +160,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) int iwl_scan_cancel(struct iwl_priv *priv) { IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); - queue_work(priv->workqueue, &priv->abort_scan); + queue_work(priv->shrd->workqueue, &priv->abort_scan); return 0; } @@ -263,7 +263,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - priv->scan_start)); - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->shrd->workqueue, &priv->scan_completed); if (priv->iw_mode != NL80211_IFTYPE_ADHOC && iwl_advanced_bt_coexist(priv) && @@ -283,7 +283,8 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = scan_notif->bt_status; - queue_work(priv->workqueue, &priv->bt_traffic_change_work); + queue_work(priv->shrd->workqueue, + &priv->bt_traffic_change_work); } } @@ -394,7 +395,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, return ret; } - queue_delayed_work(priv->workqueue, &priv->scan_check, + queue_delayed_work(priv->shrd->workqueue, &priv->scan_check, IWL_SCAN_CHECK_WATCHDOG); return 0; @@ -450,7 +451,7 @@ out_unlock: */ void iwl_internal_short_hw_scan(struct iwl_priv *priv) { - queue_work(priv->workqueue, &priv->start_internal_scan); + queue_work(priv->shrd->workqueue, &priv->start_internal_scan); } static void iwl_bg_start_internal_scan(struct work_struct *work) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 05621746825a..85d5a6231393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -147,6 +147,7 @@ struct iwl_hw_params { * @bus: pointer to the bus layer data * @priv: pointer to the upper layer data * @hw_params: see struct iwl_hw_params + * @workqueue: the workqueue used by all the layers of the driver */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -158,6 +159,8 @@ struct iwl_shared { struct iwl_bus *bus; struct iwl_priv *priv; struct iwl_hw_params hw_params; + + struct workqueue_struct *workqueue; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 52edd6a10c7a..10627f88c4e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -224,7 +224,7 @@ static void iwlagn_rx_queue_restock(struct iwl_priv *priv) /* If the pre-allocated buffer pool is dropping low, schedule to * refill it */ if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); + queue_work(priv->shrd->workqueue, &priv->rx_replenish); /* If we've added more space for the firmware to place data, tell it. From 63013ae30159c90d2a873e20e680e7810fa533fa Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:42 -0700 Subject: [PATCH 059/129] iwlagn: priv->status moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 14 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 10 +-- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 32 +++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 72 ++++++++++--------- drivers/net/wireless/iwlwifi/iwl-core.c | 39 +++++----- drivers/net/wireless/iwlwifi/iwl-core.h | 14 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 34 ++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 - drivers/net/wireless/iwlwifi/iwl-helpers.h | 4 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 6 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 22 +++--- drivers/net/wireless/iwlwifi/iwl-scan.c | 44 ++++++------ drivers/net/wireless/iwlwifi/iwl-shared.h | 2 + .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 21 +++--- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 22 +++--- drivers/net/wireless/iwlwifi/iwl-trans.c | 8 +-- 17 files changed, 177 insertions(+), 171 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 355a81cca18b..7c3e3eace955 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -387,7 +387,7 @@ void iwl_check_abort_status(struct iwl_priv *priv, { if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { IWL_ERR(priv, "Tx flush command to flush out all frames\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) queue_work(priv->shrd->workqueue, &priv->tx_flush); } } @@ -496,7 +496,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; - if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status), "TX Power requested while scanning!\n")) return -EAGAIN; @@ -945,7 +945,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); /* In power save mode use one chain, otherwise use all chains */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { /* rx_ant has been set to all valid chains previously */ active_chains = rx_ant & ((u8)(priv->chain_noise_data.active_chains)); @@ -1048,7 +1048,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ - set_bit(STATUS_SCAN_HW, &priv->status); + set_bit(STATUS_SCAN_HW, &priv->shrd->status); ret = iwlagn_set_pan_params(priv); if (ret) @@ -1056,7 +1056,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ret = trans_send_cmd(&priv->trans, &cmd); if (ret) { - clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->shrd->status); iwlagn_set_pan_params(priv); } @@ -1494,7 +1494,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) * STATUS_SCANNING to avoid race when queue_work two times from * different notifications, but quit and not perform any work at all. */ - if (test_bit(STATUS_SCAN_HW, &priv->status)) + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) goto out; iwl_update_chain_flags(priv); @@ -1775,7 +1775,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status); u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; u32 active_chains; u16 rx_chain; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2829bf843d0c..e74c2429c1c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -363,7 +363,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot0 = bcnint / 2; slot1 = bcnint - slot0; - if (test_bit(STATUS_SCAN_HW, &priv->status) || + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; @@ -379,7 +379,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) ctx_pan->beacon_int; slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); - if (test_bit(STATUS_SCAN_HW, &priv->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; slot1 = IWL_MIN_SLOT_TIME; } @@ -423,7 +423,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EINVAL; if (!iwl_is_alive(priv)) @@ -463,7 +463,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) && (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_channel)); @@ -539,7 +539,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); - if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { + if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); goto out; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 2c5558a82b81..44fff5bf9dcd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -176,7 +176,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) struct iwl_tt_mgmt *tt = &priv->thermal_throttle; unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (tt->state == IWL_TI_CT_KILL) { @@ -227,7 +227,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) struct iwl_priv *priv = (struct iwl_priv *)data; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; /* temperature timer expired, ready to go into CT_KILL state */ @@ -235,7 +235,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) IWL_DEBUG_TEMP(priv, "entering CT_KILL state when " "temperature timer expired\n"); tt->state = IWL_TI_CT_KILL; - set_bit(STATUS_CT_KILL, &priv->status); + set_bit(STATUS_CT_KILL, &priv->shrd->status); iwl_perform_ct_kill_task(priv, true); } } @@ -315,21 +315,22 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) } mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->status); + clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated * try again during next temperature read */ if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->status); + set_bit(STATUS_CT_KILL, &priv->shrd->status); tt->state = old_state; IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); } else { if (tt->state == IWL_TI_CT_KILL) { if (force) { - set_bit(STATUS_CT_KILL, &priv->status); + set_bit(STATUS_CT_KILL, + &priv->shrd->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -455,7 +456,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) } mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->status); + clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated @@ -464,7 +465,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->status); + set_bit(STATUS_CT_KILL, &priv->shrd->status); tt->state = old_state; } else { IWL_DEBUG_TEMP(priv, @@ -475,7 +476,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) if (force) { IWL_DEBUG_TEMP(priv, "Enter IWL_TI_CT_KILL\n"); - set_bit(STATUS_CT_KILL, &priv->status); + set_bit(STATUS_CT_KILL, + &priv->shrd->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -506,7 +508,7 @@ static void iwl_bg_ct_enter(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (!iwl_is_ready(priv)) @@ -535,7 +537,7 @@ static void iwl_bg_ct_exit(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (!iwl_is_ready(priv)) @@ -565,7 +567,7 @@ static void iwl_bg_ct_exit(struct work_struct *work) void iwl_tt_enter_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); @@ -574,7 +576,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv) void iwl_tt_exit_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); @@ -586,7 +588,7 @@ static void iwl_bg_tt_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (priv->cfg->base_params->temperature_kelvin) @@ -600,7 +602,7 @@ static void iwl_bg_tt_work(struct work_struct *work) void iwl_tt_handler(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a3e2ef4d3443..e77c4c47762b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -247,7 +247,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_runtime_config); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; /* dont send host command if rf-kill is on */ @@ -264,7 +264,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) goto out; /* dont send host command if rf-kill is on */ @@ -303,7 +303,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; /* dont send host command if rf-kill is on */ @@ -424,7 +424,7 @@ static void iwl_bg_ucode_trace(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (priv->event_log.ucode_trace) { @@ -440,7 +440,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tx_flush); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; /* do nothing if rf-kill is on */ @@ -1405,7 +1405,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(priv, "Start IWL Error Log Dump:\n"); IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, table.valid); + priv->shrd->status, table.valid); } priv->isr_stats.err_code = table.error_id; @@ -1765,7 +1765,7 @@ int iwl_alive_start(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->status); + set_bit(STATUS_ALIVE, &priv->shrd->status); /* Enable watchdog to monitor the driver tx queues */ iwl_setup_watchdog(priv); @@ -1838,7 +1838,7 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); } - set_bit(STATUS_READY, &priv->status); + set_bit(STATUS_READY, &priv->shrd->status); /* Configure the adapter for unassociated operation */ ret = iwlagn_commit_rxon(priv, ctx); @@ -1870,7 +1870,8 @@ static void __iwl_down(struct iwl_priv *priv) */ ieee80211_remain_on_channel_expired(priv->hw); - exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); + exit_pending = + test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ @@ -1895,19 +1896,20 @@ static void __iwl_down(struct iwl_priv *priv) /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->status); + clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); /* Clear out all status bits but a few that are stable across reset */ - priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << + priv->shrd->status &= + test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->status) << + test_bit(STATUS_FW_ERROR, &priv->shrd->status) << STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->status) << + test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << STATUS_EXIT_PENDING; trans_stop_device(&priv->trans); @@ -1934,7 +1936,7 @@ static int __iwl_up(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } @@ -1967,9 +1969,9 @@ static int __iwl_up(struct iwl_priv *priv) return 0; error: - set_bit(STATUS_EXIT_PENDING, &priv->status); + set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); __iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->status); + clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); IWL_ERR(priv, "Unable to initialize device.\n"); return ret; @@ -1989,8 +1991,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || + test_bit(STATUS_SCANNING, &priv->shrd->status)) { mutex_unlock(&priv->mutex); return; } @@ -2046,10 +2048,10 @@ static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { mutex_lock(&priv->mutex); iwlagn_prepare_restart(priv); mutex_unlock(&priv->mutex); @@ -2263,7 +2265,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_INFO(priv, "Start UP work done.\n"); /* Now we should be done, and the READY bit should be set. */ - if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) + if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) ret = -EIO; iwlagn_led_enable(priv); @@ -2905,7 +2907,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); ret = iwl_sta_rx_agg_stop(priv, sta, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) ret = 0; break; case IEEE80211_AMPDU_TX_START: @@ -2925,7 +2927,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", priv->agg_tids_count); } - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) ret = 0; if (priv->cfg->ht_params && priv->cfg->ht_params->use_rts_for_aggregation) { @@ -3060,9 +3062,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, if (iwl_is_rfkill(priv)) goto out; - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || + test_bit(STATUS_SCANNING, &priv->shrd->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) goto out; if (!iwl_is_associated_ctx(ctx)) @@ -3118,10 +3120,10 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ - set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); priv->switch_channel = cpu_to_le16(ch); if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { - clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); priv->switch_channel = 0; ieee80211_chswitch_done(ctx->vif, false); } @@ -3188,7 +3190,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); goto done; } @@ -3273,7 +3275,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) duration = 80; - if (test_bit(STATUS_SCAN_HW, &priv->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { err = -EBUSY; goto out; } @@ -3727,12 +3729,12 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); + clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else - set_bit(STATUS_RF_KILL_HW, &priv->status); + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); + test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); iwl_power_initialize(priv); iwl_tt_initialize(priv); @@ -3776,7 +3778,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) * to be called and iwl_down since we are removing the device * we need to set STATUS_EXIT_PENDING bit. */ - set_bit(STATUS_EXIT_PENDING, &priv->status); + set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); iwl_testmode_cleanup(priv); iwl_leds_exit(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b62ccd7acb4f..a5a694daddde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -121,7 +121,7 @@ int iwl_init_geos(struct iwl_priv *priv) if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); return 0; } @@ -221,7 +221,7 @@ int iwl_init_geos(struct iwl_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - set_bit(STATUS_GEO_CONFIGURED, &priv->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); return 0; } @@ -233,7 +233,7 @@ void iwl_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->status); + clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); } static bool iwl_is_channel_extension(struct iwl_priv *priv, @@ -808,10 +808,11 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; - if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, + &priv->shrd->status)) ieee80211_chswitch_done(ctx->vif, is_success); } @@ -856,16 +857,16 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned long reload_jiffies; /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->status); + set_bit(STATUS_FW_ERROR, &priv->shrd->status); /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); iwlagn_abort_notification_waits(priv); /* Keep the restart process from trying to send host * commands by clearing the ready bit */ - clear_bit(STATUS_READY, &priv->status); + clear_bit(STATUS_READY, &priv->shrd->status); wake_up_interruptible(&priv->wait_command_queue); @@ -890,7 +891,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) priv->reload_count = 0; } - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { + if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { if (iwlagn_mod_params.restart_fw) { IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); @@ -916,8 +917,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) * Keep the restart process from trying to send host * commands by clearing the ready bit. */ - clear_bit(STATUS_READY, &priv->status); - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + clear_bit(STATUS_READY, &priv->shrd->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); wake_up_interruptible(&priv->wait_command_queue); IWL_ERR(priv, "RF is used by WiMAX\n"); return; @@ -960,7 +961,7 @@ void iwl_apm_stop(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - clear_bit(STATUS_DEVICE_ENABLED, &priv->status); + clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); /* Stop device's DMA activity */ iwl_apm_stop_master(priv); @@ -1054,7 +1055,7 @@ int iwl_apm_init(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - set_bit(STATUS_DEVICE_ENABLED, &priv->status); + set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); out: return ret; @@ -1096,7 +1097,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) priv->tx_power_next = tx_power; /* do not set tx power when scanning or channel changing */ - defer = test_bit(STATUS_SCANNING, &priv->status) || + defer = test_bit(STATUS_SCANNING, &priv->shrd->status) || memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); if (defer && !force) { IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); @@ -1613,7 +1614,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) static void iwl_force_rf_reset(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; if (!iwl_is_any_associated(priv)) { @@ -1638,7 +1639,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) { struct iwl_force_reset *force_reset; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EINVAL; if (mode >= IWL_MAX_FORCE_RESET) { @@ -1810,7 +1811,7 @@ void iwl_bg_watchdog(unsigned long data) int cnt; unsigned long timeout; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; timeout = priv->cfg->base_params->wd_timeout; @@ -1930,9 +1931,9 @@ int iwl_resume(struct iwl_priv *priv) hw_rfkill = true; if (hw_rfkill) - set_bit(STATUS_RF_KILL_HW, &priv->status); + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->status); + clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index fe46d0f71362..797fefa1bf2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -426,24 +426,24 @@ static inline int iwl_is_ready(struct iwl_priv *priv) { /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &priv->status) && - test_bit(STATUS_GEO_CONFIGURED, &priv->status) && - !test_bit(STATUS_EXIT_PENDING, &priv->status); + return test_bit(STATUS_READY, &priv->shrd->status) && + test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) && + !test_bit(STATUS_EXIT_PENDING, &priv->shrd->status); } static inline int iwl_is_alive(struct iwl_priv *priv) { - return test_bit(STATUS_ALIVE, &priv->status); + return test_bit(STATUS_ALIVE, &priv->shrd->status); } static inline int iwl_is_init(struct iwl_priv *priv) { - return test_bit(STATUS_INIT, &priv->status); + return test_bit(STATUS_INIT, &priv->shrd->status); } static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status); + return test_bit(STATUS_RF_KILL_HW, &priv->shrd->status); } static inline int iwl_is_rfkill(struct iwl_priv *priv) @@ -453,7 +453,7 @@ static inline int iwl_is_rfkill(struct iwl_priv *priv) static inline int iwl_is_ctkill(struct iwl_priv *priv) { - return test_bit(STATUS_CT_KILL, &priv->status); + return test_bit(STATUS_CT_KILL, &priv->shrd->status); } static inline int iwl_is_ready_rf(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 43543e52d7b7..8bd817759264 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -492,7 +492,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, char *buf; ssize_t ret; - if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) + if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -562,37 +562,37 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, const size_t bufsz = sizeof(buf); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", - test_bit(STATUS_HCMD_ACTIVE, &priv->status)); + test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", - test_bit(STATUS_INT_ENABLED, &priv->status)); + test_bit(STATUS_INT_ENABLED, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", - test_bit(STATUS_RF_KILL_HW, &priv->status)); + test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", - test_bit(STATUS_CT_KILL, &priv->status)); + test_bit(STATUS_CT_KILL, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", - test_bit(STATUS_INIT, &priv->status)); + test_bit(STATUS_INIT, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", - test_bit(STATUS_ALIVE, &priv->status)); + test_bit(STATUS_ALIVE, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", - test_bit(STATUS_READY, &priv->status)); + test_bit(STATUS_READY, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", - test_bit(STATUS_TEMPERATURE, &priv->status)); + test_bit(STATUS_TEMPERATURE, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", - test_bit(STATUS_GEO_CONFIGURED, &priv->status)); + test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", - test_bit(STATUS_EXIT_PENDING, &priv->status)); + test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", - test_bit(STATUS_STATISTICS, &priv->status)); + test_bit(STATUS_STATISTICS, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", - test_bit(STATUS_SCANNING, &priv->status)); + test_bit(STATUS_SCANNING, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", - test_bit(STATUS_SCAN_ABORTING, &priv->status)); + test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", - test_bit(STATUS_SCAN_HW, &priv->status)); + test_bit(STATUS_SCAN_HW, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", - test_bit(STATUS_POWER_PMI, &priv->status)); + test_bit(STATUS_POWER_PMI, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", - test_bit(STATUS_FW_ERROR, &priv->status)); + test_bit(STATUS_FW_ERROR, &priv->shrd->status)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 67e422b730e4..bf166bcb0080 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1297,8 +1297,6 @@ struct iwl_priv { u32 scd_base_addr; /* scheduler sram base address */ - unsigned long status; - /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; struct traffic_stats rx_stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 9d91552d13c1..d053ed7ef794 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -134,7 +134,7 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv, static inline void iwl_disable_interrupts(struct iwl_priv *priv) { - clear_bit(STATUS_INT_ENABLED, &priv->status); + clear_bit(STATUS_INT_ENABLED, &priv->shrd->status); /* disable interrupts from uCode/NIC to host */ iwl_write32(priv, CSR_INT_MASK, 0x00000000); @@ -155,7 +155,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) static inline void iwl_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &priv->status); + set_bit(STATUS_INT_ENABLED, &priv->shrd->status); iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index d8049febe047..53b69ed704ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -126,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, }; int ret; - if (!test_bit(STATUS_READY, &priv->status)) + if (!test_bit(STATUS_READY, &priv->shrd->status)) return -EBUSY; if (priv->blink_on == on && priv->blink_off == off) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index b60e692a4765..52a6f8aa5276 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -397,18 +397,18 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, /* scan complete use sleep_power_next, need to be updated */ memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); - if (test_bit(STATUS_SCANNING, &priv->status) && !force) { + if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) { IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); return 0; } if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->status); + set_bit(STATUS_POWER_PMI, &priv->shrd->status); ret = iwl_set_power(priv, cmd); if (!ret) { if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->status); + clear_bit(STATUS_POWER_PMI, &priv->shrd->status); if (update_chains) iwl_update_chain_flags(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c8af4549a0f9..37bc017b80ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -74,7 +74,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) return; if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { @@ -149,7 +149,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) queue_work(priv->shrd->workqueue, &priv->beacon_update); } @@ -259,7 +259,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, { unsigned int msecs; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); @@ -475,7 +475,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, priv->rx_statistics_jiffies = stamp; - set_bit(STATUS_STATISTICS, &priv->status); + set_bit(STATUS_STATISTICS, &priv->shrd->status); /* Reschedule the statistics timer to occur in * reg_recalib_period seconds to ensure we get a @@ -484,7 +484,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, mod_timer(&priv->statistics_periodic, jiffies + msecs_to_jiffies(reg_recalib_period * 1000)); - if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && + if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwl_rx_calc_noise(priv); queue_work(priv->shrd->workqueue, &priv->run_time_calib_work); @@ -519,7 +519,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); - unsigned long status = priv->status; + unsigned long status = priv->shrd->status; IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", @@ -549,18 +549,18 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, iwl_tt_exit_ct_kill(priv); if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->status); + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->status); + clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); if (!(flags & RXON_CARD_DISABLED)) iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->status))) + test_bit(STATUS_RF_KILL_HW, &priv->shrd->status))) wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); + test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); else wake_up_interruptible(&priv->wait_command_queue); } @@ -581,7 +581,7 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); - if (!test_bit(STATUS_SCANNING, &priv->status)) + if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) iwl_init_sensitivity(priv); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 6610b1d687c8..bc8cb1d3b555 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -68,11 +68,11 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform * hardware scan currently */ - if (!test_bit(STATUS_READY, &priv->status) || - !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || - !test_bit(STATUS_SCAN_HW, &priv->status) || - test_bit(STATUS_FW_ERROR, &priv->status) || - test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (!test_bit(STATUS_READY, &priv->shrd->status) || + !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || + !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || + test_bit(STATUS_FW_ERROR, &priv->shrd->status) || + test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EIO; ret = trans_send_cmd(&priv->trans, &cmd); @@ -118,15 +118,15 @@ void iwl_force_scan_end(struct iwl_priv *priv) { lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->status)) { + if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); return; } IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); - clear_bit(STATUS_SCANNING, &priv->status); - clear_bit(STATUS_SCAN_HW, &priv->status); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); + clear_bit(STATUS_SCANNING, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); iwl_complete_scan(priv, true); } @@ -136,12 +136,12 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->status)) { + if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); return; } - if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { + if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); return; } @@ -180,12 +180,12 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) iwl_do_scan_abort(priv); while (time_before_eq(jiffies, timeout)) { - if (!test_bit(STATUS_SCAN_HW, &priv->status)) + if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) break; msleep(20); } - return test_bit(STATUS_SCAN_HW, &priv->status); + return test_bit(STATUS_SCAN_HW, &priv->shrd->status); } /* Service response to REPLY_SCAN_CMD (0x80) */ @@ -257,7 +257,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->tsf_high, scan_notif->status); /* The HW is no longer scanning */ - clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->shrd->status); IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", @@ -367,13 +367,13 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, return -EIO; } - if (test_bit(STATUS_SCAN_HW, &priv->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Multiple concurrent scan requests in parallel.\n"); return -EBUSY; } - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); return -EBUSY; } @@ -383,14 +383,14 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, scan_type == IWL_SCAN_ROC ? "remain-on-channel " : "internal short "); - set_bit(STATUS_SCANNING, &priv->status); + set_bit(STATUS_SCANNING, &priv->shrd->status); priv->scan_type = scan_type; priv->scan_start = jiffies; priv->scan_band = band; ret = iwlagn_request_scan(priv, vif); if (ret) { - clear_bit(STATUS_SCANNING, &priv->status); + clear_bit(STATUS_SCANNING, &priv->shrd->status); priv->scan_type = IWL_SCAN_NORMAL; return ret; } @@ -415,7 +415,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) && + if (test_bit(STATUS_SCANNING, &priv->shrd->status) && priv->scan_type != IWL_SCAN_NORMAL) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); ret = -EAGAIN; @@ -468,7 +468,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) goto unlock; } - if (test_bit(STATUS_SCANNING, &priv->status)) { + if (test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); goto unlock; } @@ -566,11 +566,11 @@ static void iwl_bg_scan_completed(struct work_struct *work) mutex_lock(&priv->mutex); - aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); + aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); if (aborted) IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); - if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { + if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); goto out_settings; } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 85d5a6231393..74ff711c7212 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -144,6 +144,7 @@ struct iwl_hw_params { * @dbg_level_dev: dbg level set per device. Prevails on * iwlagn_mod_params.debug_level if set (!= 0) * @cmd_queue: command queue number + * @status: STATUS_* * @bus: pointer to the bus layer data * @priv: pointer to the upper layer data * @hw_params: see struct iwl_hw_params @@ -155,6 +156,7 @@ struct iwl_shared { #endif /* CONFIG_IWLWIFI_DEBUG */ u8 cmd_queue; + unsigned long status; struct iwl_bus *bus; struct iwl_priv *priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 10627f88c4e2..0b798153f0df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -145,7 +145,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { @@ -346,7 +346,7 @@ void iwl_bg_rx_replenish(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, rx_replenish); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; mutex_lock(&priv->mutex); @@ -581,11 +581,12 @@ void iwl_irq_tasklet(struct iwl_priv *priv) * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(STATUS_ALIVE, &priv->status)) { + if (!test_bit(STATUS_ALIVE, &priv->shrd->status)) { if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->status); + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->status); + clear_bit(STATUS_RF_KILL_HW, + &priv->shrd->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); } @@ -688,7 +689,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) + if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status)) iwl_enable_interrupts(priv); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) @@ -858,7 +859,7 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) iwl_enable_interrupts(priv); @@ -869,7 +870,7 @@ static irqreturn_t iwl_isr(int irq, void *data) none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -957,7 +958,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, @@ -973,7 +974,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index b751f52905c0..ab421529d12c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -96,7 +96,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ @@ -544,7 +544,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int trace_idx; #endif - if (test_bit(STATUS_FW_ERROR, &priv->status)) { + if (test_bit(STATUS_FW_ERROR, &priv->shrd->status)) { IWL_WARN(priv, "fw recovery, no hcmd send\n"); return -EIO; } @@ -786,7 +786,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); @@ -917,7 +917,7 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!cmd->callback) cmd->callback = iwl_generic_cmd_callback; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EBUSY; ret = iwl_enqueue_hcmd(priv, cmd); @@ -943,30 +943,30 @@ static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - set_bit(STATUS_HCMD_ACTIVE, &priv->status); + set_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->status), + !test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status), HOST_COMPLETE_TIMEOUT); if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { + if (test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)) { IWL_ERR(priv, "Error sending %s: time out after %dms.\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" "%s\n", get_cmd_string(cmd->id)); ret = -ETIMEDOUT; @@ -974,13 +974,13 @@ static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } } - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + if (test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)) { IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); ret = -ECANCELED; goto fail; } - if (test_bit(STATUS_FW_ERROR, &priv->status)) { + if (test_bit(STATUS_FW_ERROR, &priv->shrd->status)) { IWL_ERR(priv, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); ret = -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 7a689df99496..a3e1bd0abc28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -623,7 +623,7 @@ static int iwl_nic_init(struct iwl_priv *priv) 0x800FFFFF); } - set_bit(STATUS_INIT, &priv->status); + set_bit(STATUS_INIT, &priv->shrd->status); return 0; } @@ -692,9 +692,9 @@ static int iwl_trans_start_device(struct iwl_priv *priv) /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); + clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else - set_bit(STATUS_RF_KILL_HW, &priv->status); + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); if (iwl_is_rfkill(priv)) { wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); @@ -939,7 +939,7 @@ static void iwl_trans_stop_device(struct iwl_priv *priv) * restart. So don't process again if the device is * already dead. */ - if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + if (test_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status)) { iwl_trans_tx_stop(priv); iwl_trans_rx_stop(priv); From 10b15e6f67ba4d9abb8788100a5267341cc98b7b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:43 -0700 Subject: [PATCH 060/129] iwlagn: priv->lock moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 14 +++++----- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++----- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-shared.h | 2 ++ .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 28 +++++++++---------- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-trans.c | 26 ++++++++--------- 13 files changed, 61 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e073422edab4..feefb5b0987c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -69,7 +69,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* W/A : NIC is stuck in a reset state after Early PCIe power off * (PCIe power is lost before PERST# is asserted), @@ -80,7 +80,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv) ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } static struct iwl_sensitivity_ranges iwl5000_sensitivity = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index f0e38a14053a..fb6da14bef4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -658,13 +658,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); rx_info = &priv->statistics.rx_non_phy; ofdm = &priv->statistics.rx_ofdm; cck = &priv->statistics.rx_cck; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return; } @@ -688,7 +688,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); @@ -976,13 +976,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); rx_info = &priv->statistics.rx_non_phy; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return; } @@ -997,7 +997,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", rxon_chnum, rxon_band24); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return; } @@ -1016,7 +1016,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); data->beacon_count++; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7c3e3eace955..7ace5078cc99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1673,9 +1673,9 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, /* FIXME: based on notification, adjust the prio_boost */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 6812409a57c4..cff6442ab0c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -877,12 +877,12 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, * Is there a need to switch between * full concurrency and 3-wire? */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) full_concurrent = true; else full_concurrent = false; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index e74c2429c1c8..fadfc38b87bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -576,7 +576,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); for_each_context(priv, ctx) { /* Configure HT40 channels */ @@ -620,7 +620,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->vif); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); iwl_update_bcast_stations(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3e2a9040de1b..89d7b30525f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -336,7 +336,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; @@ -404,7 +404,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) else txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; - /* irqs already disabled/saved above when locking priv->lock */ + /* irqs already disabled/saved above when locking priv->shrd->lock */ spin_lock(&priv->sta_lock); if (ieee80211_is_data_qos(fc)) { @@ -461,7 +461,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } spin_unlock(&priv->sta_lock); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); /* * Avoid atomic ops if it isn't an associated client. @@ -478,7 +478,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) drop_unlock_sta: spin_unlock(&priv->sta_lock); drop_unlock_priv: - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return -1; } @@ -620,7 +620,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, /* do not restore/save irqs */ spin_unlock(&priv->sta_lock); - spin_lock(&priv->lock); + spin_lock(&priv->shrd->lock); /* * the only reason this call can fail is queue number out of range, @@ -630,7 +630,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * mac80211 to clean up it own data. */ trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e77c4c47762b..6d2c13e7f51b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1673,10 +1673,10 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) unsigned long flags; int ret = 0; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); priv->thermal_throttle.ct_kill_toggle = false; if (priv->cfg->base_params->support_ct_kill_exit) { @@ -3083,7 +3083,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; } - spin_lock_irq(&priv->lock); + spin_lock_irq(&priv->shrd->lock); priv->current_ht_config.smps = conf->smps_mode; @@ -3113,7 +3113,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); - spin_unlock_irq(&priv->lock); + spin_unlock_irq(&priv->shrd->lock); iwl_set_rate(priv); /* @@ -3640,7 +3640,7 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) * we should init now */ spin_lock_init(&priv->reg_lock); - spin_lock_init(&priv->lock); + spin_lock_init(&priv->shrd->lock); /* * stop and reset the on-board processor just in case it is in a @@ -3796,9 +3796,9 @@ void __devexit iwl_remove(struct iwl_priv * priv) /* make sure we flush any pending irq or * tasklet for the driver */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); trans_sync_irq(&priv->trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a5a694daddde..40ad889264a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1186,7 +1186,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, q = AC_NUM - 1 - queue; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* * MULTI-FIXME @@ -1204,7 +1204,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bf166bcb0080..c60a24232d6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1226,7 +1226,6 @@ struct iwl_priv { u8 mgmt_tx_ant; /* spinlock */ - spinlock_t lock; /* protect general shared data */ spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 74ff711c7212..1c2c31c15f60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -149,6 +149,7 @@ struct iwl_hw_params { * @priv: pointer to the upper layer data * @hw_params: see struct iwl_hw_params * @workqueue: the workqueue used by all the layers of the driver + * @lock: protect general shared data */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -163,6 +164,7 @@ struct iwl_shared { struct iwl_hw_params hw_params; struct workqueue_struct *workqueue; + spinlock_t lock; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 0b798153f0df..26497dd454a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -329,9 +329,9 @@ void iwlagn_rx_replenish(struct iwl_priv *priv) iwlagn_rx_allocate(priv, GFP_KERNEL); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwlagn_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } static void iwlagn_rx_replenish_now(struct iwl_priv *priv) @@ -499,7 +499,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) u32 inta_mask; #endif - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, @@ -525,7 +525,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) } #endif - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); /* saved interrupt in inta variable now we can reset priv->inta */ priv->inta = 0; @@ -774,7 +774,7 @@ int iwl_reset_ict(struct iwl_priv *priv) if (!priv->ict_tbl_vir) return 0; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_disable_interrupts(priv); memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); @@ -794,7 +794,7 @@ int iwl_reset_ict(struct iwl_priv *priv) priv->ict_index = 0; iwl_write32(priv, CSR_INT, priv->inta_mask); iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return 0; } @@ -804,9 +804,9 @@ void iwl_disable_ict(struct iwl_priv *priv) { unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); priv->use_ict = false; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } static irqreturn_t iwl_isr(int irq, void *data) @@ -820,7 +820,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if (!priv) return IRQ_NONE; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. @@ -864,7 +864,7 @@ static irqreturn_t iwl_isr(int irq, void *data) iwl_enable_interrupts(priv); unplugged: - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return IRQ_HANDLED; none: @@ -873,7 +873,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return IRQ_NONE; } @@ -901,7 +901,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (!priv->use_ict) return iwl_isr(irq, data); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. @@ -967,7 +967,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) iwl_enable_interrupts(priv); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return IRQ_HANDLED; none: @@ -977,6 +977,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return IRQ_NONE; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index ab421529d12c..61e17dd4f389 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -444,7 +444,7 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, ra_tid = BUILD_RAxTID(sta_id, tid); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* Stop this Tx queue before configuring it */ iwlagn_tx_queue_stop_scheduler(priv, txq_id); @@ -480,7 +480,7 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); } int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index a3e1bd0abc28..cc3fc237d320 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -210,10 +210,10 @@ static int iwl_rx_init(struct iwl_priv *priv) iwl_trans_rx_hw_init(priv, rxq); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); rxq->need_update = 1; iwl_rx_queue_update_write_ptr(priv, rxq); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); return 0; } @@ -546,7 +546,7 @@ static int iwl_tx_init(struct iwl_priv *priv) alloc = true; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); /* Turn off all Tx DMA fifos */ iwl_write_prph(priv, SCD_TXFACT, 0); @@ -554,7 +554,7 @@ static int iwl_tx_init(struct iwl_priv *priv) /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { @@ -598,13 +598,13 @@ static int iwl_nic_init(struct iwl_priv *priv) unsigned long flags; /* nic_init */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_apm_init(priv); /* Set interrupt coalescing calibration timer to default (512 usecs) */ iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); iwl_set_pwr_vmain(priv); @@ -728,7 +728,7 @@ static int iwl_trans_start_device(struct iwl_priv *priv) /* * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access + * must be called under priv->shrd->lock and mac access */ static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) { @@ -777,7 +777,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) int i, chan; u32 reg_val; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; @@ -872,7 +872,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); /* Enable L1-Active */ iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, @@ -888,7 +888,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) unsigned long flags; /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_trans_txq_set_sched(priv, 0); @@ -902,7 +902,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) " DMA channel %d [0x%08x]", ch, iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); if (!priv->txq) { IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); @@ -924,9 +924,9 @@ static void iwl_trans_stop_device(struct iwl_priv *priv) iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->shrd->lock, flags); trans_sync_irq(&priv->trans); /* device going down, Stop using ICT table */ From 6ac2f839b0b21225a65f41802c5f0df5eff4f16c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:44 -0700 Subject: [PATCH 061/129] iwlagn: priv->mutex moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 12 +-- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 20 ++-- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 18 ++-- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 98 +++++++++---------- drivers/net/wireless/iwlwifi/iwl-core.c | 20 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 12 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 32 +++--- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 + drivers/net/wireless/iwlwifi/iwl-sta.c | 4 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 8 +- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 4 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 2 +- 16 files changed, 124 insertions(+), 122 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7ace5078cc99..a604baa1383e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -778,7 +778,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (vif) ctx = iwl_rxon_ctx_from_vif(vif); @@ -1165,7 +1165,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) { - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); ieee80211_stop_queues(priv->hw); if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { IWL_ERR(priv, "flush request fail\n"); @@ -1175,7 +1175,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) iwlagn_wait_tx_queue_empty(priv); done: ieee80211_wake_queues(priv->hw); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } /* @@ -1372,7 +1372,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) struct iwl_rxon_context *ctx, *found_ctx = NULL; bool found_ap = false; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* Check whether AP or GO mode is active. */ if (rssi_ena) { @@ -1485,7 +1485,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) break; } - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); /* * We can not send command to firmware while scanning. When the scan @@ -1513,7 +1513,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) */ iwlagn_bt_coex_rssi_monitor(priv); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index fadfc38b87bf..f0292fe9b4e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -132,7 +132,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv, struct ieee80211_vif *vif) { - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); @@ -316,7 +316,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; @@ -421,7 +421,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EINVAL; @@ -537,7 +537,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "changed %#x", changed); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); @@ -652,7 +652,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) iwlagn_commit_rxon(priv, ctx); } out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return ret; } @@ -667,7 +667,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap; bool need_multiple; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -792,17 +792,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, int ret; bool force = false; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (unlikely(!iwl_is_ready(priv))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return; } if (unlikely(!ctx->vif)) { IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return; } @@ -913,7 +913,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, IWL_ERR(priv, "Error sending IBSS beacon\n"); } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } void iwlagn_post_scan(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index f894bfb43da4..c99e6cce0733 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -49,7 +49,7 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) return NULL; } - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ @@ -197,7 +197,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); return iwl_send_static_wepkey_cmd(priv, ctx, false); } @@ -208,7 +208,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); @@ -232,7 +232,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { @@ -397,7 +397,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return 0; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); ctx->key_mapping_keys--; @@ -430,7 +430,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -EINVAL; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) @@ -572,7 +572,7 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) unsigned long flags; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* Remove "disable" flag, to enable Tx for this TID */ spin_lock_irqsave(&priv->sta_lock, flags); @@ -592,7 +592,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) @@ -617,7 +617,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 44fff5bf9dcd..03d8389d8ef8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -313,7 +313,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) tt->tt_power_mode = IWL_POWER_INDEX_5; break; } - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (old_state == IWL_TI_CT_KILL) clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && @@ -344,7 +344,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", tt->tt_power_mode); } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } } @@ -454,7 +454,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) * in case get disabled before */ iwl_set_rxon_ht(priv, &priv->current_ht_config); } - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (old_state == IWL_TI_CT_KILL) clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && @@ -489,7 +489,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) iwl_perform_ct_kill_task(priv, false); } } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 0fc123799d4e..3717a88cf45e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -545,7 +545,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* No init ucode required? Curious, but maybe ok */ if (!priv->ucode_init.code.len) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6d2c13e7f51b..ef60120d9bb9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -135,7 +135,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) * beacon contents. */ - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); @@ -209,7 +209,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "updating beacon w/o beacon context!\n"); goto out; @@ -239,7 +239,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwlagn_send_beacon_cmd(priv); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -262,7 +262,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) goto out; @@ -286,7 +286,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) iwlagn_send_advance_bt_config(priv); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } /** @@ -1920,9 +1920,9 @@ static void __iwl_down(struct iwl_priv *priv) static void iwl_down(struct iwl_priv *priv) { - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); __iwl_down(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); iwl_cancel_deferred_work(priv); } @@ -1934,7 +1934,7 @@ static int __iwl_up(struct iwl_priv *priv) struct iwl_rxon_context *ctx; int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); @@ -1989,11 +1989,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, run_time_calib_work); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || test_bit(STATUS_SCANNING, &priv->shrd->status)) { - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return; } @@ -2002,7 +2002,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) iwl_sensitivity_calibration(priv); } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static void iwlagn_prepare_restart(struct iwl_priv *priv) @@ -2014,7 +2014,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv) u8 bt_status; bool bt_is_sco; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); for_each_context(priv, ctx) ctx->vif = NULL; @@ -2052,9 +2052,9 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwlagn_prepare_restart(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { @@ -2256,9 +2256,9 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); ret = __iwl_up(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); if (ret) return ret; @@ -2351,7 +2351,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, if (iwlagn_mod_params.sw_crypto) return; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) goto out; @@ -2362,7 +2362,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, priv->have_rekey_data = true; out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } struct wowlan_key_data { @@ -2400,7 +2400,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, u16 p1k[IWLAGN_P1K_SIZE]; int ret, i; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && @@ -2505,7 +2505,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, break; } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static int iwlagn_mac_suspend(struct ieee80211_hw *hw, @@ -2530,7 +2530,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, if (WARN_ON(!wowlan)) return -EINVAL; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); /* Don't attempt WoWLAN when not associated, tear down instead. */ if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || @@ -2624,11 +2624,11 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * constraints. Since we're in the suspend path * that isn't really a problem though. */ - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); ieee80211_iter_keys(priv->hw, ctx->vif, iwlagn_wowlan_program_keys, &key_data); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (key_data.error) { ret = -EIO; goto error; @@ -2697,7 +2697,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); kfree(key_data.rsc_tsc); return ret; } @@ -2711,7 +2711,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) u32 base, status = 0xffffffff; int ret = -EIO; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); @@ -2755,7 +2755,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) iwl_connection_init_rx_config(priv, ctx); iwlagn_set_rxon_chain(priv, ctx); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); ieee80211_resume_disconnect(vif); @@ -2824,7 +2824,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) return 0; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_scan_cancel_timeout(priv, 100); BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); @@ -2875,7 +2875,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -2897,7 +2897,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)) return -EACCES; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -2988,7 +2988,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, ret = 0; break; } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return ret; } @@ -3006,7 +3006,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", sta->addr); sta_priv->common.sta_id = IWL_INVALID_STATION; @@ -3021,7 +3021,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return ret; } @@ -3031,7 +3031,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return 0; } @@ -3057,7 +3057,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (iwl_is_rfkill(priv)) goto out; @@ -3129,7 +3129,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, } out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -3159,7 +3159,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, #undef CHK - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; @@ -3171,7 +3171,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, */ } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); /* * Receiving all multicast frames is always enabled by the @@ -3187,7 +3187,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { @@ -3213,7 +3213,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); iwlagn_wait_tx_queue_empty(priv); done: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -3221,7 +3221,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (!priv->hw_roc_setup) return; @@ -3244,9 +3244,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, hw_roc_disable_work.work); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwlagn_disable_roc(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, @@ -3264,7 +3264,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) return -EOPNOTSUPP; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); /* * TODO: Remove this hack! Firmware needs to be updated @@ -3314,7 +3314,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, iwlagn_disable_roc(priv); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return err; } @@ -3326,10 +3326,10 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); iwlagn_disable_roc(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return 0; } @@ -3419,7 +3419,7 @@ static int iwl_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); - mutex_init(&priv->mutex); + mutex_init(&priv->shrd->mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; @@ -3492,7 +3492,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { @@ -3507,7 +3507,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, "ignoring RSSI callback\n"); } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } struct ieee80211_ops iwlagn_hw_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 40ad889264a9..bf173b6cd30b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -325,7 +325,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) conf = ieee80211_get_hw_conf(priv->hw); - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -1069,7 +1069,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) bool defer; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (priv->tx_power_user_lmt == tx_power && !force) return 0; @@ -1232,7 +1232,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; int err; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* * This variable will be correct only when there's just @@ -1276,7 +1276,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cancel_delayed_work_sync(&priv->hw_roc_disable_work); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwlagn_disable_roc(priv); @@ -1323,7 +1323,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1335,7 +1335,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv, { struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); @@ -1367,14 +1367,14 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); WARN_ON(ctx->vif != vif); ctx->vif = NULL; iwl_teardown_interface(priv, vif, false); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1698,7 +1698,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, newtype = ieee80211_iftype_p2p(newtype, newp2p); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (!ctx->vif || !iwl_is_ready_rf(priv)) { /* @@ -1762,7 +1762,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = 0; out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return err; } diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 8bd817759264..0aa84560dc2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -819,9 +819,9 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, priv->power_data.debug_sleep_level_override = value; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_power_update_mode(priv, true); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return count; } @@ -1838,9 +1838,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, return -EINVAL; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); if (ret) { IWL_ERR(priv, @@ -2231,9 +2231,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return -EFAULT; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_send_statistics_request(priv, CMD_SYNC, true); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return count; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c60a24232d6b..8ba2d94419e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1228,8 +1228,8 @@ struct iwl_priv { /* spinlock */ spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ - struct mutex mutex; + /*TODO: remove these pointers - use bus(priv) instead */ struct iwl_bus *bus; /* bus specific data */ struct iwl_trans trans; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 52a6f8aa5276..343317f6ce01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -383,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, int ret; bool update_chains; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index bc8cb1d3b555..fa100c5cefa3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -116,7 +116,7 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) void iwl_force_scan_end(struct iwl_priv *priv) { - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); @@ -134,7 +134,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); @@ -173,7 +173,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long timeout = jiffies + msecs_to_jiffies(ms); - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); @@ -358,7 +358,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); cancel_delayed_work(&priv->scan_check); @@ -413,7 +413,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, if (req->n_channels == 0) return -EINVAL; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (test_bit(STATUS_SCANNING, &priv->shrd->status) && priv->scan_type != IWL_SCAN_NORMAL) { @@ -440,7 +440,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return ret; } @@ -461,7 +461,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) IWL_DEBUG_SCAN(priv, "Start internal scan\n"); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); if (priv->scan_type == IWL_SCAN_RADIO_RESET) { IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); @@ -476,7 +476,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); unlock: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static void iwl_bg_scan_check(struct work_struct *data) @@ -489,9 +489,9 @@ static void iwl_bg_scan_check(struct work_struct *data) /* Since we are here firmware does not finish scan and * most likely is in bad shape, so we don't bother to * send abort command, just force scan complete to mac80211 */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } /** @@ -549,9 +549,9 @@ static void iwl_bg_abort_scan(struct work_struct *work) /* We keep scan_check work queued in case when firmware will not * report back scan completed notification */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_scan_cancel_timeout(priv, 200); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } static void iwl_bg_scan_completed(struct work_struct *work) @@ -564,7 +564,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) cancel_delayed_work(&priv->scan_check); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); if (aborted) @@ -612,7 +612,7 @@ out_settings: iwlagn_post_scan(priv); out: - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } void iwl_setup_scan_deferred_work(struct iwl_priv *priv) @@ -630,8 +630,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->scan_completed); if (cancel_delayed_work_sync(&priv->scan_check)) { - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 1c2c31c15f60..33953199ffc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -150,6 +150,7 @@ struct iwl_hw_params { * @hw_params: see struct iwl_hw_params * @workqueue: the workqueue used by all the layers of the driver * @lock: protect general shared data + * @mutex: */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -165,6 +166,7 @@ struct iwl_shared { struct workqueue_struct *workqueue; spinlock_t lock; + struct mutex mutex; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b5b0ff3d8890..63b434b0948b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -821,13 +821,13 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr); ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index b11f60de4f1e..ac751fa8b304 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -661,7 +661,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) return -ENOMSG; } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_UCODE: @@ -702,7 +702,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) break; } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return result; } @@ -738,7 +738,7 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); switch (cmd) { case IWL_TM_CMD_APP2DEV_READ_TRACE: IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); @@ -749,6 +749,6 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, break; } - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); return result; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 26497dd454a6..9c4bf8cd8771 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -349,9 +349,9 @@ void iwl_bg_rx_replenish(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; - mutex_lock(&priv->mutex); + mutex_lock(&priv->shrd->mutex); iwlagn_rx_replenish(priv); - mutex_unlock(&priv->mutex); + mutex_unlock(&priv->shrd->mutex); } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 61e17dd4f389..e1130a745ab6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -934,7 +934,7 @@ static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int cmd_idx; int ret; - lockdep_assert_held(&priv->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* A synchronous command can not have a callback set. */ if (WARN_ON(cmd->callback)) From 44856c6596bf4b96eb17ee5e785b5fe5b8a12531 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:45 -0700 Subject: [PATCH 062/129] iwlagn: modify the debug macro to be usable by all the layers Since all the layers need to print debug message, the debug macro cannot suppose that they will be given iwl_priv as a parameter and then dereference it. Use iwl_shared instead. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 37 ++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-rx.c | 3 +- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 225ae720c7d2..7c9e9af4a09d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -29,49 +29,50 @@ #ifndef __iwl_debug_h__ #define __iwl_debug_h__ +#include "iwl-shared.h" + struct iwl_priv; -#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) -#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) -#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) -#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) +/*No matter what is m (priv, bus, trans), this will work */ +#define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a) +#define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a) +#define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a) +#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a) -#define iwl_print_hex_error(priv, p, len) \ +#define iwl_print_hex_error(m, p, len) \ do { \ print_hex_dump(KERN_ERR, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(__priv, level, fmt, args...) \ +#define IWL_DEBUG(m, level, fmt, args...) \ do { \ - if (iwl_get_debug_level(__priv->shrd) & (level)) \ - dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ + if (iwl_get_debug_level((m)->shrd) & (level)) \ + dev_printk(KERN_ERR, bus(m)->dev, \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ +#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ do { \ - if ((iwl_get_debug_level(__priv->shrd) & (level)) && net_ratelimit())\ - dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ + if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\ + dev_printk(KERN_ERR, bus(m)->dev, \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define iwl_print_hex_dump(priv, level, p, len) \ +#define iwl_print_hex_dump(m, level, p, len) \ do { \ - if (iwl_get_debug_level(priv->shrd) & level) \ + if (iwl_get_debug_level((m)->shrd) & level) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #else -#define IWL_DEBUG(__priv, level, fmt, args...) -#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) -static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, - const void *p, u32 len) -{} +#define IWL_DEBUG(m, level, fmt, args...) +#define IWL_DEBUG_LIMIT(m, level, fmt, args...) +#define iwl_print_hex_dump(m, level, p, len) #endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 37bc017b80ac..a5e4ddad2e04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -122,7 +122,8 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + u32 __maybe_unused len = + le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", len, get_cmd_string(pkt->hdr.cmd)); From 9ca06f0a3fbf57c672c7f2cdfc85747a0bbfaf28 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:46 -0700 Subject: [PATCH 063/129] iwlagn: add IWL_DEBUG_FW_ERRORS instead of IWL_DEBUG(priv, IWL_DL_FW_ERRORS Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bf173b6cd30b..9857136627f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -893,11 +893,11 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { if (iwlagn_mod_params.restart_fw) { - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, + IWL_DEBUG_FW_ERRORS(priv, "Restarting adapter due to uCode error.\n"); queue_work(priv->shrd->workqueue, &priv->restart); } else - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, + IWL_DEBUG_FW_ERRORS(priv, "Detected FW error, but not restarting\n"); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 7c9e9af4a09d..4b042e91f65c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -166,6 +166,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) +#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a) #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) From f39c95e8d7a152b409977687a999356f0e54bde6 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:47 -0700 Subject: [PATCH 064/129] iwlagn: priv->sta_lock moves to iwl_shared Since it is used by all the layers, it needs to move to iwl_shared. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 50 ++++++------ drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 26 +++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 - drivers/net/wireless/iwlwifi/iwl-shared.h | 3 + drivers/net/wireless/iwlwifi/iwl-sta.c | 77 ++++++++++--------- drivers/net/wireless/iwlwifi/iwl-sta.h | 4 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 4 +- 9 files changed, 90 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a604baa1383e..bf2ba98e767a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -427,7 +427,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> IWLAGN_TX_RES_RA_POS; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); hdr = (void *)txb->skb->data; if (!ieee80211_is_data_qos(hdr->frame_control)) @@ -482,7 +482,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); iwl_check_abort_status(priv, tx_resp->frame_count, status); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } int iwlagn_hw_valid_rtc_data_addr(u32 addr) @@ -1079,7 +1079,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed) { - lockdep_assert_held(&priv->sta_lock); + lockdep_assert_held(&priv->shrd->sta_lock); if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index c99e6cce0733..4b13bb9df999 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -116,9 +116,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (sta_id_r) *sta_id_r = sta_id; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_LOCAL; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); /* Set up default rate scaling table in device's station table */ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); @@ -132,9 +132,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (ret) IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return 0; } @@ -311,9 +311,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv, struct iwl_addsta_cmd sta_cmd; int i; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags |= STA_KEY_FLG_MAP_KEY_MSK; @@ -388,11 +388,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -ENOENT; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) sta_id = IWL_INVALID_STATION; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); if (sta_id == IWL_INVALID_STATION) return 0; @@ -493,18 +493,18 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, unsigned long flags; u8 sta_id; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare broadcast station\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return -EINVAL; } priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_BCAST; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); if (!link_cmd) { @@ -513,9 +513,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return 0; } @@ -539,13 +539,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); if (priv->stations[sta_id].lq) kfree(priv->stations[sta_id].lq); else IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return 0; } @@ -575,12 +575,12 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) lockdep_assert_held(&priv->shrd->mutex); /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -598,14 +598,14 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, if (sta_id == IWL_INVALID_STATION) return -ENXIO; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -625,13 +625,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return -ENXIO; } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -640,14 +640,14 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = 0; priv->stations[sta_id].sta.sleep_tx_count = 0; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } @@ -655,7 +655,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) { unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = @@ -663,7 +663,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 89d7b30525f9..d0d77106da9a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -405,7 +405,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; /* irqs already disabled/saved above when locking priv->shrd->lock */ - spin_lock(&priv->sta_lock); + spin_lock(&priv->shrd->sta_lock); if (ieee80211_is_data_qos(fc)) { u8 *qc = NULL; @@ -460,7 +460,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) priv->stations[sta_id].tid[tid].seq_number = seq_number; } - spin_unlock(&priv->sta_lock); + spin_unlock(&priv->shrd->sta_lock); spin_unlock_irqrestore(&priv->shrd->lock, flags); /* @@ -476,7 +476,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) return 0; drop_unlock_sta: - spin_unlock(&priv->sta_lock); + spin_unlock(&priv->shrd->sta_lock); drop_unlock_priv: spin_unlock_irqrestore(&priv->shrd->lock, flags); return -1; @@ -534,19 +534,19 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; tid_data->agg.tx_fifo = tx_fifo; iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); if (ret) return ret; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); @@ -557,7 +557,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data->tfds_in_queue); tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; } - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return ret; } @@ -580,7 +580,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; @@ -610,7 +610,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); priv->stations[sta_id].tid[tid].agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return 0; } @@ -619,7 +619,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; /* do not restore/save irqs */ - spin_unlock(&priv->sta_lock); + spin_unlock(&priv->shrd->sta_lock); spin_lock(&priv->shrd->lock); /* @@ -647,7 +647,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, ctx = &priv->contexts[priv->stations[sta_id].ctxid]; - lockdep_assert_held(&priv->sta_lock); + lockdep_assert_held(&priv->shrd->sta_lock); switch (priv->stations[sta_id].tid[tid].agg.state) { case IWL_EMPTYING_HW_QUEUE_DELBA: @@ -890,7 +890,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, /* Find index just before block-ack window */ index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", @@ -927,7 +927,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); } - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ef60120d9bb9..cab3f63f4e4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3416,7 +3416,7 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->shrd->sta_lock); spin_lock_init(&priv->hcmd_lock); mutex_init(&priv->shrd->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8ba2d94419e5..fa92975b6a89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1307,9 +1307,6 @@ struct iwl_priv { struct iwl_tt_mgmt thermal_throttle; /* station table variables */ - - /* Note: if lock and sta_lock are needed, lock must be acquired first */ - spinlock_t sta_lock; int num_stations; struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; unsigned long ucode_key_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 33953199ffc6..71496bf05104 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -150,6 +150,8 @@ struct iwl_hw_params { * @hw_params: see struct iwl_hw_params * @workqueue: the workqueue used by all the layers of the driver * @lock: protect general shared data + * @sta_lock: protects the station table. + * If lock and sta_lock are needed, lock must be acquired first. * @mutex: */ struct iwl_shared { @@ -166,6 +168,7 @@ struct iwl_shared { struct workqueue_struct *workqueue; spinlock_t lock; + spinlock_t sta_lock; struct mutex mutex; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 63b434b0948b..9424d79b9d65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -38,7 +38,7 @@ #include "iwl-trans.h" #include "iwl-agn.h" -/* priv->sta_lock must be held */ +/* priv->shrd->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { @@ -75,7 +75,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", sta_id); - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: @@ -118,7 +118,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, priv->stations[sta_id].sta.mode == STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr); - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return ret; } @@ -337,12 +337,12 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_addsta_cmd sta_cmd; *sta_id_r = 0; - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); return -EINVAL; } @@ -354,7 +354,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", sta_id); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); return -EEXIST; } @@ -362,23 +362,23 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", sta_id, addr); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); return -EEXIST; } priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); /* Add station to device's station table */ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); } *sta_id_r = sta_id; return ret; @@ -387,7 +387,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station * - * priv->sta_lock must be held + * priv->shrd->sta_lock must be held */ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) { @@ -441,9 +441,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv, switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: if (!temporary) { - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, + flags_spin); iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, + flags_spin); } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; @@ -484,7 +486,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(sta_id == IWL_INVALID_STATION)) return -EINVAL; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", @@ -510,11 +512,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(priv->num_stations < 0)) priv->num_stations = 0; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return iwl_send_remove_station(priv, addr, sta_id, false); out_err: - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return -EINVAL; } @@ -535,7 +537,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); for (i = 0; i < hw_params(priv).max_stations; i++) { if (ctx && ctx->ctxid != priv->stations[i].ctxid) continue; @@ -546,7 +548,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, cleared = true; } } - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); if (!cleared) IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); @@ -576,7 +578,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); for (i = 0; i < hw_params(priv).max_stations; i++) { if (ctx->ctxid != priv->stations[i].ctxid) continue; @@ -600,15 +602,18 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) sizeof(struct iwl_link_quality_cmd)); send_lq = true; } - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, + flags_spin); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, + flags_spin); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[i].sta.sta.addr); priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, + flags_spin); } /* * Rate scaling has already been initialized, send @@ -616,12 +621,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) */ if (send_lq) iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } } - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); if (!found) IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); else @@ -637,9 +642,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) struct iwl_link_quality_cmd lq; bool active; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return; } @@ -649,7 +654,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); if (active) { ret = iwl_send_remove_station( @@ -659,9 +664,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_ERR(priv, "failed to remove STA %pM (%d)\n", priv->stations[sta_id].sta.sta.addr, ret); } - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) @@ -686,7 +691,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) unsigned long flags; int i; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); for (i = 0; i < hw_params(priv).max_stations; i++) { if (!(priv->stations[i].used & IWL_STA_BCAST)) continue; @@ -698,7 +703,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } #ifdef CONFIG_IWLWIFI_DEBUG @@ -782,12 +787,12 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); return -EINVAL; } - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); iwl_dump_lq_cmd(priv, lq); if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) @@ -804,9 +809,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (init) { IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", lq->sta_id); - spin_lock_irqsave(&priv->sta_lock, flags_spin); + spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); } return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 9a6768d66851..9641eb6b1d0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -76,7 +76,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) unsigned long flags; struct iwl_rxon_context *ctx; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); memset(priv->stations, 0, sizeof(priv->stations)); priv->num_stations = 0; @@ -94,7 +94,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) ctx->key_mapping_keys = 0; } - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } static inline int iwl_sta_id(struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index e1130a745ab6..b0ad127715f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -435,12 +435,12 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, if (WARN_ON(tid >= MAX_TID_COUNT)) return; - spin_lock_irqsave(&priv->sta_lock, flags); + spin_lock_irqsave(&priv->shrd->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; tx_fifo = tid_data->agg.tx_fifo; - spin_unlock_irqrestore(&priv->sta_lock, flags); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); ra_tid = BUILD_RAxTID(sta_id, tid); From e6bb4c9c00892c488f3218ea317dc6a71674faf4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:48 -0700 Subject: [PATCH 065/129] iwlagn: bus layer chooses its transport layer Remove iwl_transport_register which was a W/A. The bus layer knows what transport to use. So now, the bus layer gives the upper layer a pointer to the iwl_trans_ops struct that it wants to use. The upper layer then, allocates the desired transport layer using iwl_trans_ops->alloc function. As a result of this, priv->trans, no longer exists, priv holds a pointer to iwl_shared, which holds a pointer to iwl_trans. This required to change all the calls to the transport layer from upper layer. While we were at it, trans_X inlines have been renamed to iwl_trans_X to avoid confusions, which of course required to rename the functions inside the transport layer because of conflicts in names. So the static API functions inside the transport layer implementation have been renamed to iwl_trans_pcie_X. Until now, the IRQ / Tasklet were initialized in iwl_transport_layer. This is confusing since the registration doesn't mean to request IRQ, so I added a handler for that. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 16 +-- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 16 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 51 ++++--- drivers/net/wireless/iwlwifi/iwl-bus.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 7 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 9 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 4 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 16 ++- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 12 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 133 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-trans.h | 83 ++++++----- 24 files changed, 230 insertions(+), 174 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index feefb5b0987c..6048b3b8cd6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -315,7 +315,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(&priv->trans, &hcmd); + return iwl_trans_send_cmd(trans(priv), &hcmd); } static struct iwl_lib_ops iwl5000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index e7be968b1784..9487d9b550ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -256,7 +256,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(&priv->trans, &hcmd); + return iwl_trans_send_cmd(trans(priv), &hcmd); } static struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index fb6da14bef4e..b725f6970dee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -98,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = trans_send_cmd(&priv->trans, &hcmd); + ret = iwl_trans_send_cmd(trans(priv), &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", ret, i); @@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return trans_send_cmd(&priv->trans, &cmd_out); + return iwl_trans_send_cmd(trans(priv), &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -573,7 +573,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return trans_send_cmd(&priv->trans, &cmd_out); + return iwl_trans_send_cmd(trans(priv), &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -918,7 +918,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, priv->phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; - trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, + iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD, CMD_ASYNC, sizeof(cmd), &cmd); data->radio_write = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index bf2ba98e767a..82fb55bc0b28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -526,7 +526,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, + return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -1054,7 +1054,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (ret) return ret; - ret = trans_send_cmd(&priv->trans, &cmd); + ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret) { clear_bit(STATUS_SCAN_HW, &priv->shrd->status); iwlagn_set_pan_params(priv); @@ -1160,7 +1160,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) @@ -1354,12 +1354,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (priv->cfg->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index f0292fe9b4e6..991977e2e1b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -41,7 +41,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -67,7 +67,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -93,7 +93,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -122,7 +122,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -181,7 +181,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -267,7 +267,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, + ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -388,7 +388,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[1].width = cpu_to_le16(slot1); - ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); @@ -771,7 +771,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, priv->phy_calib_chain_noise_reset_cmd); - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 4b13bb9df999..4d02c328c377 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -189,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); else return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index d0d77106da9a..0e9deb7b64d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -429,7 +429,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } } - tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id); + tx_cmd = iwl_trans_get_tx_cmd(trans(priv), txq_id); if (unlikely(!tx_cmd)) goto drop_unlock_sta; @@ -451,7 +451,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx)) + if (iwl_trans_tx(trans(priv), skb, tx_cmd, txq_id, fc, is_agg, ctx)) goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { @@ -629,7 +629,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); + iwl_trans_txq_agg_disable(trans(priv), txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->shrd->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -658,7 +658,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - trans_txq_agg_disable(&priv->trans, txq_id, + iwl_trans_txq_agg_disable(trans(priv), txq_id, ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 3717a88cf45e..a094b66541b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -193,7 +193,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -291,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return trans_send_cmd_pdu(&priv->trans, + return iwl_trans_send_cmd_pdu(trans(priv), COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -324,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, sizeof(iwlagn_bt_prio_tbl)); - if (trans_send_cmd_pdu(&priv->trans, + if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) IWL_ERR(priv, "failed to send BT prio tbl command\n"); @@ -337,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) @@ -350,7 +350,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) { int ret; - trans_tx_start(&priv->trans); + iwl_trans_tx_start(trans(priv)); ret = iwlagn_send_wimax_coex(priv); if (ret) @@ -478,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = trans_start_device(&priv->trans); + ret = iwl_trans_start_device(trans(priv)); if (ret) return ret; @@ -495,7 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - trans_kick_nic(&priv->trans); + iwl_trans_kick_nic(trans(priv)); /* * Some things may run in the background now, but we @@ -580,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - trans_stop_device(&priv->trans); + iwl_trans_stop_device(trans(priv)); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cab3f63f4e4e..fcbc3b1d0584 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -200,7 +200,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -1685,7 +1685,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) adv_cmd.critical_temperature_exit = cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) @@ -1700,7 +1700,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) cmd.critical_temperature_R = cpu_to_le32(hw_params(priv).ct_kill_threshold); - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -1726,7 +1726,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } @@ -1738,7 +1738,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) if (IWL_UCODE_API(priv->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return trans_send_cmd_pdu(&priv->trans, + return iwl_trans_send_cmd_pdu(trans(priv), TX_ANT_CONFIGURATION_CMD, CMD_SYNC, sizeof(struct iwl_tx_ant_config_cmd), @@ -1912,7 +1912,7 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << STATUS_EXIT_PENDING; - trans_stop_device(&priv->trans); + iwl_trans_stop_device(trans(priv)); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -2336,7 +2336,7 @@ static int iwlagn_send_patterns(struct iwl_priv *priv, } cmd.data[0] = pattern_cmd; - err = trans_send_cmd(&priv->trans, &cmd); + err = iwl_trans_send_cmd(trans(priv), &cmd); kfree(pattern_cmd); return err; } @@ -2591,7 +2591,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, memcpy(&rxon, &ctx->active, sizeof(rxon)); - trans_stop_device(&priv->trans); + iwl_trans_stop_device(trans(priv)); priv->wowlan = true; @@ -2643,13 +2643,13 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, .len[0] = sizeof(*key_data.rsc_tsc), }; - ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd); + ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); if (ret) goto error; } if (key_data.use_tkip) { - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_TKIP_PARAMS, CMD_SYNC, sizeof(tkip_cmd), &tkip_cmd); @@ -2665,7 +2665,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); kek_kck_cmd.replay_ctr = priv->replay_ctr; - ret = trans_send_cmd_pdu(&priv->trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_KEK_KCK_MATERIAL, CMD_SYNC, sizeof(kek_kck_cmd), &kek_kck_cmd); @@ -2674,7 +2674,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, } } - ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, CMD_SYNC, sizeof(wakeup_filter_cmd), &wakeup_filter_cmd); if (ret) @@ -2943,7 +2943,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid, + iwl_trans_txq_agg_setup(trans(priv), iwl_sta_id(sta), tid, buf_size); /* @@ -3590,7 +3590,8 @@ out: return hw; } -int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) +int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, + struct iwl_cfg *cfg) { int err = 0; struct iwl_priv *priv; @@ -3614,6 +3615,12 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) priv->shrd->priv = priv; bus_set_drv_data(priv->bus, priv->shrd); + priv->shrd->trans = trans_ops->alloc(priv->shrd); + if (priv->shrd->trans == NULL) { + err = -ENOMEM; + goto out_free_traffic_mem; + } + /* At this point both hw and priv are allocated. */ SET_IEEE80211_DEV(hw, priv->bus->dev); @@ -3656,11 +3663,11 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - err = iwl_trans_register(&priv->trans, priv); + err = iwl_trans_request_irq(trans(priv)); if (err) - goto out_free_traffic_mem; + goto out_free_trans; - if (trans_prepare_card_hw(&priv->trans)) { + if (iwl_trans_prepare_card_hw(trans(priv))) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); goto out_free_trans; @@ -3754,7 +3761,7 @@ out_destroy_workqueue: out_free_eeprom: iwl_eeprom_free(priv); out_free_trans: - trans_free(&priv->trans); + iwl_trans_free(trans(priv)); out_free_traffic_mem: iwl_free_traffic_mem(priv); ieee80211_free_hw(priv->hw); @@ -3800,12 +3807,12 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->shrd->lock, flags); - trans_sync_irq(&priv->trans); + iwl_trans_sync_irq(trans(priv)); iwl_dealloc_ucode(priv); - trans_rx_free(&priv->trans); - trans_tx_free(&priv->trans); + iwl_trans_rx_free(trans(priv)); + iwl_trans_tx_free(trans(priv)); iwl_eeprom_free(priv); @@ -3819,7 +3826,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->shrd->workqueue = NULL; iwl_free_traffic_mem(priv); - trans_free(&priv->trans); + iwl_trans_free(trans(priv)); bus_set_drv_data(priv->bus, NULL); diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index a69800485c5c..5d0e155a6ee9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -89,7 +89,7 @@ struct iwl_bus_ops { struct iwl_bus { /* Common data to all buses */ struct device *dev; - struct iwl_bus_ops *ops; + const struct iwl_bus_ops *ops; struct iwl_shared *shrd; unsigned int irq; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9857136627f3..b5e99a66613e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -378,7 +378,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, + return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -1135,7 +1135,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, + if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -1148,12 +1148,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, + return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, + return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fa92975b6a89..4f65b0980a1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1231,7 +1231,6 @@ struct iwl_priv { /*TODO: remove these pointers - use bus(priv) instead */ struct iwl_bus *bus; /* bus specific data */ - struct iwl_trans trans; /* microcode/device supports multiple contexts */ u8 valid_contexts; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 53b69ed704ff..4bc7389b1a6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } /* Set led pattern command */ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 3b7efd7fee3d..521d7e265c2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -66,6 +66,7 @@ #include "iwl-bus.h" #include "iwl-shared.h" #include "iwl-agn.h" +#include "iwl-trans.h" /* TODO: iwl_set_bit and friends should be implemented in bus layer * this would allow us not to include iwl-io.h here */ @@ -165,7 +166,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) return val; } -static struct iwl_bus_ops pci_ops = { +static const struct iwl_bus_ops bus_ops_pci = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .set_drv_data = iwl_pci_set_drv_data, @@ -460,9 +461,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bus->dev = &pdev->dev; bus->irq = pdev->irq; - bus->ops = &pci_ops; + bus->ops = &bus_ops_pci; - err = iwl_probe(bus, cfg); + err = iwl_probe(bus, &trans_ops_pcie, cfg); if (err) goto out_disable_msi; return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 343317f6ce01..5ecb11e42e4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -336,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, + return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fa100c5cefa3..1a0cb66d7bae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -75,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EIO; - ret = trans_send_cmd(&priv->trans, &cmd); + ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 71496bf05104..467cfaacd698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -63,10 +63,14 @@ #ifndef __iwl_shared_h__ #define __iwl_shared_h__ +/*This files includes all the types / functions that are exported by the + * upper layer to the bus and transport layer */ + struct iwl_cfg; struct iwl_bus; struct iwl_priv; struct iwl_sensitivity_ranges; +struct iwl_trans_ops; extern struct iwl_mod_params iwlagn_mod_params; @@ -164,6 +168,7 @@ struct iwl_shared { struct iwl_bus *bus; struct iwl_priv *priv; + struct iwl_trans *trans; struct iwl_hw_params hw_params; struct workqueue_struct *workqueue; @@ -175,6 +180,7 @@ struct iwl_shared { /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ #define priv(_m) ((_m)->shrd->priv) #define bus(_m) ((_m)->shrd->bus) +#define trans(_m) ((_m)->shrd->trans) #define hw_params(_m) ((_m)->shrd->hw_params) #ifdef CONFIG_IWLWIFI_DEBUG @@ -204,7 +210,8 @@ int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); #endif /* !CONFIG_PM */ -int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); +int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, + struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); #endif /* #__iwl_shared_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9424d79b9d65..d4c625c13119 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); - ret = trans_send_cmd(&priv->trans, &cmd); + ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -425,7 +425,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = trans_send_cmd(&priv->trans, &cmd); + ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret) return ret; @@ -799,7 +799,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = trans_send_cmd(&priv->trans, &cmd); + ret = iwl_trans_send_cmd(trans(priv), &cmd); else ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index ac751fa8b304..4d4358ae69a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -239,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ - return trans_send_cmd(&priv->trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } @@ -405,7 +405,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - trans_stop_device(&priv->trans); + iwl_trans_stop_device(trans(priv)); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index b79330d84185..2bc421b43a91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -32,6 +32,12 @@ /*This file includes the declaration that are internal to the * trans_pcie layer */ +/** + * struct iwl_trans_pcie - PCIe transport specific data + */ +struct iwl_trans_pcie { +}; + /***************************************************** * RX ******************************************************/ @@ -62,21 +68,21 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, dma_addr_t addr, u16 len, u8 reset); int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, int count, int slots_num, u32 id); -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, - u16 len, const void *data); +int iwl_trans_pcie_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, + u32 flags, u16 len, const void *data); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt); -int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, +int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index); void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, +void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 9c4bf8cd8771..6f5edf731542 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -443,7 +443,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) if (reclaim) { /* Invoke any callbacks, transfer the buffer to caller, * and fire off the (possibly) blocking - * trans_send_cmd() + * iwl_trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) iwl_tx_cmd_complete(priv, rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index b0ad127715f6..9d7287e7a992 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -422,7 +422,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, +void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit) { int tx_fifo, txq_id, ssn_idx; @@ -483,7 +483,7 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, spin_unlock_irqrestore(&priv->shrd->lock, flags); } -int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, +int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || @@ -1015,7 +1015,7 @@ fail: return ret; } -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +int iwl_trans_pcie_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { if (cmd->flags & CMD_ASYNC) return iwl_send_cmd_async(priv, cmd); @@ -1023,8 +1023,8 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return iwl_send_cmd_sync(priv, cmd); } -int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, - const void *data) +int iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, + u16 len, const void *data) { struct iwl_host_cmd cmd = { .id = id, @@ -1033,5 +1033,5 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, .flags = flags, }; - return iwl_send_cmd(priv, &cmd); + return iwl_trans_pcie_send_cmd(priv, &cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index cc3fc237d320..739087f3025c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -60,6 +60,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +#include + #include "iwl-dev.h" #include "iwl-trans.h" #include "iwl-core.h" @@ -218,7 +220,7 @@ static int iwl_rx_init(struct iwl_priv *priv) return 0; } -static void iwl_trans_rx_free(struct iwl_priv *priv) +static void iwl_trans_pcie_rx_free(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; unsigned long flags; @@ -453,7 +455,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) * * Destroy all TX DMA queues and structures */ -static void iwl_trans_tx_free(struct iwl_priv *priv) +static void iwl_trans_pcie_tx_free(struct iwl_priv *priv) { int txq_id; @@ -528,7 +530,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) return 0; error: - trans_tx_free(&priv->trans); + iwl_trans_tx_free(trans(priv)); return ret; } @@ -572,7 +574,7 @@ static int iwl_tx_init(struct iwl_priv *priv) error: /*Upon error, free only if we allocated something */ if (alloc) - trans_tx_free(&priv->trans); + iwl_trans_tx_free(trans(priv)); return ret; } @@ -649,7 +651,7 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) } /* Note: returns standard 0/-ERROR code */ -static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) +static int iwl_trans_pcie_prepare_card_hw(struct iwl_priv *priv) { int ret; @@ -677,14 +679,14 @@ static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) return ret; } -static int iwl_trans_start_device(struct iwl_priv *priv) +static int iwl_trans_pcie_start_device(struct iwl_priv *priv) { int ret; priv->ucode_owner = IWL_OWNERSHIP_DRIVER; if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_trans_prepare_card_hw(priv)) { + iwl_trans_pcie_prepare_card_hw(priv)) { IWL_WARN(priv, "Exit HW not ready\n"); return -EIO; } @@ -768,7 +770,7 @@ static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, }; -static void iwl_trans_tx_start(struct iwl_priv *priv) +static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_rxon_context *ctx; @@ -916,7 +918,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) return 0; } -static void iwl_trans_stop_device(struct iwl_priv *priv) +static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) { unsigned long flags; @@ -927,7 +929,7 @@ static void iwl_trans_stop_device(struct iwl_priv *priv) spin_lock_irqsave(&priv->shrd->lock, flags); iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->shrd->lock, flags); - trans_sync_irq(&priv->trans); + iwl_trans_sync_irq(trans(priv)); /* device going down, Stop using ICT table */ iwl_disable_ict(priv); @@ -956,7 +958,7 @@ static void iwl_trans_stop_device(struct iwl_priv *priv) iwl_apm_stop(priv); } -static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, +static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_priv *priv, int txq_id) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; @@ -980,7 +982,7 @@ static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, return &dev_cmd->cmd.tx; } -static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, +static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx) { @@ -1109,63 +1111,23 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } -static void iwl_trans_kick_nic(struct iwl_priv *priv) +static void iwl_trans_pcie_kick_nic(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ iwl_write32(priv, CSR_RESET, 0); } -static void iwl_trans_sync_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus->irq); - tasklet_kill(&priv->irq_tasklet); -} - -static void iwl_trans_free(struct iwl_priv *priv) -{ - free_irq(priv->bus->irq, priv); - iwl_free_isr_ict(priv); -} - -static const struct iwl_trans_ops trans_ops = { - .start_device = iwl_trans_start_device, - .prepare_card_hw = iwl_trans_prepare_card_hw, - .stop_device = iwl_trans_stop_device, - - .tx_start = iwl_trans_tx_start, - - .rx_free = iwl_trans_rx_free, - .tx_free = iwl_trans_tx_free, - - .send_cmd = iwl_send_cmd, - .send_cmd_pdu = iwl_send_cmd_pdu, - - .get_tx_cmd = iwl_trans_get_tx_cmd, - .tx = iwl_trans_tx, - - .txq_agg_disable = iwl_trans_txq_agg_disable, - .txq_agg_setup = iwl_trans_txq_agg_setup, - - .kick_nic = iwl_trans_kick_nic, - - .sync_irq = iwl_trans_sync_irq, - .free = iwl_trans_free, -}; - -int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) +static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) { + struct iwl_priv *priv = priv(trans); int err; - priv->trans.ops = &trans_ops; - priv->trans.priv = priv; - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl_irq_tasklet, (unsigned long)priv); iwl_alloc_isr_ict(priv); - err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED, + err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); @@ -1174,6 +1136,63 @@ int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) } INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); - return 0; } + +static void iwl_trans_pcie_sync_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus->irq); + tasklet_kill(&priv->irq_tasklet); +} + +static void iwl_trans_pcie_free(struct iwl_priv *priv) +{ + free_irq(priv->bus->irq, priv); + iwl_free_isr_ict(priv); + kfree(trans(priv)); + trans(priv) = NULL; +} + +const struct iwl_trans_ops trans_ops_pcie; + +static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) +{ + struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + + sizeof(struct iwl_trans_pcie), + GFP_KERNEL); + if (iwl_trans) { + iwl_trans->ops = &trans_ops_pcie; + iwl_trans->shrd = shrd; + } + + return iwl_trans; +} + +const struct iwl_trans_ops trans_ops_pcie = { + .alloc = iwl_trans_pcie_alloc, + .request_irq = iwl_trans_pcie_request_irq, + .start_device = iwl_trans_pcie_start_device, + .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, + .stop_device = iwl_trans_pcie_stop_device, + + .tx_start = iwl_trans_pcie_tx_start, + + .rx_free = iwl_trans_pcie_rx_free, + .tx_free = iwl_trans_pcie_tx_free, + + .send_cmd = iwl_trans_pcie_send_cmd, + .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, + + .get_tx_cmd = iwl_trans_pcie_get_tx_cmd, + .tx = iwl_trans_pcie_tx, + + .txq_agg_disable = iwl_trans_pcie_txq_agg_disable, + .txq_agg_setup = iwl_trans_pcie_txq_agg_setup, + + .kick_nic = iwl_trans_pcie_kick_nic, + + .sync_irq = iwl_trans_pcie_sync_irq, + .free = iwl_trans_pcie_free, +}; + diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7993aa7ae668..eec25b424def 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -69,9 +69,12 @@ struct iwl_priv; struct iwl_rxon_context; struct iwl_host_cmd; +struct iwl_shared; /** * struct iwl_trans_ops - transport specific operations + * @alloc: allocates the meta data (not the queues themselves) + * @request_irq: requests IRQ - will be called before the FW load in probe flow * @start_device: allocates and inits all the resources for the transport * layer. * @prepare_card_hw: claim the ownership on the HW. Will be called during @@ -98,6 +101,8 @@ struct iwl_host_cmd; */ struct iwl_trans_ops { + struct iwl_trans *(*alloc)(struct iwl_shared *shrd); + int (*request_irq)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_priv *priv); int (*prepare_card_hw)(struct iwl_priv *priv); void (*stop_device)(struct iwl_priv *priv); @@ -127,93 +132,105 @@ struct iwl_trans_ops { struct iwl_trans { const struct iwl_trans_ops *ops; - struct iwl_priv *priv; + struct iwl_shared *shrd; + + /* pointer to trans specific struct */ + /*Ensure that this pointer will always be aligned to sizeof pointer */ + char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); }; -static inline int trans_start_device(struct iwl_trans *trans) +static inline int iwl_trans_request_irq(struct iwl_trans *trans) { - return trans->ops->start_device(trans->priv); + return trans->ops->request_irq(trans); } -static inline int trans_prepare_card_hw(struct iwl_trans *trans) +static inline int iwl_trans_start_device(struct iwl_trans *trans) { - return trans->ops->prepare_card_hw(trans->priv); + return trans->ops->start_device(priv(trans)); } -static inline void trans_stop_device(struct iwl_trans *trans) +static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) { - trans->ops->stop_device(trans->priv); + return trans->ops->prepare_card_hw(priv(trans)); } -static inline void trans_tx_start(struct iwl_trans *trans) +static inline void iwl_trans_stop_device(struct iwl_trans *trans) { - trans->ops->tx_start(trans->priv); + trans->ops->stop_device(priv(trans)); } -static inline void trans_rx_free(struct iwl_trans *trans) +static inline void iwl_trans_tx_start(struct iwl_trans *trans) { - trans->ops->rx_free(trans->priv); + trans->ops->tx_start(priv(trans)); } -static inline void trans_tx_free(struct iwl_trans *trans) +static inline void iwl_trans_rx_free(struct iwl_trans *trans) { - trans->ops->tx_free(trans->priv); + trans->ops->rx_free(priv(trans)); } -static inline int trans_send_cmd(struct iwl_trans *trans, +static inline void iwl_trans_tx_free(struct iwl_trans *trans) +{ + trans->ops->tx_free(priv(trans)); +} + +static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return trans->ops->send_cmd(trans->priv, cmd); + return trans->ops->send_cmd(priv(trans), cmd); } -static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, - u16 len, const void *data) +static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, + u32 flags, u16 len, const void *data) { - return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); + return trans->ops->send_cmd_pdu(priv(trans), id, flags, len, data); } -static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, +static inline struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_trans *trans, int txq_id) { - return trans->ops->get_tx_cmd(trans->priv, txq_id); + return trans->ops->get_tx_cmd(priv(trans), txq_id); } -static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, +static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx) { - return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); + return trans->ops->tx(priv(trans), skb, tx_cmd, txq_id, fc, ampdu, ctx); } -static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, +static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { - return trans->ops->txq_agg_disable(trans->priv, txq_id, + return trans->ops->txq_agg_disable(priv(trans), txq_id, ssn_idx, tx_fifo); } -static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, +static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, int tid, int frame_limit) { - trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); + trans->ops->txq_agg_setup(priv(trans), sta_id, tid, frame_limit); } -static inline void trans_kick_nic(struct iwl_trans *trans) +static inline void iwl_trans_kick_nic(struct iwl_trans *trans) { - trans->ops->kick_nic(trans->priv); + trans->ops->kick_nic(priv(trans)); } -static inline void trans_sync_irq(struct iwl_trans *trans) +static inline void iwl_trans_sync_irq(struct iwl_trans *trans) { - trans->ops->sync_irq(trans->priv); + trans->ops->sync_irq(priv(trans)); } -static inline void trans_free(struct iwl_trans *trans) +static inline void iwl_trans_free(struct iwl_trans *trans) { - trans->ops->free(trans->priv); + trans->ops->free(priv(trans)); } -int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); +/***************************************************** +* Transport layers implementations +******************************************************/ +extern const struct iwl_trans_ops trans_ops_pcie; /*TODO: this functions should NOT be exported from trans module - export it * until the reclaim flow will be brought to the transport module too */ From 6fbfae8e65139061080c70c8c337f74c50e8fd55 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:49 -0700 Subject: [PATCH 066/129] iwlagn: add comments to iwl_bus / iwl_trans Rename the recursive inclusion protection in iwl-bus.h while we are at it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-bus.h | 15 ++++++++++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 5d0e155a6ee9..edec2f2647d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -60,8 +60,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#ifndef __iwl_pci_h__ -#define __iwl_pci_h__ +#ifndef __iwl_bus_h__ +#define __iwl_bus_h__ + +/*This file includes the declaration that are exported from the bus layer */ struct iwl_shared; struct iwl_bus; @@ -86,6 +88,13 @@ struct iwl_bus_ops { u32 (*read32)(struct iwl_bus *bus, u32 ofs); }; +/** + * struct iwl_bus - bus common data + * @dev - pointer to struct device * that represent the device + * @ops - pointer to iwl_bus_ops + * @shrd - pointer to iwl_shared which holds shared data from the upper layer + * @irq - the irq number for the device + */ struct iwl_bus { /* Common data to all buses */ struct device *dev; @@ -138,4 +147,4 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) int __must_check iwl_pci_register_driver(void); void iwl_pci_unregister_driver(void); -#endif +#endif /* __iwl_bus_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index eec25b424def..4a0c7867cb6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -130,6 +130,11 @@ struct iwl_trans_ops { void (*free)(struct iwl_priv *priv); }; +/** + * struct iwl_trans - transport common data + * @ops - pointer to iwl_trans_ops + * @shrd - pointer to iwl_shared which holds shared data from the upper layer + */ struct iwl_trans { const struct iwl_trans_ops *ops; struct iwl_shared *shrd; From 87e5666c0722d5f4cad3560ab5c180c8bba62b8b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:50 -0700 Subject: [PATCH 067/129] iwlagn: transport handler can register debugfs entries Add a handler in iwl_trans_ops to allow it to add entries under debugfs dir given by the upper level. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 181 +-------------- drivers/net/wireless/iwlwifi/iwl-trans.c | 243 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 12 + 3 files changed, 258 insertions(+), 178 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0aa84560dc2d..d3223214a801 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -882,178 +882,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_FILE_OPS(current_sleep_command); -static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - int pos = 0, ofs = 0; - int cnt = 0, entry; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_rx_queue *rxq = &priv->rxq; - char *buf; - int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; - const u8 *ptr; - ssize_t ret; - - if (!priv->txq) { - IWL_ERR(priv, "txq not ready\n"); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate buffer\n"); - return -ENOMEM; - } - pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - txq = &priv->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "q[%d]: read_ptr: %u, write_ptr: %u\n", - cnt, q->read_ptr, q->write_ptr); - } - if (priv->tx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { - ptr = priv->tx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Tx Traffic idx: %u\n", priv->tx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "read: %u, write: %u\n", - rxq->read, rxq->write); - - if (priv->rx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { - ptr = priv->rx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Rx Traffic idx: %u\n", priv->rx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int traffic_log; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &traffic_log) != 1) - return -EFAULT; - if (traffic_log == 0) - iwl_reset_traffic_log(priv); - - return count; -} - -static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = file->private_data; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - char *buf; - int pos = 0; - int cnt; - int ret; - const size_t bufsz = sizeof(char) * 64 * - priv->cfg->base_params->num_of_queues; - - if (!priv->txq) { - IWL_ERR(priv, "txq not ready\n"); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - txq = &priv->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "hwq %.2d: read=%u write=%u stop=%d" - " swq_id=%#.2x (ac %d/hwq %d)\n", - cnt, q->read_ptr, q->write_ptr, - !!test_bit(cnt, priv->queue_stopped), - txq->swq_id, txq->swq_id & 3, - (txq->swq_id >> 2) & 0x1f); - if (cnt >= 4) - continue; - /* for the ACs, display the stop count too */ - pos += scnprintf(buf + pos, bufsz - pos, - " stop-count: %d\n", - atomic_read(&priv->queue_stop_count[cnt])); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = file->private_data; - struct iwl_rx_queue *rxq = &priv->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - if (rxq->rb_stts) { - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - } else { - pos += scnprintf(buf + pos, bufsz - pos, - "closed_rb_num: Not Allocated\n"); - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - static const char *fmt_value = " %-30s %10u\n"; static const char *fmt_hex = " %-30s 0x%02X\n"; static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; @@ -2630,9 +2458,6 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); -DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); -DEBUGFS_READ_FILE_OPS(rx_queue); -DEBUGFS_READ_FILE_OPS(tx_queue); DEBUGFS_READ_FILE_OPS(ucode_rx_stats); DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats); @@ -2696,9 +2521,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); @@ -2727,6 +2549,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); + + if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) + goto err; return 0; err: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 739087f3025c..eeeb1304eb37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -61,6 +61,7 @@ * *****************************************************************************/ #include +#include #include "iwl-dev.h" #include "iwl-trans.h" @@ -1169,6 +1170,246 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) return iwl_trans; } +#ifdef CONFIG_IWLWIFI_DEBUGFS +/* create and remove of files */ +#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ + if (!debugfs_create_file(#name, mode, parent, priv, \ + &iwl_dbgfs_##name##_ops)) \ + return -ENOMEM; \ +} while (0) + +/* file operation */ +#define DEBUGFS_READ_FUNC(name) \ +static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ + char __user *user_buf, \ + size_t count, loff_t *ppos); + +#define DEBUGFS_WRITE_FUNC(name) \ +static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos); + + +static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#define DEBUGFS_READ_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .read = iwl_dbgfs_##name##_read, \ + .open = iwl_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ + DEBUGFS_WRITE_FUNC(name); \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .write = iwl_dbgfs_##name##_write, \ + .read = iwl_dbgfs_##name##_read, \ + .open = iwl_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ +}; + +static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0, ofs = 0; + int cnt = 0, entry; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + struct iwl_rx_queue *rxq = &priv->rxq; + char *buf; + int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + + (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; + const u8 *ptr; + ssize_t ret; + + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate buffer\n"); + return -ENOMEM; + } + pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "q[%d]: read_ptr: %u, write_ptr: %u\n", + cnt, q->read_ptr, q->write_ptr); + } + if (priv->tx_traffic && + (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { + ptr = priv->tx_traffic; + pos += scnprintf(buf + pos, bufsz - pos, + "Tx Traffic idx: %u\n", priv->tx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += scnprintf(buf + pos, bufsz - pos, + "0x%.4x ", ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "read: %u, write: %u\n", + rxq->read, rxq->write); + + if (priv->rx_traffic && + (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { + ptr = priv->rx_traffic; + pos += scnprintf(buf + pos, bufsz - pos, + "Rx Traffic idx: %u\n", priv->rx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += scnprintf(buf + pos, bufsz - pos, + "0x%.4x ", ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int traffic_log; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &traffic_log) != 1) + return -EFAULT; + if (traffic_log == 0) + iwl_reset_traffic_log(priv); + + return count; +} + +static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + char *buf; + int pos = 0; + int cnt; + int ret; + const size_t bufsz = sizeof(char) * 64 * + priv->cfg->base_params->num_of_queues; + + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "hwq %.2d: read=%u write=%u stop=%d" + " swq_id=%#.2x (ac %d/hwq %d)\n", + cnt, q->read_ptr, q->write_ptr, + !!test_bit(cnt, priv->queue_stopped), + txq->swq_id, txq->swq_id & 3, + (txq->swq_id >> 2) & 0x1f); + if (cnt >= 4) + continue; + /* for the ACs, display the stop count too */ + pos += scnprintf(buf + pos, bufsz - pos, + " stop-count: %d\n", + atomic_read(&priv->queue_stop_count[cnt])); + } + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + struct iwl_priv *priv = file->private_data; + struct iwl_rx_queue *rxq = &priv->rxq; + char buf[256]; + int pos = 0; + const size_t bufsz = sizeof(buf); + + pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", + rxq->read); + pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", + rxq->write); + pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", + rxq->free_count); + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", + le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "closed_rb_num: Not Allocated\n"); + } + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + +DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); +DEBUGFS_READ_FILE_OPS(rx_queue); +DEBUGFS_READ_FILE_OPS(tx_queue); + +/* + * Create the debugfs files and directories + * + */ +static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, + struct dentry *dir) +{ + struct iwl_priv *priv = priv(trans); + + DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); + DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); + return 0; +} +#else +static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, + struct dentry *dir) +{ return 0; } + +#endif /*CONFIG_IWLWIFI_DEBUGFS */ + const struct iwl_trans_ops trans_ops_pcie = { .alloc = iwl_trans_pcie_alloc, .request_irq = iwl_trans_pcie_request_irq, @@ -1194,5 +1435,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .sync_irq = iwl_trans_pcie_sync_irq, .free = iwl_trans_pcie_free, + + .dbgfs_register = iwl_trans_pcie_dbgfs_register, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 4a0c7867cb6e..a9b3157994e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -63,6 +63,8 @@ #ifndef __iwl_trans_h__ #define __iwl_trans_h__ +#include + /*This file includes the declaration that are exported from the transport * layer */ @@ -98,6 +100,8 @@ struct iwl_shared; * layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... + * @dbgfs_register: add the dbgfs files under this directory. Files will be + * automatically deleted. */ struct iwl_trans_ops { @@ -128,6 +132,8 @@ struct iwl_trans_ops { void (*sync_irq)(struct iwl_priv *priv); void (*free)(struct iwl_priv *priv); + + int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); }; /** @@ -232,6 +238,12 @@ static inline void iwl_trans_free(struct iwl_trans *trans) trans->ops->free(priv(trans)); } +static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, + struct dentry *dir) +{ + return trans->ops->dbgfs_register(trans, dir); +} + /***************************************************** * Transport layers implementations ******************************************************/ From 5a878bf60b2bb1f1509f49b8b1784e3c9f204c64 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:51 -0700 Subject: [PATCH 068/129] iwlagn: iwl_rx_queue moves to the iwl_trans_pcie Since this struct is specific to pcie transport, move it the the pcie specific transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 44 +------ drivers/net/wireless/iwlwifi/iwl-shared.h | 8 ++ .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 49 +++++++- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 114 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-trans.c | 109 ++++++++++------- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 +- 6 files changed, 184 insertions(+), 144 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4f65b0980a1f..9c9dc1983740 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -91,14 +91,6 @@ struct iwl_tx_queue; #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -struct iwl_rx_mem_buffer { - dma_addr_t page_dma; - struct page *page; - struct list_head list; -}; - -#define rxb_addr(r) page_address(r->page) - /* defined below */ struct iwl_device_cmd; @@ -335,38 +327,6 @@ struct iwl_host_cmd { #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 -/** - * struct iwl_rx_queue - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) - * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) - * @read: Shared index to newest available Rx buffer - * @write: Shared index to oldest written Rx packet - * @free_count: Number of pre-allocated buffers in rx_free - * @rx_free: list of free SKBs for use - * @rx_used: List of Rx buffers with no SKB - * @need_update: flag to indicate we need to update read/write index - * @rb_stts: driver's pointer to receive buffer status - * @rb_stts_dma: bus address of receive buffer status - * - * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers - */ -struct iwl_rx_queue { - __le32 *bd; - dma_addr_t bd_dma; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 read; - u32 write; - u32 free_count; - u32 write_actual; - struct list_head rx_free; - struct list_head rx_used; - int need_update; - struct iwl_rb_status *rb_stts; - dma_addr_t rb_stts_dma; - spinlock_t lock; -}; - #define IWL_SUPPORTED_RATES_IE_LEN 8 #define MAX_TID_COUNT 9 @@ -1286,8 +1246,7 @@ struct iwl_priv { int activity_timer_active; - /* Rx and Tx DMA processing queues */ - struct iwl_rx_queue rxq; + /* Tx DMA processing queues */ struct iwl_tx_queue *txq; unsigned long txq_ctx_active_msk; struct iwl_dma_ptr kw; /* keep warm address */ @@ -1426,7 +1385,6 @@ struct iwl_priv { struct work_struct restart; struct work_struct scan_completed; - struct work_struct rx_replenish; struct work_struct abort_scan; struct work_struct beacon_update; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 467cfaacd698..539b76ba870a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -205,6 +205,14 @@ static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) } #endif +struct iwl_rx_mem_buffer { + dma_addr_t page_dma; + struct page *page; + struct list_head list; +}; + +#define rxb_addr(r) page_address(r->page) + #ifdef CONFIG_PM int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 2bc421b43a91..1d80515c1dbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -32,19 +32,64 @@ /*This file includes the declaration that are internal to the * trans_pcie layer */ +/** + * struct iwl_rx_queue - Rx queue + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) + * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @pool: + * @queue: + * @read: Shared index to newest available Rx buffer + * @write: Shared index to oldest written Rx packet + * @free_count: Number of pre-allocated buffers in rx_free + * @write_actual: + * @rx_free: list of free SKBs for use + * @rx_used: List of Rx buffers with no SKB + * @need_update: flag to indicate we need to update read/write index + * @rb_stts: driver's pointer to receive buffer status + * @rb_stts_dma: bus address of receive buffer status + * @lock: + * + * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers + */ +struct iwl_rx_queue { + __le32 *bd; + dma_addr_t bd_dma; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; + u32 read; + u32 write; + u32 free_count; + u32 write_actual; + struct list_head rx_free; + struct list_head rx_used; + int need_update; + struct iwl_rb_status *rb_stts; + dma_addr_t rb_stts_dma; + spinlock_t lock; +}; + /** * struct iwl_trans_pcie - PCIe transport specific data + * @rxq: all the RX queue data + * @rx_replenish: work that will be called when buffers need to be allocated + * @trans: pointer to the generic transport area */ struct iwl_trans_pcie { + struct iwl_rx_queue rxq; + struct work_struct rx_replenish; + struct iwl_trans *trans; }; +#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ + ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) + /***************************************************** * RX ******************************************************/ void iwl_bg_rx_replenish(struct work_struct *data); void iwl_irq_tasklet(struct iwl_priv *priv); -void iwlagn_rx_replenish(struct iwl_priv *priv); -void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, +void iwlagn_rx_replenish(struct iwl_trans *trans); +void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, struct iwl_rx_queue *q); /***************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 6f5edf731542..fb06acf83fc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -127,9 +127,10 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q) /** * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, +void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, struct iwl_rx_queue *q) { + struct iwl_priv *priv = priv(trans); unsigned long flags; u32 reg; @@ -145,11 +146,11 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, + IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); iwl_set_bit(priv, CSR_GP_CNTRL, @@ -178,8 +179,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, /** * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, - dma_addr_t dma_addr) +static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) { return cpu_to_le32((u32)(dma_addr >> 8)); } @@ -195,9 +195,12 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwlagn_rx_queue_restock(struct iwl_priv *priv) +static void iwlagn_rx_queue_restock(struct iwl_trans *trans) { - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + struct iwl_rx_queue *rxq = &trans_pcie->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -214,8 +217,7 @@ static void iwlagn_rx_queue_restock(struct iwl_priv *priv) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, - rxb->page_dma); + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -224,7 +226,7 @@ static void iwlagn_rx_queue_restock(struct iwl_priv *priv) /* If the pre-allocated buffer pool is dropping low, schedule to * refill it */ if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->shrd->workqueue, &priv->rx_replenish); + queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish); /* If we've added more space for the firmware to place data, tell it. @@ -233,7 +235,7 @@ static void iwlagn_rx_queue_restock(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_queue_update_write_ptr(priv, rxq); + iwl_rx_queue_update_write_ptr(trans, rxq); } } @@ -245,9 +247,12 @@ static void iwlagn_rx_queue_restock(struct iwl_priv *priv) * Also restock the Rx queue via iwl_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) +static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) { - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + struct iwl_rx_queue *rxq = &trans_pcie->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; struct page *page; @@ -265,21 +270,21 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) if (rxq->free_count > RX_LOW_WATERMARK) gfp_mask |= __GFP_NOWARN; - if (hw_params(priv).rx_page_order > 0) + if (hw_params(trans).rx_page_order > 0) gfp_mask |= __GFP_COMP; /* Alloc a new receive buffer */ page = alloc_pages(gfp_mask, - hw_params(priv).rx_page_order); + hw_params(trans).rx_page_order); if (!page) { if (net_ratelimit()) - IWL_DEBUG_INFO(priv, "alloc_pages failed, " + IWL_DEBUG_INFO(trans, "alloc_pages failed, " "order: %d\n", - hw_params(priv).rx_page_order); + hw_params(trans).rx_page_order); if ((rxq->free_count <= RX_LOW_WATERMARK) && net_ratelimit()) - IWL_CRIT(priv, "Failed to alloc_pages with %s." + IWL_CRIT(trans, "Failed to alloc_pages with %s." "Only %u free buffers remaining.\n", priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", @@ -294,7 +299,7 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, hw_params(priv).rx_page_order); + __free_pages(page, hw_params(trans).rx_page_order); return; } element = rxq->rx_used.next; @@ -306,8 +311,8 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, - PAGE_SIZE << hw_params(priv).rx_page_order, + rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0, + PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); @@ -323,35 +328,36 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) } } -void iwlagn_rx_replenish(struct iwl_priv *priv) +void iwlagn_rx_replenish(struct iwl_trans *trans) { unsigned long flags; - iwlagn_rx_allocate(priv, GFP_KERNEL); + iwlagn_rx_allocate(trans, GFP_KERNEL); - spin_lock_irqsave(&priv->shrd->lock, flags); - iwlagn_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); + iwlagn_rx_queue_restock(trans); + spin_unlock_irqrestore(&trans->shrd->lock, flags); } -static void iwlagn_rx_replenish_now(struct iwl_priv *priv) +static void iwlagn_rx_replenish_now(struct iwl_trans *trans) { - iwlagn_rx_allocate(priv, GFP_ATOMIC); + iwlagn_rx_allocate(trans, GFP_ATOMIC); - iwlagn_rx_queue_restock(priv); + iwlagn_rx_queue_restock(trans); } void iwl_bg_rx_replenish(struct work_struct *data) { - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rx_replenish); + struct iwl_trans_pcie *trans_pcie = + container_of(data, struct iwl_trans_pcie, rx_replenish); + struct iwl_trans *trans = trans_pcie->trans; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) return; - mutex_lock(&priv->shrd->mutex); - iwlagn_rx_replenish(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_lock(&trans->shrd->mutex); + iwlagn_rx_replenish(trans); + mutex_unlock(&trans->shrd->mutex); } /** @@ -361,11 +367,13 @@ void iwl_bg_rx_replenish(struct work_struct *data) * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ -static void iwl_rx_handle(struct iwl_priv *priv) +static void iwl_rx_handle(struct iwl_trans *trans) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; u32 r, i; int reclaim; unsigned long flags; @@ -380,7 +388,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) /* Rx interrupt, but nothing sent from uCode */ if (i == r) - IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); + IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); /* calculate total frames need to be restock after handling RX */ total_empty = r - rxq->write_actual; @@ -405,17 +413,17 @@ static void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; - dma_unmap_page(priv->bus->dev, rxb->page_dma, - PAGE_SIZE << hw_params(priv).rx_page_order, + dma_unmap_page(bus(trans)->dev, rxb->page_dma, + PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); - IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, + IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv, pkt, len); + trace_iwlwifi_dev_rx(priv(trans), pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -431,7 +439,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && (pkt->hdr.cmd != REPLY_TX); - iwl_rx_dispatch(priv, rxb); + iwl_rx_dispatch(priv(trans), rxb); /* * XXX: After here, we should always check rxb->page @@ -446,9 +454,9 @@ static void iwl_rx_handle(struct iwl_priv *priv) * iwl_trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) - iwl_tx_cmd_complete(priv, rxb); + iwl_tx_cmd_complete(priv(trans), rxb); else - IWL_WARN(priv, "Claim null rxb?\n"); + IWL_WARN(trans, "Claim null rxb?\n"); } /* Reuse the page if possible. For notification packets and @@ -456,9 +464,9 @@ static void iwl_rx_handle(struct iwl_priv *priv) * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, + rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, 0, PAGE_SIZE << - hw_params(priv).rx_page_order, + hw_params(trans).rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; @@ -474,7 +482,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) count++; if (count >= 8) { rxq->read = i; - iwlagn_rx_replenish_now(priv); + iwlagn_rx_replenish_now(trans); count = 0; } } @@ -483,9 +491,9 @@ static void iwl_rx_handle(struct iwl_priv *priv) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwlagn_rx_replenish_now(priv); + iwlagn_rx_replenish_now(trans); else - iwlagn_rx_queue_restock(priv); + iwlagn_rx_queue_restock(trans); } /* tasklet for iwlagn interrupt */ @@ -611,8 +619,10 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans(priv)); IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + iwl_rx_queue_update_write_ptr(trans(priv), &trans_pcie->rxq); for (i = 0; i < hw_params(priv).max_txq_num; i++) iwl_txq_update_write_ptr(priv, &priv->txq[i]); @@ -650,7 +660,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* Disable periodic interrupt; we use it as just a one-shot. */ iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - iwl_rx_handle(priv); + iwl_rx_handle(trans(priv)); /* * Enable periodic interrupt in 8 msec only if we received diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index eeeb1304eb37..95d7b04a65f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -73,12 +73,14 @@ #include "iwl-core.h" #include "iwl-shared.h" -static int iwl_trans_rx_alloc(struct iwl_priv *priv) +static int iwl_trans_rx_alloc(struct iwl_trans *trans) { - struct iwl_rx_queue *rxq = &priv->rxq; - struct device *dev = priv->bus->dev; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct device *dev = bus(trans)->dev; - memset(&priv->rxq, 0, sizeof(priv->rxq)); + memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); spin_lock_init(&rxq->lock); INIT_LIST_HEAD(&rxq->rx_free); @@ -112,9 +114,11 @@ err_bd: return -ENOMEM; } -static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) +static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) { - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; int i; /* Fill the rx_used queue with _all_ of the Rx buffers */ @@ -122,10 +126,10 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, - PAGE_SIZE << hw_params(priv).rx_page_order, + dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, + PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); - __iwl_free_pages(priv, rxq->pool[i].page); + __iwl_free_pages(priv(trans), rxq->pool[i].page); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); @@ -181,14 +185,17 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static int iwl_rx_init(struct iwl_priv *priv) +static int iwl_rx_init(struct iwl_trans *trans) { - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + int i, err; unsigned long flags; if (!rxq->bd) { - err = iwl_trans_rx_alloc(priv); + err = iwl_trans_rx_alloc(trans); if (err) return err; } @@ -197,7 +204,7 @@ static int iwl_rx_init(struct iwl_priv *priv) INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); - iwl_trans_rxq_free_rx_bufs(priv); + iwl_trans_rxq_free_rx_bufs(trans); for (i = 0; i < RX_QUEUE_SIZE; i++) rxq->queue[i] = NULL; @@ -209,45 +216,48 @@ static int iwl_rx_init(struct iwl_priv *priv) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); - iwlagn_rx_replenish(priv); + iwlagn_rx_replenish(trans); - iwl_trans_rx_hw_init(priv, rxq); + iwl_trans_rx_hw_init(priv(trans), rxq); - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(priv, rxq); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + iwl_rx_queue_update_write_ptr(trans, rxq); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return 0; } -static void iwl_trans_pcie_rx_free(struct iwl_priv *priv) +static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) { - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + unsigned long flags; /*if rxq->bd is NULL, it means that nothing has been allocated, * exit now */ if (!rxq->bd) { - IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); + IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); return; } spin_lock_irqsave(&rxq->lock, flags); - iwl_trans_rxq_free_rx_bufs(priv); + iwl_trans_rxq_free_rx_bufs(trans); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(priv->bus->dev, + dma_free_coherent(bus(trans)->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else - IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); + IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); rxq->rb_stts = NULL; } @@ -614,7 +624,7 @@ static int iwl_nic_init(struct iwl_priv *priv) priv->cfg->lib->nic_config(priv); /* Allocate the RX queue, or reset if it is already allocated */ - iwl_rx_init(priv); + iwl_rx_init(trans(priv)); /* Allocate or reset and init all Tx and Command queues */ if (iwl_tx_init(priv)) @@ -1120,6 +1130,8 @@ static void iwl_trans_pcie_kick_nic(struct iwl_priv *priv) static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_priv *priv = priv(trans); int err; @@ -1136,7 +1148,7 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) return err; } - INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); + INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); return 0; } @@ -1163,8 +1175,11 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) sizeof(struct iwl_trans_pcie), GFP_KERNEL); if (iwl_trans) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(iwl_trans); iwl_trans->ops = &trans_ops_pcie; iwl_trans->shrd = shrd; + trans_pcie->trans = iwl_trans; } return iwl_trans; @@ -1173,7 +1188,7 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) #ifdef CONFIG_IWLWIFI_DEBUGFS /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, priv, \ + if (!debugfs_create_file(#name, mode, parent, trans, \ &iwl_dbgfs_##name##_ops)) \ return -ENOMEM; \ } while (0) @@ -1218,12 +1233,15 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = file->private_data; + struct iwl_trans *trans = file->private_data; + struct iwl_priv *priv = priv(trans); int pos = 0, ofs = 0; int cnt = 0, entry; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq; struct iwl_queue *q; - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; char *buf; int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; @@ -1231,16 +1249,16 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, ssize_t ret; if (!priv->txq) { - IWL_ERR(priv, "txq not ready\n"); + IWL_ERR(trans, "txq not ready\n"); return -EAGAIN; } buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { - IWL_ERR(priv, "Can not allocate buffer\n"); + IWL_ERR(trans, "Can not allocate buffer\n"); return -ENOMEM; } pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { txq = &priv->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, @@ -1248,10 +1266,10 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, cnt, q->read_ptr, q->write_ptr); } if (priv->tx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { + (iwl_get_debug_level(trans->shrd) & IWL_DL_TX)) { ptr = priv->tx_traffic; pos += scnprintf(buf + pos, bufsz - pos, - "Tx Traffic idx: %u\n", priv->tx_traffic_idx); + "Tx Traffic idx: %u\n", priv->tx_traffic_idx); for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; entry++, ofs += 16) { @@ -1272,10 +1290,10 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, rxq->read, rxq->write); if (priv->rx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { + (iwl_get_debug_level(trans->shrd) & IWL_DL_RX)) { ptr = priv->rx_traffic; pos += scnprintf(buf + pos, bufsz - pos, - "Rx Traffic idx: %u\n", priv->rx_traffic_idx); + "Rx Traffic idx: %u\n", priv->rx_traffic_idx); for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; entry++, ofs += 16) { @@ -1299,7 +1317,7 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = file->private_data; + struct iwl_trans *trans = file->private_data; char buf[8]; int buf_size; int traffic_log; @@ -1311,7 +1329,7 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, if (sscanf(buf, "%d", &traffic_log) != 1) return -EFAULT; if (traffic_log == 0) - iwl_reset_traffic_log(priv); + iwl_reset_traffic_log(priv(trans)); return count; } @@ -1320,7 +1338,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = file->private_data; + struct iwl_trans *trans = file->private_data; + struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq; struct iwl_queue *q; char *buf; @@ -1338,7 +1357,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, if (!buf) return -ENOMEM; - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { txq = &priv->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, @@ -1363,8 +1382,10 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = file->private_data; - struct iwl_rx_queue *rxq = &priv->rxq; + struct iwl_trans *trans = file->private_data; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; char buf[256]; int pos = 0; const size_t bufsz = sizeof(buf); @@ -1396,8 +1417,6 @@ DEBUGFS_READ_FILE_OPS(tx_queue); static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, struct dentry *dir) { - struct iwl_priv *priv = priv(trans); - DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index a9b3157994e9..8eee910b15e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -112,7 +112,7 @@ struct iwl_trans_ops { void (*stop_device)(struct iwl_priv *priv); void (*tx_start)(struct iwl_priv *priv); void (*tx_free)(struct iwl_priv *priv); - void (*rx_free)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_trans *trans); int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); @@ -177,7 +177,7 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) static inline void iwl_trans_rx_free(struct iwl_trans *trans) { - trans->ops->rx_free(priv(trans)); + trans->ops->rx_free(trans); } static inline void iwl_trans_tx_free(struct iwl_trans *trans) From 57210f7c9f04a2509ee54a0f454003a714db96dd Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:52 -0700 Subject: [PATCH 069/129] iwlagn: move iwl_suspend / iwl_resume to the transport layer These flows needs to access the APM and a few other registers that can differ between different transports. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++--- drivers/net/wireless/iwlwifi/iwl-core.c | 41 ------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 - drivers/net/wireless/iwlwifi/iwl-pci.c | 4 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 + drivers/net/wireless/iwlwifi/iwl-trans.c | 50 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 14 +++++++ 8 files changed, 73 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fcbc3b1d0584..660abede935c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1818,7 +1818,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { + if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -1833,7 +1833,7 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - if (!priv->wowlan) { + if (!priv->shrd->wowlan) { /* WoWLAN ucode will not reply in the same way, skip it */ iwl_reset_run_time_calib(priv); } @@ -2593,7 +2593,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_trans_stop_device(trans(priv)); - priv->wowlan = true; + priv->shrd->wowlan = true; ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan, IWL_UCODE_WOWLAN); @@ -2693,7 +2693,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, goto out; error: - priv->wowlan = false; + priv->shrd->wowlan = false; iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: @@ -2745,7 +2745,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - priv->wowlan = false; + priv->shrd->wowlan = false; device_set_wakeup_enable(priv->bus->dev, false); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b5e99a66613e..d77af6969a5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1900,44 +1900,3 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, return cpu_to_le32(res); } -#ifdef CONFIG_PM - -int iwl_suspend(struct iwl_priv *priv) -{ - /* - * This function is called when system goes into suspend state - * mac80211 will call iwl_mac_stop() from the mac80211 suspend function - * first but since iwl_mac_stop() has no knowledge of who the caller is, - * it will not call apm_ops.stop() to stop the DMA operation. - * Calling apm_ops.stop here to make sure we stop the DMA. - * - * But of course ... if we have configured WoWLAN then we did other - * things already :-) - */ - if (!priv->wowlan) - iwl_apm_stop(priv); - - return 0; -} - -int iwl_resume(struct iwl_priv *priv) -{ - bool hw_rfkill = false; - - iwl_enable_interrupts(priv); - - if (!(iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rfkill = true; - - if (hw_rfkill) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); - - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill); - - return 0; -} - -#endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9c9dc1983740..8a8fc74eebca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1280,8 +1280,6 @@ struct iwl_priv { u8 mac80211_registered; - bool wowlan; - /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 521d7e265c2a..4b990907f26f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -517,7 +517,7 @@ static int iwl_pci_suspend(struct device *device) * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_suspend(shrd->priv); + return iwl_trans_suspend(shrd->trans); } static int iwl_pci_resume(struct device *device) @@ -536,7 +536,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(shrd->priv); + return iwl_trans_resume(shrd->trans); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 5ecb11e42e4a..9f0e620fc3a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -348,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->wowlan) + if (priv->shrd->wowlan) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); else if (!priv->cfg->base_params->no_idle_support && priv->hw->conf.flags & IEEE80211_CONF_IDLE) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 539b76ba870a..a5ef79bb275a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -165,6 +165,7 @@ struct iwl_shared { u8 cmd_queue; unsigned long status; + bool wowlan; struct iwl_bus *bus; struct iwl_priv *priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 95d7b04a65f3..621b9a822090 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1167,6 +1167,54 @@ static void iwl_trans_pcie_free(struct iwl_priv *priv) trans(priv) = NULL; } +#ifdef CONFIG_PM + +static int iwl_trans_pcie_suspend(struct iwl_trans *trans) +{ + /* + * This function is called when system goes into suspend state + * mac80211 will call iwl_mac_stop() from the mac80211 suspend function + * first but since iwl_mac_stop() has no knowledge of who the caller is, + * it will not call apm_ops.stop() to stop the DMA operation. + * Calling apm_ops.stop here to make sure we stop the DMA. + * + * But of course ... if we have configured WoWLAN then we did other + * things already :-) + */ + if (!trans->shrd->wowlan) + iwl_apm_stop(priv(trans)); + + return 0; +} + +static int iwl_trans_pcie_resume(struct iwl_trans *trans) +{ + bool hw_rfkill = false; + + iwl_enable_interrupts(priv(trans)); + + if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + hw_rfkill = true; + + if (hw_rfkill) + set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + else + clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + + wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, hw_rfkill); + + return 0; +} +#else /* CONFIG_PM */ +static int iwl_trans_pcie_suspend(struct iwl_trans *trans) +{ return 0; } + +static int iwl_trans_pcie_resume(struct iwl_trans *trans) +{ return 0; } + +#endif /* CONFIG_PM */ + const struct iwl_trans_ops trans_ops_pcie; static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) @@ -1456,5 +1504,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .free = iwl_trans_pcie_free, .dbgfs_register = iwl_trans_pcie_dbgfs_register, + .suspend = iwl_trans_pcie_suspend, + .resume = iwl_trans_pcie_resume, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8eee910b15e8..c12763c1a3a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -102,6 +102,8 @@ struct iwl_shared; * irq, tasklet etc... * @dbgfs_register: add the dbgfs files under this directory. Files will be * automatically deleted. + * @suspend: stop the device unless WoWLAN is configured + * @resume: resume activity of the device */ struct iwl_trans_ops { @@ -134,6 +136,8 @@ struct iwl_trans_ops { void (*free)(struct iwl_priv *priv); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); + int (*suspend)(struct iwl_trans *trans); + int (*resume)(struct iwl_trans *trans); }; /** @@ -244,6 +248,16 @@ static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, return trans->ops->dbgfs_register(trans, dir); } +static inline int iwl_trans_suspend(struct iwl_trans *trans) +{ + return trans->ops->suspend(trans); +} + +static inline int iwl_trans_resume(struct iwl_trans *trans) +{ + return trans->ops->resume(trans); +} + /***************************************************** * Transport layers implementations ******************************************************/ From 0c325769a394559941acda83e888a1d9b1ef8b7f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:53 -0700 Subject: [PATCH 070/129] iwlagn: move ISR related data to transport layer Since the ISR is entirely in the transport layer, its data should be in the pcie specific region. Change sync_irq to first disable and then synchronize the IRQ. iwl_isr and iwl_isr_ict now receive iwl_trans. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 12 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 13 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 21 -- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 45 ++- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 333 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-trans.c | 50 +-- drivers/net/wireless/iwlwifi/iwl-trans.h | 13 +- 7 files changed, 255 insertions(+), 232 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 660abede935c..ca6bb7b1c96d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3627,7 +3627,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; - priv->inta_mask = CSR_INI_SET_MASK; /* is antenna coupling more than 35dB ? */ priv->bt_ant_couple_ok = @@ -3771,8 +3770,6 @@ out: void __devexit iwl_remove(struct iwl_priv * priv) { - unsigned long flags; - wait_for_completion(&priv->firmware_loading_complete); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); @@ -3801,13 +3798,8 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_tt_exit(priv); /* make sure we flush any pending irq or - * tasklet for the driver - */ - spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->shrd->lock, flags); - - iwl_trans_sync_irq(trans(priv)); + * tasklet for the driver */ + iwl_trans_disable_sync_irq(trans(priv)); iwl_dealloc_ucode(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8a8fc74eebca..40a01c0e4f30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1259,6 +1259,7 @@ struct iwl_priv { struct traffic_stats rx_stats; /* counts interrupts */ + /* TODO: move to the transport layer */ struct isr_statistics isr_stats; struct iwl_power_mgr power_data; @@ -1315,14 +1316,6 @@ struct iwl_priv { } accum_stats, delta_stats, max_delta_stats; #endif - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; /* * reporting the number of tids has AGG on. 0 means * no AGGREGATION @@ -1379,8 +1372,6 @@ struct iwl_priv { struct iwl_rxon_context *cur_rssi_ctx; bool bt_is_sco; - u32 inta_mask; - struct work_struct restart; struct work_struct scan_completed; struct work_struct abort_scan; @@ -1398,8 +1389,6 @@ struct iwl_priv { struct work_struct bt_full_concurrency; struct work_struct bt_runtime_config; - struct tasklet_struct irq_tasklet; - struct delayed_work scan_check; /* TX Power */ diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index d053ed7ef794..09ed7af19889 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -132,33 +132,12 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv, #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue -static inline void iwl_disable_interrupts(struct iwl_priv *priv) -{ - clear_bit(STATUS_INT_ENABLED, &priv->shrd->status); - - /* disable interrupts from uCode/NIC to host */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* acknowledge/clear/reset any interrupts still pending - * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(priv, CSR_INT, 0xffffffff); - iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); -} - static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); } -static inline void iwl_enable_interrupts(struct iwl_priv *priv) -{ - IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &priv->shrd->status); - iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); -} - /** * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time * @priv -- pointer to iwl_priv data structure diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 1d80515c1dbf..7e2f954c95f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -78,6 +78,18 @@ struct iwl_trans_pcie { struct iwl_rx_queue rxq; struct work_struct rx_replenish; struct iwl_trans *trans; + + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + struct tasklet_struct irq_tasklet; + + u32 inta_mask; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ @@ -87,7 +99,7 @@ struct iwl_trans_pcie { * RX ******************************************************/ void iwl_bg_rx_replenish(struct work_struct *data); -void iwl_irq_tasklet(struct iwl_priv *priv); +void iwl_irq_tasklet(struct iwl_trans *trans); void iwlagn_rx_replenish(struct iwl_trans *trans); void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, struct iwl_rx_queue *q); @@ -96,12 +108,11 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, * ICT ******************************************************/ int iwl_reset_ict(struct iwl_priv *priv); -void iwl_disable_ict(struct iwl_priv *priv); -int iwl_alloc_isr_ict(struct iwl_priv *priv); -void iwl_free_isr_ict(struct iwl_priv *priv); +void iwl_disable_ict(struct iwl_trans *trans); +int iwl_alloc_isr_ict(struct iwl_trans *trans); +void iwl_free_isr_ict(struct iwl_trans *trans); irqreturn_t iwl_isr_ict(int irq, void *data); - /***************************************************** * TX / HCMD ******************************************************/ @@ -130,4 +141,28 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); +static inline void iwl_disable_interrupts(struct iwl_trans *trans) +{ + clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); + + /* disable interrupts from uCode/NIC to host */ + iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); + + /* acknowledge/clear/reset any interrupts still pending + * from uCode or flow handler (Rx/Tx DMA) */ + iwl_write32(priv(trans), CSR_INT, 0xffffffff); + iwl_write32(priv(trans), CSR_FH_INT_STATUS, 0xffffffff); + IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); +} + +static inline void iwl_enable_interrupts(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); + set_bit(STATUS_INT_ENABLED, &trans->shrd->status); + iwl_write32(priv(trans), CSR_INT_MASK, trans_pcie->inta_mask); +} + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index fb06acf83fc6..15e2645c2fb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -497,7 +497,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) } /* tasklet for iwlagn interrupt */ -void iwl_irq_tasklet(struct iwl_priv *priv) +void iwl_irq_tasklet(struct iwl_trans *trans) { u32 inta = 0; u32 handled = 0; @@ -507,7 +507,10 @@ void iwl_irq_tasklet(struct iwl_priv *priv) u32 inta_mask; #endif - spin_lock_irqsave(&priv->shrd->lock, flags); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans->shrd->lock, flags); /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, @@ -520,33 +523,34 @@ void iwl_irq_tasklet(struct iwl_priv *priv) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); + iwl_write32(priv(trans), CSR_INT, + trans_pcie->inta | ~trans_pcie->inta_mask); - inta = priv->inta; + inta = trans_pcie->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & IWL_DL_ISR) { + if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", + inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); + IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", inta, inta_mask); } #endif - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); - /* saved interrupt in inta variable now we can reset priv->inta */ - priv->inta = 0; + /* saved interrupt in inta variable now we can reset trans_pcie->inta */ + trans_pcie->inta = 0; /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); + IWL_ERR(trans, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); + iwl_disable_interrupts(trans); - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); + priv(trans)->isr_stats.hw++; + iwl_irq_handle_error(priv(trans)); handled |= CSR_INT_BIT_HW_ERR; @@ -554,18 +558,18 @@ void iwl_irq_tasklet(struct iwl_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { + if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " + IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " "the frame/frames.\n"); - priv->isr_stats.sch++; + priv(trans)->isr_stats.sch++; } /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; + IWL_DEBUG_ISR(trans, "Alive interrupt\n"); + priv(trans)->isr_stats.alive++; } } #endif @@ -575,27 +579,29 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl_read32(priv, CSR_GP_CNTRL) & + if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", + IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); - priv->isr_stats.rfkill++; + priv(trans)->isr_stats.rfkill++; /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(STATUS_ALIVE, &priv->shrd->status)) { + if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) { if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, + &trans->shrd->status); else clear_bit(STATUS_RF_KILL_HW, - &priv->shrd->status); - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); + &trans->shrd->status); + wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, + hw_rf_kill); } handled |= CSR_INT_BIT_RF_KILL; @@ -603,30 +609,29 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(priv, "Microcode CT kill error detected.\n"); - priv->isr_stats.ctkill++; + IWL_ERR(trans, "Microcode CT kill error detected.\n"); + priv(trans)->isr_stats.ctkill++; handled |= CSR_INT_BIT_CT_KILL; } /* Error detected by uCode */ if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " + IWL_ERR(trans, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - iwl_irq_handle_error(priv); + priv(trans)->isr_stats.sw++; + iwl_irq_handle_error(priv(trans)); handled |= CSR_INT_BIT_SW_ERR; } /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans(priv)); - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(trans(priv), &trans_pcie->rxq); - for (i = 0; i < hw_params(priv).max_txq_num; i++) - iwl_txq_update_write_ptr(priv, &priv->txq[i]); + IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); + for (i = 0; i < hw_params(trans).max_txq_num; i++) + iwl_txq_update_write_ptr(priv(trans), + &priv(trans)->txq[i]); - priv->isr_stats.wakeup++; + priv(trans)->isr_stats.wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -636,15 +641,16 @@ void iwl_irq_tasklet(struct iwl_priv *priv) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | CSR_INT_BIT_RX_PERIODIC)) { - IWL_DEBUG_ISR(priv, "Rx interrupt\n"); + IWL_DEBUG_ISR(trans, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(priv, CSR_FH_INT_STATUS, + iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); + iwl_write32(priv(trans), + CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the * the device: @@ -658,9 +664,9 @@ void iwl_irq_tasklet(struct iwl_priv *priv) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(priv, CSR_INT_PERIODIC_REG, + iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - iwl_rx_handle(trans(priv)); + iwl_rx_handle(trans); /* * Enable periodic interrupt in 8 msec only if we received @@ -670,40 +676,40 @@ void iwl_irq_tasklet(struct iwl_priv *priv) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(priv, CSR_INT_PERIODIC_REG, + iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); - priv->isr_stats.rx++; + priv(trans)->isr_stats.rx++; } /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); - priv->isr_stats.tx++; + iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); + priv(trans)->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ - priv->ucode_write_complete = 1; - wake_up_interruptible(&priv->wait_command_queue); + priv(trans)->ucode_write_complete = 1; + wake_up_interruptible(&priv(trans)->wait_command_queue); } if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; + IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv(trans)->isr_stats.unhandled++; } - if (inta & ~(priv->inta_mask)) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); + if (inta & ~(trans_pcie->inta_mask)) { + IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n", + inta & ~trans_pcie->inta_mask); } /* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status)) - iwl_enable_interrupts(priv); + if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) + iwl_enable_interrupts(trans); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv); + iwl_enable_rfkill_int(priv(trans)); } /****************************************************************************** @@ -714,18 +720,21 @@ void iwl_irq_tasklet(struct iwl_priv *priv) #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) /* Free dram table */ -void iwl_free_isr_ict(struct iwl_priv *priv) +void iwl_free_isr_ict(struct iwl_trans *trans) { - if (priv->ict_tbl_vir) { - dma_free_coherent(priv->bus->dev, + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + if (trans_pcie->ict_tbl_vir) { + dma_free_coherent(bus(trans)->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->ict_tbl_vir, - priv->ict_tbl_dma); - priv->ict_tbl_vir = NULL; - memset(&priv->ict_tbl_dma, 0, - sizeof(priv->ict_tbl_dma)); - memset(&priv->aligned_ict_tbl_dma, 0, - sizeof(priv->aligned_ict_tbl_dma)); + trans_pcie->ict_tbl_vir, + trans_pcie->ict_tbl_dma); + trans_pcie->ict_tbl_vir = NULL; + memset(&trans_pcie->ict_tbl_dma, 0, + sizeof(trans_pcie->ict_tbl_dma)); + memset(&trans_pcie->aligned_ict_tbl_dma, 0, + sizeof(trans_pcie->aligned_ict_tbl_dma)); } } @@ -733,43 +742,45 @@ void iwl_free_isr_ict(struct iwl_priv *priv) /* allocate dram shared table it is a PAGE_SIZE aligned * also reset all data related to ICT table interrupt. */ -int iwl_alloc_isr_ict(struct iwl_priv *priv) +int iwl_alloc_isr_ict(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); /* allocate shrared data table */ - priv->ict_tbl_vir = - dma_alloc_coherent(priv->bus->dev, + trans_pcie->ict_tbl_vir = + dma_alloc_coherent(bus(trans)->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->ict_tbl_dma, GFP_KERNEL); - if (!priv->ict_tbl_vir) + &trans_pcie->ict_tbl_dma, GFP_KERNEL); + if (!trans_pcie->ict_tbl_vir) return -ENOMEM; /* align table to PAGE_SIZE boundary */ - priv->aligned_ict_tbl_dma = - ALIGN(priv->ict_tbl_dma, PAGE_SIZE); + trans_pcie->aligned_ict_tbl_dma = + ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); - IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->ict_tbl_dma, - (unsigned long long)priv->aligned_ict_tbl_dma, - (int)(priv->aligned_ict_tbl_dma - - priv->ict_tbl_dma)); + IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)trans_pcie->ict_tbl_dma, + (unsigned long long)trans_pcie->aligned_ict_tbl_dma, + (int)(trans_pcie->aligned_ict_tbl_dma - + trans_pcie->ict_tbl_dma)); - priv->ict_tbl = priv->ict_tbl_vir + - (priv->aligned_ict_tbl_dma - - priv->ict_tbl_dma); + trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + + (trans_pcie->aligned_ict_tbl_dma - + trans_pcie->ict_tbl_dma); - IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->ict_tbl, priv->ict_tbl_vir, - (int)(priv->aligned_ict_tbl_dma - - priv->ict_tbl_dma)); + IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", + trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, + (int)(trans_pcie->aligned_ict_tbl_dma - + trans_pcie->ict_tbl_dma)); /* reset table and index to all 0 */ - memset(priv->ict_tbl_vir, 0, + memset(trans_pcie->ict_tbl_vir, 0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->ict_index = 0; + trans_pcie->ict_index = 0; /* add periodic RX interrupt */ - priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC; return 0; } @@ -780,110 +791,120 @@ int iwl_reset_ict(struct iwl_priv *priv) { u32 val; unsigned long flags; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); - if (!priv->ict_tbl_vir) + if (!trans_pcie->ict_tbl_vir) return 0; - spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_disable_interrupts(priv); + spin_lock_irqsave(&trans->shrd->lock, flags); + iwl_disable_interrupts(trans); - memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " + IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " "aligned dma address %Lx\n", val, - (unsigned long long)priv->aligned_ict_tbl_dma); + (unsigned long long)trans_pcie->aligned_ict_tbl_dma); - iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->use_ict = true; - priv->ict_index = 0; - iwl_write32(priv, CSR_INT, priv->inta_mask); - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + iwl_write32(priv(trans), CSR_DRAM_INT_TBL_REG, val); + trans_pcie->use_ict = true; + trans_pcie->ict_index = 0; + iwl_write32(priv(trans), CSR_INT, trans_pcie->inta_mask); + iwl_enable_interrupts(trans); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return 0; } /* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_priv *priv) +void iwl_disable_ict(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + unsigned long flags; - spin_lock_irqsave(&priv->shrd->lock, flags); - priv->use_ict = false; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); + trans_pcie->use_ict = false; + spin_unlock_irqrestore(&trans->shrd->lock, flags); } static irqreturn_t iwl_isr(int irq, void *data) { - struct iwl_priv *priv = data; + struct iwl_trans *trans = data; + struct iwl_trans_pcie *trans_pcie; u32 inta, inta_mask; unsigned long flags; #ifdef CONFIG_IWLWIFI_DEBUG u32 inta_fh; #endif - if (!priv) + if (!trans) return IRQ_NONE; - spin_lock_irqsave(&priv->shrd->lock, flags); + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans->shrd->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ + iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); + inta = iwl_read32(priv(trans), CSR_INT); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ if (!inta) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); goto none; } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared. It might have already raised * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); goto unplugged; } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " + if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { + inta_fh = iwl_read32(priv(trans), CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); } #endif - priv->inta |= inta; + trans_pcie->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && - !priv->inta) - iwl_enable_interrupts(priv); + tasklet_schedule(&trans_pcie->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); unplugged: - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) - iwl_enable_interrupts(priv); + if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return IRQ_NONE; } @@ -897,50 +918,53 @@ static irqreturn_t iwl_isr(int irq, void *data) */ irqreturn_t iwl_isr_ict(int irq, void *data) { - struct iwl_priv *priv = data; + struct iwl_trans *trans = data; + struct iwl_trans_pcie *trans_pcie; u32 inta, inta_mask; u32 val = 0; unsigned long flags; - if (!priv) + if (!trans) return IRQ_NONE; + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + /* dram interrupt table not set yet, * use legacy interrupt. */ - if (!priv->use_ict) + if (!trans_pcie->use_ict) return iwl_isr(irq, data); - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ + iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->ict_tbl[priv->ict_index]) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) { + IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); goto none; } /* read all entries that not 0 start with ict_index */ - while (priv->ict_tbl[priv->ict_index]) { + while (trans_pcie->ict_tbl[trans_pcie->ict_index]) { - val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); - IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->ict_index, + val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); + IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", + trans_pcie->ict_index, le32_to_cpu( - priv->ict_tbl[priv->ict_index])); - priv->ict_tbl[priv->ict_index] = 0; - priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, - ICT_COUNT); + trans_pcie->ict_tbl[trans_pcie->ict_index])); + trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; + trans_pcie->ict_index = + iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); } @@ -959,34 +983,35 @@ irqreturn_t iwl_isr_ict(int irq, void *data) val |= 0x8000; inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", inta, inta_mask, val); - inta &= priv->inta_mask; - priv->inta |= inta; + inta &= trans_pcie->inta_mask; + trans_pcie->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && - !priv->inta) { + tasklet_schedule(&trans_pcie->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + !trans_pcie->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. */ - iwl_enable_interrupts(priv); + iwl_enable_interrupts(trans); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) - iwl_enable_interrupts(priv); + if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); return IRQ_NONE; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 621b9a822090..687a09226e6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -711,7 +711,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) if (iwl_is_rfkill(priv)) { wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(priv); + iwl_enable_interrupts(trans(priv)); return -ERFKILL; } @@ -730,7 +730,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) /* clear (again), then enable host interrupts */ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); + iwl_enable_interrupts(trans(priv)); /* really make sure rfkill handshake bits are cleared */ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); @@ -931,19 +931,14 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) { - unsigned long flags; - /* stop and reset the on-board processor */ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->shrd->lock, flags); - iwl_trans_sync_irq(trans(priv)); + iwl_trans_disable_sync_irq(trans(priv)); /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); + iwl_disable_ict(trans(priv)); /* * If a HW restart happens during firmware loading, @@ -1132,19 +1127,20 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_priv *priv = priv(trans); int err; - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); + trans_pcie->inta_mask = CSR_INI_SET_MASK; - iwl_alloc_isr_ict(priv); + tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)trans); + + iwl_alloc_isr_ict(trans); err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, priv); + DRV_NAME, trans); if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); - iwl_free_isr_ict(priv); + IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); + iwl_free_isr_ict(trans); return err; } @@ -1152,17 +1148,25 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) return 0; } -static void iwl_trans_pcie_sync_irq(struct iwl_priv *priv) +static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) { + unsigned long flags; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans->shrd->lock, flags); + iwl_disable_interrupts(trans); + spin_unlock_irqrestore(&trans->shrd->lock, flags); + /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus->irq); - tasklet_kill(&priv->irq_tasklet); + synchronize_irq(bus(trans)->irq); + tasklet_kill(&trans_pcie->irq_tasklet); } static void iwl_trans_pcie_free(struct iwl_priv *priv) { - free_irq(priv->bus->irq, priv); - iwl_free_isr_ict(priv); + free_irq(priv->bus->irq, trans(priv)); + iwl_free_isr_ict(trans(priv)); kfree(trans(priv)); trans(priv) = NULL; } @@ -1191,7 +1195,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) { bool hw_rfkill = false; - iwl_enable_interrupts(priv(trans)); + iwl_enable_interrupts(trans); if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) @@ -1500,7 +1504,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .kick_nic = iwl_trans_pcie_kick_nic, - .sync_irq = iwl_trans_pcie_sync_irq, + .disable_sync_irq = iwl_trans_pcie_disable_sync_irq, .free = iwl_trans_pcie_free, .dbgfs_register = iwl_trans_pcie_dbgfs_register, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c12763c1a3a8..b4c7166a70e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -94,10 +94,9 @@ struct iwl_shared; * ready and a successful ADDBA response has been received. * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run - * @sync_irq: the upper layer will typically disable interrupt and call this - * handler. After this handler returns, it is guaranteed that all - * the ISR / tasklet etc... have finished running and the transport - * layer shall not pass any Rx. + * @disable_sync_irq: Disable and sync: after this handler returns, it is + * guaranteed that all the ISR / tasklet etc... have finished running + * and the transport layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... * @dbgfs_register: add the dbgfs files under this directory. Files will be @@ -132,7 +131,7 @@ struct iwl_trans_ops { void (*kick_nic)(struct iwl_priv *priv); - void (*sync_irq)(struct iwl_priv *priv); + void (*disable_sync_irq)(struct iwl_trans *trans); void (*free)(struct iwl_priv *priv); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); @@ -232,9 +231,9 @@ static inline void iwl_trans_kick_nic(struct iwl_trans *trans) trans->ops->kick_nic(priv(trans)); } -static inline void iwl_trans_sync_irq(struct iwl_trans *trans) +static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) { - trans->ops->sync_irq(priv(trans)); + trans->ops->disable_sync_irq(trans); } static inline void iwl_trans_free(struct iwl_trans *trans) From 7ff94706a055f3e21710b08ffbe3979d7db615db Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:54 -0700 Subject: [PATCH 071/129] iwlagn: move the NIC error flow to the transport layer It is transport dependent, move to the PCIe transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 358 ---------------- drivers/net/wireless/iwlwifi/iwl-core.c | 38 -- drivers/net/wireless/iwlwifi/iwl-core.h | 4 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 42 -- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 6 + .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 396 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 40 ++ 7 files changed, 442 insertions(+), 442 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ca6bb7b1c96d..f6884a54b7f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1308,364 +1308,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) release_firmware(ucode_raw); } -static const char * const desc_lookup_text[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT_WDG", - "SYSASSERT", - "FATAL_ERROR", - "BAD_COMMAND", - "HW_ERROR_TUNE_LOCK", - "HW_ERROR_TEMPERATURE", - "ILLEGAL_CHAN_FREQ", - "VCC_NOT_STABLE", - "FH_ERROR", - "NMI_INTERRUPT_HOST", - "NMI_INTERRUPT_ACTION_PT", - "NMI_INTERRUPT_UNKNOWN", - "UCODE_VERSION_MISMATCH", - "HW_ERROR_ABS_LOCK", - "HW_ERROR_CAL_LOCK_FAIL", - "NMI_INTERRUPT_INST_ACTION_PT", - "NMI_INTERRUPT_DATA_ACTION_PT", - "NMI_TRM_HW_ER", - "NMI_INTERRUPT_TRM", - "NMI_INTERRUPT_BREAK_POINT", - "DEBUG_0", - "DEBUG_1", - "DEBUG_2", - "DEBUG_3", -}; - -static struct { char *name; u8 num; } advanced_lookup[] = { - { "NMI_INTERRUPT_WDG", 0x34 }, - { "SYSASSERT", 0x35 }, - { "UCODE_VERSION_MISMATCH", 0x37 }, - { "BAD_COMMAND", 0x38 }, - { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, - { "FATAL_ERROR", 0x3D }, - { "NMI_TRM_HW_ERR", 0x46 }, - { "NMI_INTERRUPT_TRM", 0x4C }, - { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, - { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, - { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, - { "NMI_INTERRUPT_HOST", 0x66 }, - { "NMI_INTERRUPT_ACTION_PT", 0x7C }, - { "NMI_INTERRUPT_UNKNOWN", 0x84 }, - { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, - { "ADVANCED_SYSASSERT", 0 }, -}; - -static const char *desc_lookup(u32 num) -{ - int i; - int max = ARRAY_SIZE(desc_lookup_text); - - if (num < max) - return desc_lookup_text[num]; - - max = ARRAY_SIZE(advanced_lookup) - 1; - for (i = 0; i < max; i++) { - if (advanced_lookup[i].num == num) - break; - } - return advanced_lookup[i].name; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -void iwl_dump_nic_error_log(struct iwl_priv *priv) -{ - u32 base; - struct iwl_error_event_table table; - - base = priv->device_pointers.error_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_errlog_ptr; - } else { - if (!base) - base = priv->inst_errlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, - "Not valid error log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return; - } - - iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); - - if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); - IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->shrd->status, table.valid); - } - - priv->isr_stats.err_code = table.error_id; - - trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, - table.data1, table.data2, table.line, - table.blink1, table.blink2, table.ilink1, - table.ilink2, table.bcon_time, table.gp1, - table.gp2, table.gp3, table.ucode_ver, - table.hw_ver, table.brd_ver); - IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, - desc_lookup(table.error_id)); - IWL_ERR(priv, "0x%08X | uPc\n", table.pc); - IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); - IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); - IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); - IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); - IWL_ERR(priv, "0x%08X | data1\n", table.data1); - IWL_ERR(priv, "0x%08X | data2\n", table.data2); - IWL_ERR(priv, "0x%08X | line\n", table.line); - IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); - IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); - IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); - IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); - IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); - IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); - IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); - IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); - IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); - IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); -} - -#define EVENT_START_OFFSET (4 * sizeof(u32)) - -/** - * iwl_print_event_log - Dump error event log to syslog - * - */ -static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode, - int pos, char **buf, size_t bufsz) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - unsigned long reg_flags; - - if (num_events == 0) - return pos; - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_evtlog_ptr; - } else { - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (mode == 0) - event_size = 2 * sizeof(u32); - else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - - /* Set starting address; reads will auto-increment */ - iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); - rmb(); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (mode == 0) { - /* data, ev */ - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOG:0x%08x:%04u\n", - time, ev); - } else { - trace_iwlwifi_dev_ucode_event(priv, 0, - time, ev); - IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", - time, ev); - } - } else { - data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - } else { - IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - trace_iwlwifi_dev_ucode_event(priv, time, - data, ev); - } - } - } - - /* Allow device to power down */ - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return pos; -} - -/** - * iwl_print_last_event_logs - Dump the newest # of event log to syslog - */ -static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, - u32 num_wraps, u32 next_entry, - u32 size, u32 mode, - int pos, char **buf, size_t bufsz) -{ - /* - * display the newest DEFAULT_LOG_ENTRIES entries - * i.e the entries just before the next ont that uCode would fill. - */ - if (num_wraps) { - if (next_entry < size) { - pos = iwl_print_event_log(priv, - capacity - (size - next_entry), - size - next_entry, mode, - pos, buf, bufsz); - pos = iwl_print_event_log(priv, 0, - next_entry, mode, - pos, buf, bufsz); - } else - pos = iwl_print_event_log(priv, next_entry - size, - size, mode, pos, buf, bufsz); - } else { - if (next_entry < size) { - pos = iwl_print_event_log(priv, 0, next_entry, - mode, pos, buf, bufsz); - } else { - pos = iwl_print_event_log(priv, next_entry - size, - size, mode, pos, buf, bufsz); - } - } - return pos; -} - -#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) - -int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, - char **buf, bool display) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - u32 size; /* # entries that we'll print */ - u32 logsize; - int pos = 0; - size_t bufsz = 0; - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - logsize = priv->init_evtlog_size; - if (!base) - base = priv->init_evtlog_ptr; - } else { - logsize = priv->inst_evtlog_size; - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, - "Invalid event log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return -EINVAL; - } - - /* event log header */ - capacity = iwl_read_targ_mem(priv, base); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - - if (capacity > logsize) { - IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, logsize); - capacity = logsize; - } - - if (next_entry > logsize) { - IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, logsize); - next_entry = logsize; - } - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return pos; - } - - /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) && !full_log) - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#else - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#endif - IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", - size); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - if (full_log) - bufsz = capacity * 48; - else - bufsz = size * 48; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - } - if ((iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) || full_log) { - /* - * if uCode has wrapped back to top of log, - * start at the oldest entry, - * i.e the next one that uCode would fill. - */ - if (num_wraps) - pos = iwl_print_event_log(priv, next_entry, - capacity - next_entry, mode, - pos, buf, bufsz); - /* (then/else) start at top of log */ - pos = iwl_print_event_log(priv, 0, - next_entry, mode, pos, buf, bufsz); - } else - pos = iwl_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#else - pos = iwl_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#endif - return pos; -} - static void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d77af6969a5b..88fc39619214 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -902,44 +902,6 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) } } -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -void iwl_irq_handle_error(struct iwl_priv *priv) -{ - /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ - if (priv->cfg->internal_wimax_coex && - (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & - APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(priv, APMG_PS_CTRL_REG) & - APMG_PS_CTRL_VAL_RESET_REQ))) { - /* - * Keep the restart process from trying to send host - * commands by clearing the ready bit. - */ - clear_bit(STATUS_READY, &priv->shrd->status); - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - wake_up_interruptible(&priv->wait_command_queue); - IWL_ERR(priv, "RF is used by WiMAX\n"); - return; - } - - IWL_ERR(priv, "Loaded firmware version: %s\n", - priv->hw->wiphy->fw_version); - - iwl_dump_nic_error_log(priv); - iwl_dump_csr(priv); - iwl_dump_fh(priv, NULL, false); - iwl_dump_nic_event_log(priv, false, NULL, false); -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) - iwl_print_rx_config_cmd(priv, - &priv->contexts[IWL_RXON_CTX_BSS]); -#endif - - iwlagn_fw_error(priv, false); -} - static int iwl_apm_stop_master(struct iwl_priv *priv) { int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 797fefa1bf2a..aa6211837b48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -266,7 +266,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, void iwl_connection_init_rx_config(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_set_rate(struct iwl_priv *priv); -void iwl_irq_handle_error(struct iwl_priv *priv); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, @@ -376,9 +375,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, /***************************************************** * Error Handling Debugging ******************************************************/ -void iwl_dump_nic_error_log(struct iwl_priv *priv); -int iwl_dump_nic_event_log(struct iwl_priv *priv, - bool full_log, char **buf, bool display); void iwl_dump_csr(struct iwl_priv *priv); int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d3223214a801..fa070de2840c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -442,46 +442,6 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, return ret; } -static ssize_t iwl_dbgfs_log_event_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -ENOMEM; - - ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - } - return ret; -} - -static ssize_t iwl_dbgfs_log_event_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - u32 event_log_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &event_log_flag) != 1) - return -EFAULT; - if (event_log_flag == 1) - iwl_dump_nic_event_log(priv, true, NULL, false); - - return count; -} - - - static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -870,7 +830,6 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_FILE_OPS(wowlan_sram); -DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(channels); @@ -2509,7 +2468,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 7e2f954c95f2..4694c462ed4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -141,6 +141,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); +/***************************************************** +* Error handling +******************************************************/ +int iwl_dump_nic_event_log(struct iwl_priv *priv, + bool full_log, char **buf, bool display); + static inline void iwl_disable_interrupts(struct iwl_trans *trans) { clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 15e2645c2fb3..aa7ced4324b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -496,6 +496,402 @@ static void iwl_rx_handle(struct iwl_trans *trans) iwlagn_rx_queue_restock(trans); } +static const char * const desc_lookup_text[] = { + "OK", + "FAIL", + "BAD_PARAM", + "BAD_CHECKSUM", + "NMI_INTERRUPT_WDG", + "SYSASSERT", + "FATAL_ERROR", + "BAD_COMMAND", + "HW_ERROR_TUNE_LOCK", + "HW_ERROR_TEMPERATURE", + "ILLEGAL_CHAN_FREQ", + "VCC_NOT_STABLE", + "FH_ERROR", + "NMI_INTERRUPT_HOST", + "NMI_INTERRUPT_ACTION_PT", + "NMI_INTERRUPT_UNKNOWN", + "UCODE_VERSION_MISMATCH", + "HW_ERROR_ABS_LOCK", + "HW_ERROR_CAL_LOCK_FAIL", + "NMI_INTERRUPT_INST_ACTION_PT", + "NMI_INTERRUPT_DATA_ACTION_PT", + "NMI_TRM_HW_ER", + "NMI_INTERRUPT_TRM", + "NMI_INTERRUPT_BREAK_POINT", + "DEBUG_0", + "DEBUG_1", + "DEBUG_2", + "DEBUG_3", +}; + +static struct { char *name; u8 num; } advanced_lookup[] = { + { "NMI_INTERRUPT_WDG", 0x34 }, + { "SYSASSERT", 0x35 }, + { "UCODE_VERSION_MISMATCH", 0x37 }, + { "BAD_COMMAND", 0x38 }, + { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, + { "FATAL_ERROR", 0x3D }, + { "NMI_TRM_HW_ERR", 0x46 }, + { "NMI_INTERRUPT_TRM", 0x4C }, + { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, + { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, + { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, + { "NMI_INTERRUPT_HOST", 0x66 }, + { "NMI_INTERRUPT_ACTION_PT", 0x7C }, + { "NMI_INTERRUPT_UNKNOWN", 0x84 }, + { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, + { "ADVANCED_SYSASSERT", 0 }, +}; + +static const char *desc_lookup(u32 num) +{ + int i; + int max = ARRAY_SIZE(desc_lookup_text); + + if (num < max) + return desc_lookup_text[num]; + + max = ARRAY_SIZE(advanced_lookup) - 1; + for (i = 0; i < max; i++) { + if (advanced_lookup[i].num == num) + break; + } + return advanced_lookup[i].name; +} + +#define ERROR_START_OFFSET (1 * sizeof(u32)) +#define ERROR_ELEM_SIZE (7 * sizeof(u32)) + +static void iwl_dump_nic_error_log(struct iwl_priv *priv) +{ + u32 base; + struct iwl_error_event_table table; + + base = priv->device_pointers.error_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_errlog_ptr; + } else { + if (!base) + base = priv->inst_errlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Not valid error log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return; + } + + iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); + + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->shrd->status, table.valid); + } + + priv->isr_stats.err_code = table.error_id; + + trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, + table.data1, table.data2, table.line, + table.blink1, table.blink2, table.ilink1, + table.ilink2, table.bcon_time, table.gp1, + table.gp2, table.gp3, table.ucode_ver, + table.hw_ver, table.brd_ver); + IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + desc_lookup(table.error_id)); + IWL_ERR(priv, "0x%08X | uPc\n", table.pc); + IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(priv, "0x%08X | data1\n", table.data1); + IWL_ERR(priv, "0x%08X | data2\n", table.data2); + IWL_ERR(priv, "0x%08X | line\n", table.line); + IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); +} + +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +static void iwl_irq_handle_error(struct iwl_priv *priv) +{ + /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ + if (priv->cfg->internal_wimax_coex && + (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & + APMS_CLK_VAL_MRB_FUNC_MODE) || + (iwl_read_prph(priv, APMG_PS_CTRL_REG) & + APMG_PS_CTRL_VAL_RESET_REQ))) { + /* + * Keep the restart process from trying to send host + * commands by clearing the ready bit. + */ + clear_bit(STATUS_READY, &priv->shrd->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); + wake_up_interruptible(&priv->wait_command_queue); + IWL_ERR(priv, "RF is used by WiMAX\n"); + return; + } + + IWL_ERR(priv, "Loaded firmware version: %s\n", + priv->hw->wiphy->fw_version); + + iwl_dump_nic_error_log(priv); + iwl_dump_csr(priv); + iwl_dump_fh(priv, NULL, false); + iwl_dump_nic_event_log(priv, false, NULL, false); +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) + iwl_print_rx_config_cmd(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); +#endif + + iwlagn_fw_error(priv, false); +} + +#define EVENT_START_OFFSET (4 * sizeof(u32)) + +/** + * iwl_print_event_log - Dump error event log to syslog + * + */ +static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode, + int pos, char **buf, size_t bufsz) +{ + u32 i; + u32 base; /* SRAM byte address of event log header */ + u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ + u32 ptr; /* SRAM byte address of log data */ + u32 ev, time, data; /* event log data */ + unsigned long reg_flags; + + if (num_events == 0) + return pos; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_evtlog_ptr; + } else { + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (mode == 0) + event_size = 2 * sizeof(u32); + else + event_size = 3 * sizeof(u32); + + ptr = base + EVENT_START_OFFSET + (start_idx * event_size); + + /* Make sure device is powered up for SRAM reads */ + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + + /* Set starting address; reads will auto-increment */ + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + rmb(); + + /* "time" is actually "data" for mode 0 (no timestamp). + * place event id # at far right for easier visual parsing. */ + for (i = 0; i < num_events; i++) { + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (mode == 0) { + /* data, ev */ + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOG:0x%08x:%04u\n", + time, ev); + } else { + trace_iwlwifi_dev_ucode_event(priv, 0, + time, ev); + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", + time, ev); + } + } else { + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + } else { + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + trace_iwlwifi_dev_ucode_event(priv, time, + data, ev); + } + } + } + + /* Allow device to power down */ + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return pos; +} + +/** + * iwl_print_last_event_logs - Dump the newest # of event log to syslog + */ +static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, + u32 num_wraps, u32 next_entry, + u32 size, u32 mode, + int pos, char **buf, size_t bufsz) +{ + /* + * display the newest DEFAULT_LOG_ENTRIES entries + * i.e the entries just before the next ont that uCode would fill. + */ + if (num_wraps) { + if (next_entry < size) { + pos = iwl_print_event_log(priv, + capacity - (size - next_entry), + size - next_entry, mode, + pos, buf, bufsz); + pos = iwl_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); + } else + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } else { + if (next_entry < size) { + pos = iwl_print_event_log(priv, 0, next_entry, + mode, pos, buf, bufsz); + } else { + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } + } + return pos; +} + +#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) + +int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display) +{ + u32 base; /* SRAM byte address of event log header */ + u32 capacity; /* event log capacity in # entries */ + u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ + u32 num_wraps; /* # times uCode wrapped to top of log */ + u32 next_entry; /* index of next entry to be written by uCode */ + u32 size; /* # entries that we'll print */ + u32 logsize; + int pos = 0; + size_t bufsz = 0; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + logsize = priv->init_evtlog_size; + if (!base) + base = priv->init_evtlog_ptr; + } else { + logsize = priv->inst_evtlog_size; + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Invalid event log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return -EINVAL; + } + + /* event log header */ + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + + if (capacity > logsize) { + IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", + capacity, logsize); + capacity = logsize; + } + + if (next_entry > logsize) { + IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", + next_entry, logsize); + next_entry = logsize; + } + + size = num_wraps ? capacity : next_entry; + + /* bail out if nothing in log */ + if (size == 0) { + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); + return pos; + } + + /* enable/disable bt channel inhibition */ + priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (!(iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) && !full_log) + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#else + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#endif + IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", + size); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + if (full_log) + bufsz = capacity * 48; + else + bufsz = size * 48; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + } + if ((iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) || full_log) { + /* + * if uCode has wrapped back to top of log, + * start at the oldest entry, + * i.e the next one that uCode would fill. + */ + if (num_wraps) + pos = iwl_print_event_log(priv, next_entry, + capacity - next_entry, mode, + pos, buf, bufsz); + /* (then/else) start at top of log */ + pos = iwl_print_event_log(priv, 0, + next_entry, mode, pos, buf, bufsz); + } else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#endif + return pos; +} + /* tasklet for iwlagn interrupt */ void iwl_irq_tasklet(struct iwl_trans *trans) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 687a09226e6d..5926cac711b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1458,7 +1458,46 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } +static ssize_t iwl_dbgfs_log_event_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_trans *trans = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -ENOMEM; + + ret = pos = iwl_dump_nic_event_log(priv(trans), true, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + } + return ret; +} + +static ssize_t iwl_dbgfs_log_event_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_trans *trans = file->private_data; + u32 event_log_flag; + char buf[8]; + int buf_size; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &event_log_flag) != 1) + return -EFAULT; + if (event_log_flag == 1) + iwl_dump_nic_event_log(priv(trans), true, NULL, false); + + return count; +} + DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); +DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_READ_FILE_OPS(tx_queue); @@ -1472,6 +1511,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); + DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); return 0; } #else From dd5b6d0a2059027366028630746d951b1e1e24b3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:55 -0700 Subject: [PATCH 072/129] iwlagn: enable 11n aggregation without checking traffic load Enable HT aggregation when it reach reasonable traffic without checking traffic load which delay enabling the aggregation and lower the throughput but this behavior can be overwrite by module parameter this address https://bugzilla.kernel.org/show_bug.cgi?id=40042 Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 82fb55bc0b28..6cfd23620973 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -612,6 +612,7 @@ struct iwl_mod_params iwlagn_mod_params = { .power_level = IWL_POWER_INDEX_1, .bt_ch_announce = 1, .wanted_ucode_alternative = 1, + .auto_agg = true, /* the rest are 0 by default */ }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cff6442ab0c0..3870b723c8c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -420,7 +420,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, load = rs_tl_get_load(lq_data, tid); - if (load > IWL_AGG_LOAD_THRESHOLD) { + if ((iwlagn_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); ret = ieee80211_start_tx_ba_session(sta, tid, 5000); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f6884a54b7f8..be2ba4ddb92c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3588,6 +3588,11 @@ module_param_named(power_level, iwlagn_mod_params.power_level, MODULE_PARM_DESC(power_level, "default power save level (range from 1 - 5, default: 1)"); +module_param_named(auto_agg, iwlagn_mod_params.auto_agg, + bool, S_IRUGO); +MODULE_PARM_DESC(auto_agg, + "enable agg w/o check traffic load (default: enable)"); + /* * For now, keep using power level 1 instead of automatically * adjusting ... diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a5ef79bb275a..ec71ec7e1fc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -93,6 +93,7 @@ struct iwl_mod_params { int ant_coupling; bool bt_ch_announce; int wanted_ucode_alternative; + bool auto_agg; /* def: true = enable agg. without check */ }; /** From 6a9ae0dc1d4ed6a2007aea14e41d9ba0ae1e3fd4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:56 -0700 Subject: [PATCH 073/129] iwlagn: support small form factor SKU of 6205 Different subsystem ID Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-pci.c | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9487d9b550ca..c2cba80fb73f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -396,6 +396,12 @@ struct iwl_cfg iwl6005_2bg_cfg = { IWL_DEVICE_6005, }; +struct iwl_cfg iwl6005_2agn_sff_cfg = { + .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN", + IWL_DEVICE_6005, + .ht_params = &iwl6000_ht_params, +}; + #define IWL_DEVICE_6030 \ .fw_name_pre = IWL6030_FW_PRE, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ea2a5fe8da8f..d2fa77adbf22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -76,6 +76,7 @@ extern struct iwl_cfg iwl5150_abg_cfg; extern struct iwl_cfg iwl6005_2agn_cfg; extern struct iwl_cfg iwl6005_2abg_cfg; extern struct iwl_cfg iwl6005_2bg_cfg; +extern struct iwl_cfg iwl6005_2agn_sff_cfg; extern struct iwl_cfg iwl1030_bgn_cfg; extern struct iwl_cfg iwl1030_bg_cfg; extern struct iwl_cfg iwl6030_2agn_cfg; diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 4b990907f26f..191c16adeeb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -260,6 +260,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, /* 6x30 Series */ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, From fee84f0dc45f40eabbddf619d5ec18d456c5185a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:57 -0700 Subject: [PATCH 074/129] iwlagn: more comments for bt channel inhibition Add comments for better description Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 6cfd23620973..57839cab92ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -610,7 +610,7 @@ struct iwl_mod_params iwlagn_mod_params = { .bt_coex_active = true, .no_sleep_autoadjust = true, .power_level = IWL_POWER_INDEX_1, - .bt_ch_announce = 1, + .bt_ch_announce = true, .wanted_ucode_alternative = 1, .auto_agg = true, /* the rest are 0 by default */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index be2ba4ddb92c..a79ee7a451d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3542,7 +3542,7 @@ MODULE_PARM_DESC(antenna_coupling, module_param_named(bt_ch_inhibition, iwlagn_mod_params.bt_ch_announce, bool, S_IRUGO); MODULE_PARM_DESC(bt_ch_inhibition, - "Disable BT channel inhibition (default: enable)"); + "Enable BT channel inhibition (default: enable)"); module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ec71ec7e1fc4..6c20d03a2b72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -91,7 +91,7 @@ struct iwl_mod_params { int power_level; /* def: 1 = power level */ u32 debug_level; /* levels are IWL_DL_* */ int ant_coupling; - bool bt_ch_announce; + bool bt_ch_announce; /* def: enable = BT channel inhibition */ int wanted_ucode_alternative; bool auto_agg; /* def: true = enable agg. without check */ }; From e4ef84d94b0dbb75b4da6628611341af5812360f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:10:58 -0700 Subject: [PATCH 075/129] iwlagn: add comments to module parameters Add more comments to iwl_mod_params Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 56 ++++++++++++++++------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 6c20d03a2b72..fd9a9224edfc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -74,26 +74,48 @@ struct iwl_trans_ops; extern struct iwl_mod_params iwlagn_mod_params; +/** + * struct iwl_mod_params + * @sw_crypto: using hardware encryption, default = 0 + * @num_of_queues: number of tx queue, HW dependent + * @disable_11n: 11n capabilities enabled, default = 0 + * @amsdu_size_8K: enable 8K amsdu size, default = 1 + * @antenna: both antennas (use diversity), default = 0 + * @restart_fw: restart firmware, default = 1 + * @plcp_check: enable plcp health check, default = true + * @ack_check: disable ack health check, default = false + * @wd_disable: enable stuck queue check, default = false + * @bt_coex_active: enable bt coex, default = true + * @led_mode: system default, default = 0 + * @no_sleep_autoadjust: disable autoadjust, default = true + * @power_save: disable power save, default = false + * @power_level: power level, default = 1 + * @debug_level: levels are IWL_DL_* + * @ant_coupling: antenna coupling in dB, default = 0 + * @bt_ch_announce: BT channel inhibition, default = enable + * @wanted_ucode_alternative: ucode alternative to use, default = 1 + * @auto_agg: enable agg. without check, default = true + */ struct iwl_mod_params { - int sw_crypto; /* def: 0 = using hardware encryption */ - int num_of_queues; /* def: HW dependent */ - int disable_11n; /* def: 0 = 11n capabilities enabled */ - int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ - int antenna; /* def: 0 = both antennas (use diversity) */ - int restart_fw; /* def: 1 = restart firmware */ - bool plcp_check; /* def: true = enable plcp health check */ - bool ack_check; /* def: false = disable ack health check */ - bool wd_disable; /* def: false = enable stuck queue check */ - bool bt_coex_active; /* def: true = enable bt coex */ - int led_mode; /* def: 0 = system default */ - bool no_sleep_autoadjust; /* def: true = disable autoadjust */ - bool power_save; /* def: false = disable power save */ - int power_level; /* def: 1 = power level */ - u32 debug_level; /* levels are IWL_DL_* */ + int sw_crypto; + int num_of_queues; + int disable_11n; + int amsdu_size_8K; + int antenna; + int restart_fw; + bool plcp_check; + bool ack_check; + bool wd_disable; + bool bt_coex_active; + int led_mode; + bool no_sleep_autoadjust; + bool power_save; + int power_level; + u32 debug_level; int ant_coupling; - bool bt_ch_announce; /* def: enable = BT channel inhibition */ + bool bt_ch_announce; int wanted_ucode_alternative; - bool auto_agg; /* def: true = enable agg. without check */ + bool auto_agg; }; /** From 1f7b6172db86e9ab2b4cd794441bb2c40ab287fc Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:10:59 -0700 Subject: [PATCH 076/129] iwlagn: move isr_statistics to transport layer It is accessed by the transport layer only, hence the move. The debugfs handlers that accessed it moved to the transport layer too. The rx_handlers part of it stayed in the upper layer and a special debugfs has been added for it Also add missing includes to iwl-commands.h. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 3 + drivers/net/wireless/iwlwifi/iwl-core.c | 5 -- drivers/net/wireless/iwlwifi/iwl-core.h | 2 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 54 +++--------- drivers/net/wireless/iwlwifi/iwl-dev.h | 23 +---- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 19 ++++ .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 27 +++--- drivers/net/wireless/iwlwifi/iwl-trans.c | 88 +++++++++++++++++++ 9 files changed, 140 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 0016c61b3000..86b974804ead 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -69,6 +69,9 @@ #ifndef __iwl_commands_h__ #define __iwl_commands_h__ +#include +#include + struct iwl_priv; /* uCode version contains 4 values: Major/Minor/API/Serial */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 88fc39619214..347cbec935b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1121,11 +1121,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) &statistics_cmd); } -void iwl_clear_isr_stats(struct iwl_priv *priv) -{ - memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); -} - int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index aa6211837b48..110ffaea0949 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -387,8 +387,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif -void iwl_clear_isr_stats(struct iwl_priv *priv); - /***************************************************** * GEOS ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index fa070de2840c..787dae5fec99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -556,11 +556,12 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_interrupt_read(struct file *file, +static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; + int pos = 0; int cnt = 0; char *buf; @@ -573,61 +574,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, return -ENOMEM; } - pos += scnprintf(buf + pos, bufsz - pos, - "Interrupt Statistics Report:\n"); - - pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", - priv->isr_stats.hw); - pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", - priv->isr_stats.sw); - if (priv->isr_stats.sw || priv->isr_stats.hw) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tLast Restarting Code: 0x%X\n", - priv->isr_stats.err_code); - } -#ifdef CONFIG_IWLWIFI_DEBUG - pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", - priv->isr_stats.sch); - pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", - priv->isr_stats.alive); -#endif - pos += scnprintf(buf + pos, bufsz - pos, - "HW RF KILL switch toggled:\t %u\n", - priv->isr_stats.rfkill); - - pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", - priv->isr_stats.ctkill); - - pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", - priv->isr_stats.wakeup); - - pos += scnprintf(buf + pos, bufsz - pos, - "Rx command responses:\t\t %u\n", - priv->isr_stats.rx); for (cnt = 0; cnt < REPLY_MAX; cnt++) { - if (priv->isr_stats.rx_handlers[cnt] > 0) + if (priv->rx_handlers_stats[cnt] > 0) pos += scnprintf(buf + pos, bufsz - pos, "\tRx handler[%36s]:\t\t %u\n", get_cmd_string(cnt), - priv->isr_stats.rx_handlers[cnt]); + priv->rx_handlers_stats[cnt]); } - pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", - priv->isr_stats.tx); - - pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", - priv->isr_stats.unhandled); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; } -static ssize_t iwl_dbgfs_interrupt_write(struct file *file, +static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; + char buf[8]; int buf_size; u32 reset_flag; @@ -639,7 +604,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, if (sscanf(buf, "%x", &reset_flag) != 1) return -EFAULT; if (reset_flag == 0) - iwl_clear_isr_stats(priv); + memset(&priv->rx_handlers_stats[0], 0, + sizeof(priv->rx_handlers_stats)); return count; } @@ -834,7 +800,7 @@ DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); -DEBUGFS_READ_WRITE_FILE_OPS(interrupt); +DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers); DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); @@ -2471,7 +2437,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 40a01c0e4f30..f3852edaccf5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -810,22 +810,6 @@ enum iwl_pa_type { IWL_PA_INTERNAL = 1, }; -/* interrupt statistics */ -struct isr_statistics { - u32 hw; - u32 sw; - u32 err_code; - u32 sch; - u32 alive; - u32 rfkill; - u32 ctkill; - u32 wakeup; - u32 rx; - u32 rx_handlers[REPLY_MAX]; - u32 tx; - u32 unhandled; -}; - /* reply_tx_statistics (for _agn devices) */ struct reply_tx_error_statistics { u32 pp_delay; @@ -1155,6 +1139,9 @@ struct iwl_priv { /* jiffies when last recovery from statistics was performed */ unsigned long rx_statistics_jiffies; + /*counters */ + u32 rx_handlers_stats[REPLY_MAX]; + /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; @@ -1258,10 +1245,6 @@ struct iwl_priv { struct traffic_stats tx_stats; struct traffic_stats rx_stats; - /* counts interrupts */ - /* TODO: move to the transport layer */ - struct isr_statistics isr_stats; - struct iwl_power_mgr power_data; struct iwl_tt_mgmt thermal_throttle; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index a5e4ddad2e04..d7c7c93b2daf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1020,7 +1020,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) * handle those that need handling via function in * rx_handlers table. See iwl_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; + priv->rx_handlers_stats[pkt->hdr.cmd]++; priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 4694c462ed4e..f60b26f4dc7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -32,6 +32,24 @@ /*This file includes the declaration that are internal to the * trans_pcie layer */ +/** + * struct isr_statistics - interrupt statistics + * + */ +struct isr_statistics { + u32 hw; + u32 sw; + u32 err_code; + u32 sch; + u32 alive; + u32 rfkill; + u32 ctkill; + u32 wakeup; + u32 rx; + u32 tx; + u32 unhandled; +}; + /** * struct iwl_rx_queue - Rx queue * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) @@ -88,6 +106,7 @@ struct iwl_trans_pcie { u32 inta; bool use_ict; struct tasklet_struct irq_tasklet; + struct isr_statistics isr_stats; u32 inta_mask; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index aa7ced4324b8..b1635eee24b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -569,6 +569,9 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) { u32 base; struct iwl_error_event_table table; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); base = priv->device_pointers.error_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { @@ -596,7 +599,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) priv->shrd->status, table.valid); } - priv->isr_stats.err_code = table.error_id; + trans_pcie->isr_stats.err_code = table.error_id; trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, table.data1, table.data2, table.line, @@ -905,6 +908,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct isr_statistics *isr_stats = &trans_pcie->isr_stats; + spin_lock_irqsave(&trans->shrd->lock, flags); @@ -945,7 +950,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(trans); - priv(trans)->isr_stats.hw++; + isr_stats->hw++; iwl_irq_handle_error(priv(trans)); handled |= CSR_INT_BIT_HW_ERR; @@ -959,13 +964,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " "the frame/frames.\n"); - priv(trans)->isr_stats.sch++; + isr_stats->sch++; } /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) { IWL_DEBUG_ISR(trans, "Alive interrupt\n"); - priv(trans)->isr_stats.alive++; + isr_stats->alive++; } } #endif @@ -982,7 +987,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); - priv(trans)->isr_stats.rfkill++; + isr_stats->rfkill++; /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio @@ -1006,7 +1011,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { IWL_ERR(trans, "Microcode CT kill error detected.\n"); - priv(trans)->isr_stats.ctkill++; + isr_stats->ctkill++; handled |= CSR_INT_BIT_CT_KILL; } @@ -1014,7 +1019,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(trans, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); - priv(trans)->isr_stats.sw++; + isr_stats->sw++; iwl_irq_handle_error(priv(trans)); handled |= CSR_INT_BIT_SW_ERR; } @@ -1027,7 +1032,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) iwl_txq_update_write_ptr(priv(trans), &priv(trans)->txq[i]); - priv(trans)->isr_stats.wakeup++; + isr_stats->wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -1075,14 +1080,14 @@ void iwl_irq_tasklet(struct iwl_trans *trans) iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); - priv(trans)->isr_stats.rx++; + isr_stats->rx++; } /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); - priv(trans)->isr_stats.tx++; + isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ priv(trans)->ucode_write_complete = 1; @@ -1091,7 +1096,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (inta & ~handled) { IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv(trans)->isr_stats.unhandled++; + isr_stats->unhandled++; } if (inta & ~(trans_pcie->inta_mask)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 5926cac711b3..63a310135f76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1496,8 +1496,95 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_interrupt_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_trans *trans = file->private_data; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct isr_statistics *isr_stats = &trans_pcie->isr_stats; + + int pos = 0; + char *buf; + int bufsz = 24 * 64; /* 24 items * 64 char per item */ + ssize_t ret; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(trans, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + pos += scnprintf(buf + pos, bufsz - pos, + "Interrupt Statistics Report:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", + isr_stats->hw); + pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", + isr_stats->sw); + if (isr_stats->sw || isr_stats->hw) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tLast Restarting Code: 0x%X\n", + isr_stats->err_code); + } +#ifdef CONFIG_IWLWIFI_DEBUG + pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", + isr_stats->sch); + pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", + isr_stats->alive); +#endif + pos += scnprintf(buf + pos, bufsz - pos, + "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill); + + pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", + isr_stats->ctkill); + + pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", + isr_stats->wakeup); + + pos += scnprintf(buf + pos, bufsz - pos, + "Rx command responses:\t\t %u\n", isr_stats->rx); + + pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", + isr_stats->tx); + + pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", + isr_stats->unhandled); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_interrupt_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_trans *trans = file->private_data; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct isr_statistics *isr_stats = &trans_pcie->isr_stats; + + char buf[8]; + int buf_size; + u32 reset_flag; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%x", &reset_flag) != 1) + return -EFAULT; + if (reset_flag == 0) + memset(isr_stats, 0, sizeof(*isr_stats)); + + return count; +} + DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_WRITE_FILE_OPS(log_event); +DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_READ_FILE_OPS(tx_queue); @@ -1512,6 +1599,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); return 0; } #else From a0eaad713f6fc1f63fe293ad6ce63cb01e05c03c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:00 -0700 Subject: [PATCH 077/129] iwlagn: reclaim the packets in transport layer The reclaim flow is really transport related. Define a simple API to allow the upper layer to request from the transport layer to reclaim packets until an index written in the Tx response / BA notification. The transport layer prepares a list of the packets that are being freed and passes this list to the upper layer. Between the two layers, the CB of the skb is used to pass a pointer to the context (BSS / PAN) in which the skb was sent. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 271 +--------- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 506 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn.h | 8 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 + drivers/net/wireless/iwlwifi/iwl-helpers.h | 6 + .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 55 ++ drivers/net/wireless/iwlwifi/iwl-trans.c | 31 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 10 + 8 files changed, 411 insertions(+), 481 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 57839cab92ae..52ddb49d2017 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -42,12 +42,6 @@ #include "iwl-trans.h" #include "iwl-shared.h" -static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) -{ - return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & MAX_SN; -} - static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) { status &= TX_STATUS_MSK; @@ -125,7 +119,7 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) } } -static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) { status &= AGG_TX_STATUS_MSK; @@ -172,11 +166,10 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) } } -static void iwlagn_set_tx_status(struct iwl_priv *priv, +void iwlagn_set_tx_status(struct iwl_priv *priv, struct ieee80211_tx_info *info, - struct iwl_rxon_context *ctx, struct iwlagn_tx_resp *tx_resp, - int txq_id, bool is_agg) + bool is_agg) { u16 status = le16_to_cpu(tx_resp->status.status); @@ -188,20 +181,6 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, info); if (!iwl_is_tx_success(status)) iwlagn_count_tx_err_status(priv, status); - - if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && - iwl_is_associated_ctx(ctx) && ctx->vif && - ctx->vif->type == NL80211_IFTYPE_STATION) { - ctx->last_tx_rejected = true; - iwl_stop_queue(priv, &priv->txq[txq_id]); - } - - IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " - "0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); } #ifdef CONFIG_IWLWIFI_DEBUG @@ -231,157 +210,6 @@ const char *iwl_get_agg_tx_fail_reason(u16 status) } #endif /* CONFIG_IWLWIFI_DEBUG */ -static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwlagn_tx_resp *tx_resp, - int txq_id, u16 start_idx) -{ - u16 status; - struct agg_tx_status *frame_status = &tx_resp->status; - struct ieee80211_hdr *hdr = NULL; - int i, sh, idx; - u16 seq; - - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); - - agg->frame_count = tx_resp->frame_count; - agg->start_idx = start_idx; - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - agg->bitmap = 0; - - /* # frames attempted by Tx command */ - if (agg->frame_count == 1) { - struct iwl_tx_info *txb; - - /* Only one frame was attempted; no block-ack will arrive */ - idx = start_idx; - - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); - txb = &priv->txq[txq_id].txb[idx]; - iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), - txb->ctx, tx_resp, txq_id, true); - agg->wait_for_ba = 0; - } else { - /* Two or more frames were attempted; expect block-ack */ - u64 bitmap = 0; - - /* - * Start is the lowest frame sent. It may not be the first - * frame in the batch; we figure this out dynamically during - * the following loop. - */ - int start = agg->start_idx; - - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < agg->frame_count; i++) { - u16 sc; - status = le16_to_cpu(frame_status[i].status); - seq = le16_to_cpu(frame_status[i].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); - - if (status & AGG_TX_STATUS_MSK) - iwlagn_count_agg_tx_err_status(priv, status); - - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; - - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", - agg->frame_count, txq_id, idx); - IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " - "try-count (0x%08x)\n", - iwl_get_agg_tx_fail_reason(status), - status & AGG_TX_STATUS_MSK, - status & AGG_TX_TRY_MSK); - - hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); - if (!hdr) { - IWL_ERR(priv, - "BUG_ON idx doesn't point to valid skb" - " idx=%d, txq_id=%d\n", idx, txq_id); - return -1; - } - - sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERR(priv, - "BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", - idx, SEQ_TO_SN(sc), - hdr->seq_ctrl); - return -1; - } - - IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", - i, idx, SEQ_TO_SN(sc)); - - /* - * sh -> how many frames ahead of the starting frame is - * the current one? - * - * Note that all frames sent in the batch must be in a - * 64-frame window, so this number should be in [0,63]. - * If outside of this window, then we've found a new - * "first" frame in the batch and need to change start. - */ - sh = idx - start; - - /* - * If >= 64, out of window. start must be at the front - * of the circular buffer, idx must be near the end of - * the buffer, and idx is the new "first" frame. Shift - * the indices around. - */ - if (sh >= 64) { - /* Shift bitmap by start - idx, wrapped */ - sh = 0x100 - idx + start; - bitmap = bitmap << sh; - /* Now idx is the new start so sh = 0 */ - sh = 0; - start = idx; - /* - * If <= -64 then wraps the 256-pkt circular buffer - * (e.g., start = 255 and idx = 0, sh should be 1) - */ - } else if (sh <= -64) { - sh = 0x100 - start + idx; - /* - * If < 0 but > -64, out of window. idx is before start - * but not wrapped. Shift the indices around. - */ - } else if (sh < 0) { - /* Shift by how far start is ahead of idx */ - sh = start - idx; - bitmap = bitmap << sh; - /* Now idx is the new start so sh = 0 */ - start = idx; - sh = 0; - } - /* Sequence number start + sh was sent in this batch */ - bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", - start, (unsigned long long)bitmap); - } - - /* - * Store the bitmap and possibly the new start, if we wrapped - * the buffer above - */ - agg->bitmap = bitmap; - agg->start_idx = start; - IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", - agg->frame_count, agg->start_idx, - (unsigned long long)agg->bitmap); - - if (bitmap) - agg->wait_for_ba = 1; - } - return 0; -} - void iwl_check_abort_status(struct iwl_priv *priv, u8 frame_count, u32 status) { @@ -392,99 +220,6 @@ void iwl_check_abort_status(struct iwl_priv *priv, } } -void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_info *info; - struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - struct ieee80211_hdr *hdr; - struct iwl_tx_info *txb; - u32 status = le16_to_cpu(tx_resp->status.status); - int tid; - int sta_id; - int freed; - unsigned long flags; - - if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) " - "index %d is out of range [0-%d] %d %d\n", __func__, - txq_id, index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - txq->time_stamp = jiffies; - txb = &txq->txb[txq->q.read_ptr]; - info = IEEE80211_SKB_CB(txb->skb); - memset(&info->status, 0, sizeof(info->status)); - - tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> - IWLAGN_TX_RES_TID_POS; - sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> - IWLAGN_TX_RES_RA_POS; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - - hdr = (void *)txb->skb->data; - if (!ieee80211_is_data_qos(hdr->frame_control)) - priv->last_seq_ctl = tx_resp->seq_ctl; - - if (txq->sched_retry) { - const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); - struct iwl_ht_agg *agg; - - agg = &priv->stations[sta_id].tid[tid].agg; - /* - * If the BT kill count is non-zero, we'll get this - * notification again. - */ - if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { - IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n"); - } - iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - - /* check if BAR is needed */ - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (txq->q.read_ptr != (scd_ssn & 0xff)) { - index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " - "scd_ssn=%d idx=%d txq=%d swq=%d\n", - scd_ssn , index, txq_id, txq->swq_id); - - freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq); - } - } else { - iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, - txq_id, false); - freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - iwl_queue_space(&txq->q) > txq->q.low_mark && - status != TX_STATUS_FAIL_PASSIVE_NO_RX) - iwl_wake_queue(priv, txq); - } - - iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); - - iwl_check_abort_status(priv, tx_resp->frame_count, status); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); -} - int iwlagn_hw_valid_rtc_data_addr(u32 addr) { return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 0e9deb7b64d3..b56a269aa5f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "iwl-dev.h" #include "iwl-core.h" @@ -696,126 +697,6 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, rcu_read_unlock(); } -static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info, - bool is_agg) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; - - if (!is_agg) - iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1); - - ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); -} - -int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct iwl_tx_info *tx_info; - int nfreed = 0; - struct ieee80211_hdr *hdr; - - if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { - IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " - "index %d is out of range [0-%d] %d %d.\n", __func__, - txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); - return 0; - } - - for (index = iwl_queue_inc_wrap(index, q->n_bd); - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - tx_info = &txq->txb[txq->q.read_ptr]; - - if (WARN_ON_ONCE(tx_info->skb == NULL)) - continue; - - hdr = (struct ieee80211_hdr *)tx_info->skb->data; - if (ieee80211_is_data_qos(hdr->frame_control)) - nfreed++; - - iwlagn_tx_status(priv, tx_info, - txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); - tx_info->skb = NULL; - - iwlagn_txq_inval_byte_cnt_tbl(priv, txq); - - iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr); - } - return nfreed; -} - -/** - * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack - * - * Go through block-ack's bitmap of ACK'd frames, update driver's record of - * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. - */ -static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl_compressed_ba_resp *ba_resp) - -{ - int sh; - u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - struct ieee80211_tx_info *info; - u64 bitmap, sent_bitmap; - - if (unlikely(!agg->wait_for_ba)) { - if (unlikely(ba_resp->bitmap)) - IWL_ERR(priv, "Received BA when not expected\n"); - return -EINVAL; - } - - /* Mark that the expected block-ack response arrived */ - agg->wait_for_ba = 0; - IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); - - /* Calculate shift to align block-ack bits with our Tx window bits */ - sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); - if (sh < 0) - sh += 0x100; - - /* - * Check for success or failure according to the - * transmitted bitmap and block-ack bitmap - */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - sent_bitmap = bitmap & agg->bitmap; - - /* Sanity check values reported by uCode */ - if (ba_resp->txed_2_done > ba_resp->txed) { - IWL_DEBUG_TX_REPLY(priv, - "bogus sent(%d) and ack(%d) count\n", - ba_resp->txed, ba_resp->txed_2_done); - /* - * set txed_2_done = txed, - * so it won't impact rate scale - */ - ba_resp->txed = ba_resp->txed_2_done; - } - IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", - ba_resp->txed, ba_resp->txed_2_done); - - /* Find the first ACKed frame to store the TX status */ - while (sent_bitmap && !(sent_bitmap & 1)) { - agg->start_idx = (agg->start_idx + 1) & 0xff; - sent_bitmap >>= 1; - } - - info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); - memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; - info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_len = ba_resp->txed_2_done; - info->status.ampdu_len = ba_resp->txed; - iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); - - return 0; -} - /** * translate ucode response to mac80211 tx status control values */ @@ -839,97 +720,6 @@ void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); } -/** - * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA - * - * Handles block-acknowledge notification from device, which reports success - * of frames sent via aggregation. - */ -void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; - struct iwl_tx_queue *txq = NULL; - struct iwl_ht_agg *agg; - int index; - int sta_id; - int tid; - unsigned long flags; - - /* "flow" corresponds to Tx queue */ - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - - /* "ssn" is start of block-ack Tx window, corresponds to index - * (in Tx queue's circular buffer) of first TFD/frame in window */ - u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - - if (scd_flow >= hw_params(priv).max_txq_num) { - IWL_ERR(priv, - "BUG_ON scd_flow is bigger than number of queues\n"); - return; - } - - txq = &priv->txq[scd_flow]; - sta_id = ba_resp->sta_id; - tid = ba_resp->tid; - agg = &priv->stations[sta_id].tid[tid].agg; - if (unlikely(agg->txq_id != scd_flow)) { - /* - * FIXME: this is a uCode bug which need to be addressed, - * log the information and return for now! - * since it is possible happen very often and in order - * not to fill the syslog, don't enable the logging by default - */ - IWL_DEBUG_TX_REPLY(priv, - "BA scd_flow %d does not match txq_id %d\n", - scd_flow, agg->txq_id); - return; - } - - /* Find index just before block-ack window */ - index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - - IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " - "sta_id = %d\n", - agg->wait_for_ba, - (u8 *) &ba_resp->sta_addr_lo32, - ba_resp->sta_id); - IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " - "%d, scd_ssn = %d\n", - ba_resp->tid, - ba_resp->seq_ctl, - (unsigned long long)le64_to_cpu(ba_resp->bitmap), - ba_resp->scd_flow, - ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", - agg->start_idx, - (unsigned long long)agg->bitmap); - - /* Update driver's record of ACK vs. not for each frame in window */ - iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); - - /* Release all TFDs before the SSN, i.e. all TFDs in front of - * block-ack window (we assume that they've been successfully - * transmitted ... if not, it's too late anyway). */ - if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { - /* calculate mac80211 ampdu sw queue to wake */ - int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && - priv->mac80211_registered && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq); - - iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); - } - - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); -} - #ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_get_tx_fail_reason(u32 status) { @@ -969,3 +759,297 @@ const char *iwl_get_tx_fail_reason(u32 status) #undef TX_STATUS_POSTPONE } #endif /* CONFIG_IWLWIFI_DEBUG */ + +static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, + struct iwlagn_tx_resp *tx_resp) +{ + struct agg_tx_status *frame_status = &tx_resp->status; + int tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> + IWLAGN_TX_RES_TID_POS; + int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> + IWLAGN_TX_RES_RA_POS; + struct iwl_ht_agg *agg = &priv->stations[sta_id].tid[tid].agg; + u32 status = le16_to_cpu(tx_resp->status.status); + int i; + + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, + "got tx response w/o block-ack\n"); + + agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + agg->wait_for_ba = (tx_resp->frame_count > 1); + + /* + * If the BT kill count is non-zero, we'll get this + * notification again. + */ + if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && + priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); + } + + /* Construct bit-map of pending frames within Tx window */ + for (i = 0; i < tx_resp->frame_count; i++) { + u16 fstatus = le16_to_cpu(frame_status[i].status); + + if (status & AGG_TX_STATUS_MSK) + iwlagn_count_agg_tx_err_status(priv, fstatus); + + if (status & (AGG_TX_STATE_FEW_BYTES_MSK | + AGG_TX_STATE_ABORT_MSK)) + continue; + + IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " + "try-count (0x%08x)\n", + iwl_get_agg_tx_fail_reason(fstatus), + fstatus & AGG_TX_STATUS_MSK, + fstatus & AGG_TX_TRY_MSK); + } +} + +static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) +{ + return le32_to_cpup((__le32 *)&tx_resp->status + + tx_resp->frame_count) & MAX_SN; +} + +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int cmd_index = SEQ_TO_INDEX(sequence); + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct ieee80211_hdr *hdr; + u32 status = le16_to_cpu(tx_resp->status.status); + u32 ssn = iwlagn_get_scd_ssn(tx_resp); + int tid; + int sta_id; + int freed; + struct ieee80211_tx_info *info; + unsigned long flags; + struct sk_buff_head skbs; + struct sk_buff *skb; + struct iwl_rxon_context *ctx; + + if ((cmd_index >= txq->q.n_bd) || + (iwl_queue_used(&txq->q, cmd_index) == 0)) { + IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) " + "cmd_index %d is out of range [0-%d] %d %d\n", + __func__, txq_id, cmd_index, txq->q.n_bd, + txq->q.write_ptr, txq->q.read_ptr); + return; + } + + txq->time_stamp = jiffies; + + tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> + IWLAGN_TX_RES_TID_POS; + sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> + IWLAGN_TX_RES_RA_POS; + + spin_lock_irqsave(&priv->shrd->sta_lock, flags); + + if (txq->sched_retry) + iwl_rx_reply_tx_agg(priv, tx_resp); + + if (tx_resp->frame_count == 1) { + bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); + + __skb_queue_head_init(&skbs); + /*we can free until ssn % q.n_bd not inclusive */ + iwl_trans_reclaim(trans(priv), txq_id, ssn, status, &skbs); + freed = 0; + while (!skb_queue_empty(&skbs)) { + skb = __skb_dequeue(&skbs); + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_data_qos(hdr->frame_control)) + priv->last_seq_ctl = tx_resp->seq_ctl; + + info = IEEE80211_SKB_CB(skb); + ctx = info->driver_data[0]; + + memset(&info->status, 0, sizeof(info->status)); + + if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && + iwl_is_associated_ctx(ctx) && ctx->vif && + ctx->vif->type == NL80211_IFTYPE_STATION) { + ctx->last_tx_rejected = true; + iwl_stop_queue(priv, &priv->txq[txq_id]); + + IWL_DEBUG_TX_REPLY(priv, + "TXQ %d status %s (0x%08x) " + "rate_n_flags 0x%x retries %d\n", + txq_id, + iwl_get_tx_fail_reason(status), + status, + le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); + + IWL_DEBUG_TX_REPLY(priv, + "FrameCnt = %d, idx=%d\n", + tx_resp->frame_count, cmd_index); + } + + /* check if BAR is needed */ + if (is_agg && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), + tx_resp, is_agg); + if (!is_agg) + iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); + + ieee80211_tx_status_irqsafe(priv->hw, skb); + + freed++; + } + + WARN_ON(!is_agg && freed != 1); + + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); + } + + iwl_check_abort_status(priv, tx_resp->frame_count, status); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); +} + +/** + * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA + * + * Handles block-acknowledge notification from device, which reports success + * of frames sent via aggregation. + */ +void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; + struct iwl_tx_queue *txq = NULL; + struct iwl_ht_agg *agg; + struct sk_buff_head reclaimed_skbs; + struct ieee80211_tx_info *info; + struct ieee80211_hdr *hdr; + struct sk_buff *skb; + unsigned long flags; + int index; + int sta_id; + int tid; + int freed; + + /* "flow" corresponds to Tx queue */ + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + + /* "ssn" is start of block-ack Tx window, corresponds to index + * (in Tx queue's circular buffer) of first TFD/frame in window */ + u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); + + if (scd_flow >= hw_params(priv).max_txq_num) { + IWL_ERR(priv, + "BUG_ON scd_flow is bigger than number of queues\n"); + return; + } + + txq = &priv->txq[scd_flow]; + sta_id = ba_resp->sta_id; + tid = ba_resp->tid; + agg = &priv->stations[sta_id].tid[tid].agg; + + /* Find index of block-ack window */ + index = ba_resp_scd_ssn & (txq->q.n_bd - 1); + + spin_lock_irqsave(&priv->shrd->sta_lock, flags); + + if (unlikely(agg->txq_id != scd_flow)) { + /* + * FIXME: this is a uCode bug which need to be addressed, + * log the information and return for now! + * since it is possible happen very often and in order + * not to fill the syslog, don't enable the logging by default + */ + IWL_DEBUG_TX_REPLY(priv, + "BA scd_flow %d does not match txq_id %d\n", + scd_flow, agg->txq_id); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + return; + } + + if (unlikely(!agg->wait_for_ba)) { + if (unlikely(ba_resp->bitmap)) + IWL_ERR(priv, "Received BA when not expected\n"); + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + return; + } + + IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " + "sta_id = %d\n", + agg->wait_for_ba, + (u8 *) &ba_resp->sta_addr_lo32, + ba_resp->sta_id); + IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " + "scd_flow = %d, scd_ssn = %d\n", + ba_resp->tid, + ba_resp->seq_ctl, + (unsigned long long)le64_to_cpu(ba_resp->bitmap), + ba_resp->scd_flow, + ba_resp->scd_ssn); + + /* Mark that the expected block-ack response arrived */ + agg->wait_for_ba = 0; + + /* Sanity check values reported by uCode */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + ba_resp->txed = ba_resp->txed_2_done; + } + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); + + __skb_queue_head_init(&reclaimed_skbs); + + /* Release all TFDs before the SSN, i.e. all TFDs in front of + * block-ack window (we assume that they've been successfully + * transmitted ... if not, it's too late anyway). */ + iwl_trans_reclaim(trans(priv), scd_flow, ba_resp_scd_ssn, 0, + &reclaimed_skbs); + freed = 0; + while (!skb_queue_empty(&reclaimed_skbs)) { + + skb = __skb_dequeue(&reclaimed_skbs); + hdr = (struct ieee80211_hdr *)skb->data; + + if (ieee80211_is_data_qos(hdr->frame_control)) + freed++; + else + WARN_ON_ONCE(1); + + if (freed == 0) { + /* this is the first skb we deliver in this batch */ + /* put the rate scaling data there */ + info = IEEE80211_SKB_CB(skb); + memset(&info->status, 0, sizeof(info->status)); + info->flags |= IEEE80211_TX_STAT_ACK; + info->flags |= IEEE80211_TX_STAT_AMPDU; + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; + iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, + info); + } + + ieee80211_tx_status_irqsafe(priv->hw, skb); + } + + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); + + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d2fa77adbf22..f34590765074 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -146,6 +146,11 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwlagn_ucode_type ucode_type); /* lib */ +void iwlagn_set_tx_status(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + struct iwlagn_tx_resp *tx_resp, + bool is_agg); +void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status); void iwl_check_abort_status(struct iwl_priv *priv, u8 frame_count, u32 status); int iwlagn_hw_valid_rtc_data_addr(u32 addr); @@ -178,7 +183,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); +void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs); static inline u32 iwl_tx_status_to_mac80211(u32 status) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f3852edaccf5..022cfc738903 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -166,6 +166,8 @@ struct iwl_tx_info { * @time_stamp: time (in jiffies) of last read_ptr change * @need_update: indicates need to update read/write index * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled + * @sta_id: valid if sched_retry is set + * @tid: valid if sched_retry is set * * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * descriptors) and required locking structures. @@ -184,6 +186,9 @@ struct iwl_tx_queue { u8 sched_retry; u8 active; u8 swq_id; + + u16 sta_id; + u16 tid; }; #define IWL_NUM_SCAN_RATES (2) diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 09ed7af19889..f744fdc39a4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -90,6 +90,9 @@ static inline void iwl_wake_queue(struct iwl_priv *priv, u8 ac = queue & 3; u8 hwq = (queue >> 2) & 0x1f; + if (unlikely(!priv->mac80211_registered)) + return; + if (test_and_clear_bit(hwq, priv->queue_stopped)) if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) ieee80211_wake_queue(priv->hw, ac); @@ -102,6 +105,9 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, u8 ac = queue & 3; u8 hwq = (queue >> 2) & 0x1f; + if (unlikely(!priv->mac80211_registered)) + return; + if (!test_and_set_bit(hwq, priv->queue_stopped)) if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) ieee80211_stop_queue(priv->hw, ac); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 9d7287e7a992..7438aaedbd5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -480,6 +480,9 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + priv->txq[txq_id].sta_id = sta_id; + priv->txq[txq_id].tid = tid; + spin_unlock_irqrestore(&priv->shrd->lock, flags); } @@ -1035,3 +1038,55 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, return iwl_trans_pcie_send_cmd(priv, &cmd); } + +/* Frees buffers until index _not_ inclusive */ +void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs) + +{ + struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_tx_info *tx_info; + struct ieee80211_tx_info *info; + int last_to_free; + + /*Since we free until index _not_ inclusive, the one before index is + * the last we will free. This one must be used */ + last_to_free = iwl_queue_dec_wrap(index, q->n_bd); + + if ((index >= q->n_bd) || + (iwl_queue_used(q, last_to_free) == 0)) { + IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " + "last_to_free %d is out of range [0-%d] %d %d.\n", + __func__, txq_id, last_to_free, q->n_bd, + q->write_ptr, q->read_ptr); + return; + } + + IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id, + q->read_ptr, index); + + if (WARN_ON(!skb_queue_empty(skbs))) + return; + + for (; + q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + + tx_info = &txq->txb[txq->q.read_ptr]; + + if (WARN_ON_ONCE(tx_info->skb == NULL)) + continue; + + info = IEEE80211_SKB_CB(tx_info->skb); + info->driver_data[0] = tx_info->ctx; + + __skb_queue_tail(skbs, tx_info->skb); + + tx_info->skb = NULL; + + iwlagn_txq_inval_byte_cnt_tbl(priv(trans), txq); + + iwlagn_txq_free_tfd(priv(trans), txq, txq->q.read_ptr); + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 63a310135f76..06cec8268c6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1106,7 +1106,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, * regardless of the value of ret. "ret" only indicates * whether or not we should update the write pointer. */ - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { + if (iwl_queue_space(q) < q->high_mark) { if (wait_write_ptr) { txq->need_update = 1; iwl_txq_update_write_ptr(priv, txq); @@ -1148,6 +1148,34 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) return 0; } +static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, + int ssn, u32 status, struct sk_buff_head *skbs) +{ + struct iwl_priv *priv = priv(trans); + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + /* n_bd is usually 256 => n_bd - 1 = 0xff */ + int tfd_num = ssn & (txq->q.n_bd - 1); + u8 agg_state; + bool cond; + + if (txq->sched_retry) { + agg_state = + priv->stations[txq->sta_id].tid[txq->tid].agg.state; + cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); + } else { + cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); + } + + if (txq->q.read_ptr != tfd_num) { + IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " + "scd_ssn=%d idx=%d txq=%d swq=%d\n", + ssn , tfd_num, txq_id, txq->swq_id); + iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); + if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) + iwl_wake_queue(priv, txq); + } +} + static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) { unsigned long flags; @@ -1626,6 +1654,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .get_tx_cmd = iwl_trans_pcie_get_tx_cmd, .tx = iwl_trans_pcie_tx, + .reclaim = iwl_trans_pcie_reclaim, .txq_agg_disable = iwl_trans_pcie_txq_agg_disable, .txq_agg_setup = iwl_trans_pcie_txq_agg_setup, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index b4c7166a70e3..519ad91bda1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -90,6 +90,7 @@ struct iwl_shared; * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb + * @reclaim: free packet until ssn. Returns a list of freed packets. * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. * @txq_agg_disable: de-configure a Tx queue to send AMPDUs @@ -123,6 +124,8 @@ struct iwl_trans_ops { int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, + u32 status, struct sk_buff_head *skbs); int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); @@ -213,6 +216,13 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, return trans->ops->tx(priv(trans), skb, tx_cmd, txq_id, fc, ampdu, ctx); } +static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, + int ssn, u32 status, + struct sk_buff_head *skbs) +{ + trans->ops->reclaim(trans, txq_id, ssn, status, skbs); +} + static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { From 04e1cabe4294fdf744489deb1e91edb1ec02e9a4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:01 -0700 Subject: [PATCH 078/129] iwlagn: move reclaim related functions Now that the reclaim flow has been moved to the transport layer, a lot of functions can be made static or don't need to be exported outside the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 193 ----------------- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 197 +++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.h | 19 -- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 6 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 9 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 7 - 6 files changed, 200 insertions(+), 231 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 52ddb49d2017..bca5f99377ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -42,184 +42,6 @@ #include "iwl-trans.h" #include "iwl-shared.h" -static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) -{ - status &= TX_STATUS_MSK; - - switch (status) { - case TX_STATUS_POSTPONE_DELAY: - priv->reply_tx_stats.pp_delay++; - break; - case TX_STATUS_POSTPONE_FEW_BYTES: - priv->reply_tx_stats.pp_few_bytes++; - break; - case TX_STATUS_POSTPONE_BT_PRIO: - priv->reply_tx_stats.pp_bt_prio++; - break; - case TX_STATUS_POSTPONE_QUIET_PERIOD: - priv->reply_tx_stats.pp_quiet_period++; - break; - case TX_STATUS_POSTPONE_CALC_TTAK: - priv->reply_tx_stats.pp_calc_ttak++; - break; - case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: - priv->reply_tx_stats.int_crossed_retry++; - break; - case TX_STATUS_FAIL_SHORT_LIMIT: - priv->reply_tx_stats.short_limit++; - break; - case TX_STATUS_FAIL_LONG_LIMIT: - priv->reply_tx_stats.long_limit++; - break; - case TX_STATUS_FAIL_FIFO_UNDERRUN: - priv->reply_tx_stats.fifo_underrun++; - break; - case TX_STATUS_FAIL_DRAIN_FLOW: - priv->reply_tx_stats.drain_flow++; - break; - case TX_STATUS_FAIL_RFKILL_FLUSH: - priv->reply_tx_stats.rfkill_flush++; - break; - case TX_STATUS_FAIL_LIFE_EXPIRE: - priv->reply_tx_stats.life_expire++; - break; - case TX_STATUS_FAIL_DEST_PS: - priv->reply_tx_stats.dest_ps++; - break; - case TX_STATUS_FAIL_HOST_ABORTED: - priv->reply_tx_stats.host_abort++; - break; - case TX_STATUS_FAIL_BT_RETRY: - priv->reply_tx_stats.bt_retry++; - break; - case TX_STATUS_FAIL_STA_INVALID: - priv->reply_tx_stats.sta_invalid++; - break; - case TX_STATUS_FAIL_FRAG_DROPPED: - priv->reply_tx_stats.frag_drop++; - break; - case TX_STATUS_FAIL_TID_DISABLE: - priv->reply_tx_stats.tid_disable++; - break; - case TX_STATUS_FAIL_FIFO_FLUSHED: - priv->reply_tx_stats.fifo_flush++; - break; - case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: - priv->reply_tx_stats.insuff_cf_poll++; - break; - case TX_STATUS_FAIL_PASSIVE_NO_RX: - priv->reply_tx_stats.fail_hw_drop++; - break; - case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: - priv->reply_tx_stats.sta_color_mismatch++; - break; - default: - priv->reply_tx_stats.unknown++; - break; - } -} - -void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) -{ - status &= AGG_TX_STATUS_MSK; - - switch (status) { - case AGG_TX_STATE_UNDERRUN_MSK: - priv->reply_agg_tx_stats.underrun++; - break; - case AGG_TX_STATE_BT_PRIO_MSK: - priv->reply_agg_tx_stats.bt_prio++; - break; - case AGG_TX_STATE_FEW_BYTES_MSK: - priv->reply_agg_tx_stats.few_bytes++; - break; - case AGG_TX_STATE_ABORT_MSK: - priv->reply_agg_tx_stats.abort++; - break; - case AGG_TX_STATE_LAST_SENT_TTL_MSK: - priv->reply_agg_tx_stats.last_sent_ttl++; - break; - case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: - priv->reply_agg_tx_stats.last_sent_try++; - break; - case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: - priv->reply_agg_tx_stats.last_sent_bt_kill++; - break; - case AGG_TX_STATE_SCD_QUERY_MSK: - priv->reply_agg_tx_stats.scd_query++; - break; - case AGG_TX_STATE_TEST_BAD_CRC32_MSK: - priv->reply_agg_tx_stats.bad_crc32++; - break; - case AGG_TX_STATE_RESPONSE_MSK: - priv->reply_agg_tx_stats.response++; - break; - case AGG_TX_STATE_DUMP_TX_MSK: - priv->reply_agg_tx_stats.dump_tx++; - break; - case AGG_TX_STATE_DELAY_TX_MSK: - priv->reply_agg_tx_stats.delay_tx++; - break; - default: - priv->reply_agg_tx_stats.unknown++; - break; - } -} - -void iwlagn_set_tx_status(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwlagn_tx_resp *tx_resp, - bool is_agg) -{ - u16 status = le16_to_cpu(tx_resp->status.status); - - info->status.rates[0].count = tx_resp->failure_frame + 1; - if (is_agg) - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_tx_status_to_mac80211(status); - iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), - info); - if (!iwl_is_tx_success(status)) - iwlagn_count_tx_err_status(priv, status); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x - -const char *iwl_get_agg_tx_fail_reason(u16 status) -{ - status &= AGG_TX_STATUS_MSK; - switch (status) { - case AGG_TX_STATE_TRANSMITTED: - return "SUCCESS"; - AGG_TX_STATE_FAIL(UNDERRUN_MSK); - AGG_TX_STATE_FAIL(BT_PRIO_MSK); - AGG_TX_STATE_FAIL(FEW_BYTES_MSK); - AGG_TX_STATE_FAIL(ABORT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); - AGG_TX_STATE_FAIL(SCD_QUERY_MSK); - AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); - AGG_TX_STATE_FAIL(RESPONSE_MSK); - AGG_TX_STATE_FAIL(DUMP_TX_MSK); - AGG_TX_STATE_FAIL(DELAY_TX_MSK); - } - - return "UNKNOWN"; -} -#endif /* CONFIG_IWLWIFI_DEBUG */ - -void iwl_check_abort_status(struct iwl_priv *priv, - u8 frame_count, u32 status) -{ - if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { - IWL_ERR(priv, "Tx flush command to flush out all frames\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - queue_work(priv->shrd->workqueue, &priv->tx_flush); - } -} - int iwlagn_hw_valid_rtc_data_addr(u32 addr) { return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && @@ -812,21 +634,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, vif->bss_conf.bssid); } -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed) -{ - lockdep_assert_held(&priv->shrd->sta_lock); - - if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->stations[sta_id].tid[tid].tfds_in_queue, - freed); - priv->stations[sta_id].tid[tid].tfds_in_queue = 0; - } -} - #define IWL_FLUSH_WAIT_MS 2000 int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index b56a269aa5f4..e95f9c61f95a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -638,7 +638,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return 0; } -int iwlagn_txq_check_empty(struct iwl_priv *priv, +static int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) { struct iwl_queue *q = &priv->txq[txq_id].q; @@ -700,7 +700,7 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, /** * translate ucode response to mac80211 tx status control values */ -void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, +static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info) { struct ieee80211_tx_rate *r = &info->control.rates[0]; @@ -760,6 +760,53 @@ const char *iwl_get_tx_fail_reason(u32 status) } #endif /* CONFIG_IWLWIFI_DEBUG */ +static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= AGG_TX_STATUS_MSK; + + switch (status) { + case AGG_TX_STATE_UNDERRUN_MSK: + priv->reply_agg_tx_stats.underrun++; + break; + case AGG_TX_STATE_BT_PRIO_MSK: + priv->reply_agg_tx_stats.bt_prio++; + break; + case AGG_TX_STATE_FEW_BYTES_MSK: + priv->reply_agg_tx_stats.few_bytes++; + break; + case AGG_TX_STATE_ABORT_MSK: + priv->reply_agg_tx_stats.abort++; + break; + case AGG_TX_STATE_LAST_SENT_TTL_MSK: + priv->reply_agg_tx_stats.last_sent_ttl++; + break; + case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: + priv->reply_agg_tx_stats.last_sent_try++; + break; + case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: + priv->reply_agg_tx_stats.last_sent_bt_kill++; + break; + case AGG_TX_STATE_SCD_QUERY_MSK: + priv->reply_agg_tx_stats.scd_query++; + break; + case AGG_TX_STATE_TEST_BAD_CRC32_MSK: + priv->reply_agg_tx_stats.bad_crc32++; + break; + case AGG_TX_STATE_RESPONSE_MSK: + priv->reply_agg_tx_stats.response++; + break; + case AGG_TX_STATE_DUMP_TX_MSK: + priv->reply_agg_tx_stats.dump_tx++; + break; + case AGG_TX_STATE_DELAY_TX_MSK: + priv->reply_agg_tx_stats.delay_tx++; + break; + default: + priv->reply_agg_tx_stats.unknown++; + break; + } +} + static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, struct iwlagn_tx_resp *tx_resp) { @@ -808,12 +855,158 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, } } +#ifdef CONFIG_IWLWIFI_DEBUG +#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x + +const char *iwl_get_agg_tx_fail_reason(u16 status) +{ + status &= AGG_TX_STATUS_MSK; + switch (status) { + case AGG_TX_STATE_TRANSMITTED: + return "SUCCESS"; + AGG_TX_STATE_FAIL(UNDERRUN_MSK); + AGG_TX_STATE_FAIL(BT_PRIO_MSK); + AGG_TX_STATE_FAIL(FEW_BYTES_MSK); + AGG_TX_STATE_FAIL(ABORT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); + AGG_TX_STATE_FAIL(SCD_QUERY_MSK); + AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); + AGG_TX_STATE_FAIL(RESPONSE_MSK); + AGG_TX_STATE_FAIL(DUMP_TX_MSK); + AGG_TX_STATE_FAIL(DELAY_TX_MSK); + } + + return "UNKNOWN"; +} +#endif /* CONFIG_IWLWIFI_DEBUG */ + static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) { return le32_to_cpup((__le32 *)&tx_resp->status + tx_resp->frame_count) & MAX_SN; } +static void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed) +{ + lockdep_assert_held(&priv->shrd->sta_lock); + + if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + else { + IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", + priv->stations[sta_id].tid[tid].tfds_in_queue, + freed); + priv->stations[sta_id].tid[tid].tfds_in_queue = 0; + } +} + +static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_POSTPONE_DELAY: + priv->reply_tx_stats.pp_delay++; + break; + case TX_STATUS_POSTPONE_FEW_BYTES: + priv->reply_tx_stats.pp_few_bytes++; + break; + case TX_STATUS_POSTPONE_BT_PRIO: + priv->reply_tx_stats.pp_bt_prio++; + break; + case TX_STATUS_POSTPONE_QUIET_PERIOD: + priv->reply_tx_stats.pp_quiet_period++; + break; + case TX_STATUS_POSTPONE_CALC_TTAK: + priv->reply_tx_stats.pp_calc_ttak++; + break; + case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: + priv->reply_tx_stats.int_crossed_retry++; + break; + case TX_STATUS_FAIL_SHORT_LIMIT: + priv->reply_tx_stats.short_limit++; + break; + case TX_STATUS_FAIL_LONG_LIMIT: + priv->reply_tx_stats.long_limit++; + break; + case TX_STATUS_FAIL_FIFO_UNDERRUN: + priv->reply_tx_stats.fifo_underrun++; + break; + case TX_STATUS_FAIL_DRAIN_FLOW: + priv->reply_tx_stats.drain_flow++; + break; + case TX_STATUS_FAIL_RFKILL_FLUSH: + priv->reply_tx_stats.rfkill_flush++; + break; + case TX_STATUS_FAIL_LIFE_EXPIRE: + priv->reply_tx_stats.life_expire++; + break; + case TX_STATUS_FAIL_DEST_PS: + priv->reply_tx_stats.dest_ps++; + break; + case TX_STATUS_FAIL_HOST_ABORTED: + priv->reply_tx_stats.host_abort++; + break; + case TX_STATUS_FAIL_BT_RETRY: + priv->reply_tx_stats.bt_retry++; + break; + case TX_STATUS_FAIL_STA_INVALID: + priv->reply_tx_stats.sta_invalid++; + break; + case TX_STATUS_FAIL_FRAG_DROPPED: + priv->reply_tx_stats.frag_drop++; + break; + case TX_STATUS_FAIL_TID_DISABLE: + priv->reply_tx_stats.tid_disable++; + break; + case TX_STATUS_FAIL_FIFO_FLUSHED: + priv->reply_tx_stats.fifo_flush++; + break; + case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: + priv->reply_tx_stats.insuff_cf_poll++; + break; + case TX_STATUS_FAIL_PASSIVE_NO_RX: + priv->reply_tx_stats.fail_hw_drop++; + break; + case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: + priv->reply_tx_stats.sta_color_mismatch++; + break; + default: + priv->reply_tx_stats.unknown++; + break; + } +} + +static void iwlagn_set_tx_status(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + struct iwlagn_tx_resp *tx_resp, + bool is_agg) +{ + u16 status = le16_to_cpu(tx_resp->status.status); + + info->status.rates[0].count = tx_resp->failure_frame + 1; + if (is_agg) + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->flags |= iwl_tx_status_to_mac80211(status); + iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), + info); + if (!iwl_is_tx_success(status)) + iwlagn_count_tx_err_status(priv, status); +} + +static void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status) +{ + if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { + IWL_ERR(priv, "Tx flush command to flush out all frames\n"); + if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + queue_work(priv->shrd->workqueue, &priv->tx_flush); + } +} + void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f34590765074..c30299da4daf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -121,10 +121,6 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } -/* tx queue */ -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed); - /* RXON */ int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -146,13 +142,6 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwlagn_ucode_type ucode_type); /* lib */ -void iwlagn_set_tx_status(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwlagn_tx_resp *tx_resp, - bool is_agg); -void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status); -void iwl_check_abort_status(struct iwl_priv *priv, - u8 frame_count, u32 status); int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); @@ -169,22 +158,14 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* tx */ -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int index); -void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); -int iwlagn_txq_check_empty(struct iwl_priv *priv, - int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs); static inline u32 iwl_tx_status_to_mac80211(u32 status) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index f60b26f4dc7b..717b6dc38b20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -136,8 +136,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data); * TX / HCMD ******************************************************/ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int index); int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset); @@ -159,6 +157,10 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, int tx_fifo_id, int scd_retry); void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs); /***************************************************** * Error handling diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 7438aaedbd5c..e1f9ceeb02ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -332,13 +332,7 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, return 0; } -/*TODO: this functions should NOT be exported from trans module - export it - * until the reclaim flow will be brought to the transport module too. - * Add a declaration to make sparse happy */ -void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - -void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, +static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; @@ -1042,7 +1036,6 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, /* Frees buffers until index _not_ inclusive */ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, struct sk_buff_head *skbs) - { struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; struct iwl_queue *q = &txq->q; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 519ad91bda1c..7fd0296f155e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -272,11 +272,4 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) ******************************************************/ extern const struct iwl_trans_ops trans_ops_pcie; -/*TODO: this functions should NOT be exported from trans module - export it - * until the reclaim flow will be brought to the transport module too */ - -struct iwl_tx_queue; -void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - #endif /* __iwl_trans_h__ */ From 105183b156b7c220b47c3162e087101a0a6abc9f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:02 -0700 Subject: [PATCH 079/129] iwlagn: move scd_bc_tbls and scd_base_addr to iwl_trans_pcie Needed for PCIe only Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 -- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 4 +++ .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 26 ++++++++++++--- drivers/net/wireless/iwlwifi/iwl-trans.c | 33 ++++++++++++------- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 022cfc738903..ab9816aeb40a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1242,9 +1242,6 @@ struct iwl_priv { struct iwl_tx_queue *txq; unsigned long txq_ctx_active_msk; struct iwl_dma_ptr kw; /* keep warm address */ - struct iwl_dma_ptr scd_bc_tbls; - - u32 scd_base_addr; /* scheduler sram base address */ /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 717b6dc38b20..cb4b59dcfc3b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -91,6 +91,8 @@ struct iwl_rx_queue { * @rxq: all the RX queue data * @rx_replenish: work that will be called when buffers need to be allocated * @trans: pointer to the generic transport area + * @scd_base_addr: scheduler sram base address in SRAM + * @scd_bc_tbls: pointer to the byte count table of the scheduler */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -109,6 +111,8 @@ struct iwl_trans_pcie { struct isr_statistics isr_stats; u32 inta_mask; + u32 scd_base_addr; + struct iwl_dma_ptr scd_bc_tbls; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index e1f9ceeb02ed..a462d697a690 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -45,7 +45,10 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt) { - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); int write_ptr = txq->q.write_ptr; int txq_id = txq->q.id; u8 sec_ctl = 0; @@ -53,6 +56,8 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; __le16 bc_ent; + scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; + WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; @@ -335,12 +340,17 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id = txq->q.id; int read_ptr = txq->q.read_ptr; u8 sta_id = 0; __le16 bc_ent; + scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; + WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); if (txq_id != priv->shrd->cmd_queue) @@ -361,9 +371,13 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, u32 tbl_dw; u16 scd_q2ratid; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; - tbl_dw_addr = priv->scd_base_addr + + tbl_dw_addr = trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); @@ -424,6 +438,10 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, unsigned long flags; struct iwl_tid_data *tid_data; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + if (WARN_ON(sta_id == IWL_INVALID_STATION)) return; if (WARN_ON(tid >= MAX_TID_COUNT)) @@ -459,7 +477,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 06cec8268c6c..0e04b51e7f79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -469,6 +469,9 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) static void iwl_trans_pcie_tx_free(struct iwl_priv *priv) { int txq_id; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); /* Tx queues */ if (priv->txq) { @@ -482,7 +485,7 @@ static void iwl_trans_pcie_tx_free(struct iwl_priv *priv) iwlagn_free_dma_ptr(priv, &priv->kw); - iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); + iwlagn_free_dma_ptr(priv, &trans_pcie->scd_bc_tbls); } /** @@ -496,6 +499,9 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) { int ret; int txq_id, slots_num; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ @@ -504,7 +510,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) goto error; } - ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, + ret = iwlagn_alloc_dma_ptr(priv, &trans_pcie->scd_bc_tbls, hw_params(priv).scd_bc_tbls_size); if (ret) { IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); @@ -785,30 +791,33 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_rxon_context *ctx; + struct iwl_trans *trans = trans(priv); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); u32 a; unsigned long flags; int i, chan; u32 reg_val; - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); - priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + trans_pcie->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; /* reset conext data memory */ - for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; a += 4) iwl_write_targ_mem(priv, a, 0); /* reset tx status memory */ - for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; a += 4) iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + + for (; a < trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(priv).max_txq_num); a += 4) iwl_write_targ_mem(priv, a, 0); iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); + trans_pcie->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) @@ -829,9 +838,9 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) for (i = 0; i < hw_params(priv).max_txq_num; i++) { iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << @@ -843,7 +852,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) } iwl_write_prph(priv, SCD_INTERRUPT_MASK, - IWL_MASK(0, hw_params(priv).max_txq_num)); + IWL_MASK(0, hw_params(trans).max_txq_num)); /* Activate all Tx DMA/FIFO channels */ iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); From effcea16e554b4d7497bbcfc80b9baca8e017691 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:03 -0700 Subject: [PATCH 080/129] iwlagn: fix the check of IWLAGN_FIRST_AMPDU_QUEUE BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != IWLAGN_FIRST_AMPDU_QUEUE); This check can be buggy. IWLAGN_FIRST_AMPDU_QUEUE has to be greater than the ARRAY_SIZE of iwlagn_ipan_queue_to_tx_fifo. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 0e04b51e7f79..a2950a4cc35c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -875,9 +875,9 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < IWLAGN_FIRST_AMPDU_QUEUE); - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < IWLAGN_FIRST_AMPDU_QUEUE); for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { From 845a9c0d8acea87dede740bc5feb9ec2d00505d9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:04 -0700 Subject: [PATCH 081/129] iwlagn: move all iwl_is_XXX helpers to iwl-shared.h Logic move after all priv->status moved to struct iwl_shared Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 ++--- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 66 ------------------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 14 ++-- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 4 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 65 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 4 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 2 +- 14 files changed, 100 insertions(+), 101 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 991977e2e1b0..7ce56ff4a525 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -426,7 +426,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EINVAL; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EBUSY; /* This function hardcodes a bunch of dual-mode assumptions */ @@ -544,7 +544,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (!iwl_is_ready(priv)) { + if (!iwl_is_ready(priv->shrd)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; } @@ -794,7 +794,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); - if (unlikely(!iwl_is_ready(priv))) { + if (unlikely(!iwl_is_ready(priv->shrd))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); mutex_unlock(&priv->shrd->mutex); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 4d02c328c377..8f0b86de1863 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -214,7 +214,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, keyconf->keyidx); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); - if (iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv->shrd)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 03d8389d8ef8..1a39aafb3b05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -511,7 +511,7 @@ static void iwl_bg_ct_enter(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; - if (!iwl_is_ready(priv)) + if (!iwl_is_ready(priv->shrd)) return; if (tt->state != IWL_TI_CT_KILL) { @@ -540,7 +540,7 @@ static void iwl_bg_ct_exit(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; - if (!iwl_is_ready(priv)) + if (!iwl_is_ready(priv->shrd)) return; /* stop ct_kill_exit_tm timer */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index e95f9c61f95a..97d03a85d579 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -338,7 +338,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ctx = iwl_rxon_ctx_from_vif(info->control.vif); spin_lock_irqsave(&priv->shrd->lock, flags); - if (iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv->shrd)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a79ee7a451d1..f559c6362a00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -251,7 +251,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return; iwlagn_send_advance_bt_config(priv); } @@ -268,7 +268,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) goto out; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) goto out; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", @@ -307,7 +307,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return; iwl_send_statistics_request(priv, CMD_ASYNC, false); @@ -444,7 +444,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) return; /* do nothing if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return; IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); @@ -510,7 +510,7 @@ static ssize_t show_temperature(struct device *d, struct iwl_shared *shrd = dev_get_drvdata(d); struct iwl_priv *priv = shrd->priv; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; return sprintf(buf, "%d\n", priv->temperature); @@ -523,7 +523,7 @@ static ssize_t show_tx_power(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return sprintf(buf, "off\n"); else return sprintf(buf, "%d\n", priv->tx_power_user_lmt); @@ -1412,7 +1412,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Enable watchdog to monitor the driver tx queues */ iwl_setup_watchdog(priv); - if (iwl_is_rfkill(priv)) + if (iwl_is_rfkill(priv->shrd)) return -ERFKILL; /* download priority table before any calibration request */ @@ -2701,7 +2701,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); - if (iwl_is_rfkill(priv)) + if (iwl_is_rfkill(priv->shrd)) goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || @@ -2836,7 +2836,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); goto done; } - if (iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv->shrd)) { IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); goto done; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 347cbec935b9..cfc23c25e979 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1051,7 +1051,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return -EIO; /* scan complete and commit_rxon use tx_power_next value, @@ -1131,7 +1131,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, IWL_DEBUG_MAC80211(priv, "enter\n"); - if (!iwl_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv->shrd)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -1237,7 +1237,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) iwlagn_disable_roc(priv); - if (!iwl_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv->shrd)) { IWL_WARN(priv, "Try to add interface when device not ready\n"); err = -EINVAL; goto out; @@ -1657,7 +1657,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&priv->shrd->mutex); - if (!ctx->vif || !iwl_is_ready_rf(priv)) { + if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) { /* * Huh? But wait ... this can maybe happen when * we're in the middle of a firmware restart! diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 110ffaea0949..e5b3c356b392 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -393,72 +393,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, int iwl_init_geos(struct iwl_priv *priv); void iwl_free_geos(struct iwl_priv *priv); -/*************** DRIVER STATUS FUNCTIONS *****/ - -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_CT_KILL 4 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_DEVICE_ENABLED 18 -#define STATUS_CHANNEL_SWITCH_PENDING 19 - - -static inline int iwl_is_ready(struct iwl_priv *priv) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &priv->shrd->status) && - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) && - !test_bit(STATUS_EXIT_PENDING, &priv->shrd->status); -} - -static inline int iwl_is_alive(struct iwl_priv *priv) -{ - return test_bit(STATUS_ALIVE, &priv->shrd->status); -} - -static inline int iwl_is_init(struct iwl_priv *priv) -{ - return test_bit(STATUS_INIT, &priv->shrd->status); -} - -static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->shrd->status); -} - -static inline int iwl_is_rfkill(struct iwl_priv *priv) -{ - return iwl_is_rfkill_hw(priv); -} - -static inline int iwl_is_ctkill(struct iwl_priv *priv) -{ - return test_bit(STATUS_CT_KILL, &priv->shrd->status); -} - -static inline int iwl_is_ready_rf(struct iwl_priv *priv) -{ - - if (iwl_is_rfkill(priv)) - return 0; - - return iwl_is_ready(priv); -} - extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 787dae5fec99..9ca429c23ad1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -740,7 +740,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) return -EINVAL; - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return -EAGAIN; priv->power_data.debug_sleep_level_override = value; @@ -851,7 +851,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, struct statistics_rx_non_phy *delta_general, *max_general; struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1277,7 +1277,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, ssize_t ret; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1471,7 +1471,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1584,7 +1584,7 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, ssize_t ret; struct statistics_bt_activity *bt, *accum_bt; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; if (!priv->bt_enable_flag) @@ -1672,7 +1672,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; ssize_t ret; - if (!iwl_is_alive(priv)) + if (!iwl_is_alive(priv->shrd)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -2259,7 +2259,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, if (sscanf(buf, "%d", &flush) != 1) return -EINVAL; - if (iwl_is_rfkill(priv)) + if (iwl_is_rfkill(priv->shrd)) return -EFAULT; iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 9f0e620fc3a1..2c91a48b8010 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -392,7 +392,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) return 0; - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) return -EIO; /* scan complete use sleep_power_next, need to be updated */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 1a0cb66d7bae..2bb94f7351c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -362,7 +362,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, cancel_delayed_work(&priv->scan_check); - if (!iwl_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv->shrd)) { IWL_WARN(priv, "Request scan called when driver not ready.\n"); return -EIO; } @@ -606,7 +606,7 @@ out_complete: out_settings: /* Can we still talk to firmware ? */ - if (!iwl_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv->shrd)) goto out; iwlagn_post_scan(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index fd9a9224edfc..ff4c04fee429 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -246,4 +246,69 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); +/***************************************************** +* DRIVER STATUS FUNCTIONS +******************************************************/ +#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ +/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_CT_KILL 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_DEVICE_ENABLED 18 +#define STATUS_CHANNEL_SWITCH_PENDING 19 + +static inline int iwl_is_ready(struct iwl_shared *shrd) +{ + /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are + * set but EXIT_PENDING is not */ + return test_bit(STATUS_READY, &shrd->status) && + test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && + !test_bit(STATUS_EXIT_PENDING, &shrd->status); +} + +static inline int iwl_is_alive(struct iwl_shared *shrd) +{ + return test_bit(STATUS_ALIVE, &shrd->status); +} + +static inline int iwl_is_init(struct iwl_shared *shrd) +{ + return test_bit(STATUS_INIT, &shrd->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) +{ + return test_bit(STATUS_RF_KILL_HW, &shrd->status); +} + +static inline int iwl_is_rfkill(struct iwl_shared *shrd) +{ + return iwl_is_rfkill_hw(shrd); +} + +static inline int iwl_is_ctkill(struct iwl_shared *shrd) +{ + return test_bit(STATUS_CT_KILL, &shrd->status); +} + +static inline int iwl_is_ready_rf(struct iwl_shared *shrd) +{ + if (iwl_is_rfkill(shrd)) + return 0; + + return iwl_is_ready(shrd); +} + #endif /* #__iwl_shared_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d4c625c13119..1154e4843087 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -468,7 +468,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, { unsigned long flags; - if (!iwl_is_ready(priv)) { + if (!iwl_is_ready(priv->shrd)) { IWL_DEBUG_INFO(priv, "Unable to remove station %pM, device not ready.\n", addr); @@ -572,7 +572,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int ret; bool send_lq; - if (!iwl_is_ready(priv)) { + if (!iwl_is_ready(priv->shrd)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index a462d697a690..ac2fae12707a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -599,9 +599,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; - if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { + if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv->shrd)) { IWL_WARN(priv, "Not sending command - %s KILL\n", - iwl_is_rfkill(priv) ? "RF" : "CT"); + iwl_is_rfkill(priv->shrd) ? "RF" : "CT"); return -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index a2950a4cc35c..b080e69374ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -715,7 +715,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) else set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); - if (iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv->shrd)) { wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); iwl_enable_interrupts(trans(priv)); return -ERFKILL; From 790428b6552c698b2f295457b5dee686323cb732 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:05 -0700 Subject: [PATCH 082/129] iwlagn: move iwl_free_pages to iwl-shared.h This helper is used by the transport and the upper layer. Kill __iwl_free_pages which was used in the transport only. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 9 --------- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 5 +++++ drivers/net/wireless/iwlwifi/iwl-sta.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 3 ++- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ab9816aeb40a..eac25c507d30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1505,13 +1505,4 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } -static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) -{ - __free_pages(page, hw_params(priv).rx_page_order); -} - -static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) -{ - free_pages(page, hw_params(priv).rx_page_order); -} #endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2bb94f7351c9..fc5af3475392 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -91,7 +91,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) ret = -EIO; } - iwl_free_pages(priv, cmd.reply_page); + iwl_free_pages(priv->shrd, cmd.reply_page); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ff4c04fee429..1229eb3c098c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -229,6 +229,11 @@ static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) } #endif +static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page) +{ + free_pages(page, shrd->hw_params.rx_page_order); +} + struct iwl_rx_mem_buffer { dma_addr_t page_dma; struct page *page; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 1154e4843087..26b2bd4db6b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -177,7 +177,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, pkt = (struct iwl_rx_packet *)cmd.reply_page; ret = iwl_process_add_sta_resp(priv, sta, pkt, true); } - iwl_free_pages(priv, cmd.reply_page); + iwl_free_pages(priv->shrd, cmd.reply_page); return ret; } @@ -455,7 +455,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, break; } } - iwl_free_pages(priv, cmd.reply_page); + iwl_free_pages(priv->shrd, cmd.reply_page); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index ac2fae12707a..ed497247f97e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -1023,7 +1023,7 @@ cancel: } fail: if (cmd->reply_page) { - iwl_free_pages(priv, cmd->reply_page); + iwl_free_pages(priv->shrd, cmd->reply_page); cmd->reply_page = 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index b080e69374ea..89560089a348 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -129,7 +129,8 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); - __iwl_free_pages(priv(trans), rxq->pool[i].page); + __free_pages(rxq->pool[i].page, + hw_params(trans).rx_page_order); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); From 6d8f6eeb350696050a1f5cf8f9d0daabab68eaf5 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:06 -0700 Subject: [PATCH 083/129] iwlagn: transport layer should receive iwl_trans Change a lot of functions to have them receive iwl_trans and not iwl_priv. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 16 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 186 ++++++------- drivers/net/wireless/iwlwifi/iwl-trans.c | 248 +++++++++--------- drivers/net/wireless/iwlwifi/iwl-trans.h | 40 +-- 4 files changed, 251 insertions(+), 239 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index cb4b59dcfc3b..b2af467430a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -140,28 +140,26 @@ irqreturn_t iwl_isr_ict(int irq, void *data); * TX / HCMD ******************************************************/ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, +int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset); -int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, - int count, int slots_num, u32 id); -int iwl_trans_pcie_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, +int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); +int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); +int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt); int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo); -void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index); +void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, +void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index); void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, struct sk_buff_head *skbs); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index ed497247f97e..1704eab8ddf2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -41,12 +41,11 @@ /** * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt) { struct iwlagn_scd_bc_tbl *scd_bc_tbl; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int write_ptr = txq->q.write_ptr; @@ -170,7 +169,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) return tfd->num_tbs & 0x1f; } -static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, +static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { int i; @@ -180,39 +179,39 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, num_tbs = iwl_tfd_get_num_tbs(tfd); if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); + IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); /* @todo issue fatal error, it is quite serious situation */ return; } /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(priv->bus->dev, + dma_unmap_single(bus(trans)->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } /** * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data + * @trans - transport private data * @txq - tx queue * @index - the index of the TFD to be freed * * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, +void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index) { struct iwl_tfd *tfd_tmp = txq->tfds; - iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], + iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], DMA_TO_DEVICE); /* free SKB */ @@ -229,7 +228,7 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, } } -int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, +int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset) @@ -249,7 +248,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, /* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", + IWL_ERR(trans, "Error can not send more than %d chunks\n", IWL_NUM_OF_TBS); return -EINVAL; } @@ -258,7 +257,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, return -EINVAL; if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(priv, "Unaligned address = %llx\n", + IWL_ERR(trans, "Unaligned address = %llx\n", (unsigned long long)addr); iwl_tfd_set_tb(tfd, num_tbs, addr, len); @@ -307,8 +306,7 @@ int iwl_queue_space(const struct iwl_queue *q) /** * iwl_queue_init - Initialize queue's high/low-water and read/write indexes */ -int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, - int count, int slots_num, u32 id) +int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) { q->n_bd = count; q->n_window = slots_num; @@ -337,23 +335,20 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, return 0; } -static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, +static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq) { - struct iwlagn_scd_bc_tbl *scd_bc_tbl; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; int txq_id = txq->q.id; int read_ptr = txq->q.read_ptr; u8 sta_id = 0; __le16 bc_ent; - scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != priv->shrd->cmd_queue) + if (txq_id != trans->shrd->cmd_queue) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -364,14 +359,13 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; } -static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, +static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, u16 txq_id) { u32 tbl_dw_addr; u32 tbl_dw; u16 scd_q2ratid; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -380,34 +374,34 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, tbl_dw_addr = trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(priv(trans), tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(priv(trans), tbl_dw_addr, tbl_dw); return 0; } -static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) +static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, + iwl_write_prph(priv(trans), SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } -void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, +void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index) { - iwl_write_direct32(priv, HBUS_TARG_WRPTR, + iwl_write_direct32(priv(trans), HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv(trans), SCD_QUEUE_RDPTR(txq_id), index); } void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, @@ -459,10 +453,10 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, spin_lock_irqsave(&priv->shrd->lock, flags); /* Stop this Tx queue before configuring it */ - iwlagn_tx_queue_stop_scheduler(priv, txq_id); + iwlagn_tx_queue_stop_scheduler(trans, txq_id); /* Map receiver-address / traffic-ID to this queue */ - iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); + iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); /* Set this queue as a chain-building queue */ iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + @@ -501,6 +495,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { + struct iwl_trans *trans = trans(priv); if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { @@ -512,14 +507,14 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, return -EINVAL; } - iwlagn_tx_queue_stop_scheduler(priv, txq_id); + iwlagn_tx_queue_stop_scheduler(trans, txq_id); iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv, txq_id); @@ -539,8 +534,9 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { + struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq = &priv->txq[priv->shrd->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; @@ -559,14 +555,14 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int trace_idx; #endif - if (test_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - IWL_WARN(priv, "fw recovery, no hcmd send\n"); + if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { + IWL_WARN(trans, "fw recovery, no hcmd send\n"); return -EIO; } if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); + IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n"); return -EIO; } @@ -599,9 +595,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; - if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv->shrd)) { - IWL_WARN(priv, "Not sending command - %s KILL\n", - iwl_is_rfkill(priv->shrd) ? "RF" : "CT"); + if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) { + IWL_WARN(trans, "Not sending command - %s KILL\n", + iwl_is_rfkill(trans->shrd) ? "RF" : "CT"); return -EIO; } @@ -610,10 +606,10 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { spin_unlock_irqrestore(&priv->hcmd_lock, flags); - IWL_ERR(priv, "No space in command queue\n"); + IWL_ERR(trans, "No space in command queue\n"); is_ct_kill = iwl_check_for_ct_kill(priv); if (!is_ct_kill) { - IWL_ERR(priv, "Restarting adapter due to queue full\n"); + IWL_ERR(trans, "Restarting adapter queue is full\n"); iwlagn_fw_error(priv, false); } return -ENOSPC; @@ -634,7 +630,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; out_cmd->hdr.sequence = - cpu_to_le16(QUEUE_TO_SEQ(priv->shrd->cmd_queue) | + cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) | INDEX_TO_SEQ(q->write_ptr)); /* and copy the data that needs to be copied */ @@ -649,16 +645,16 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd_dest += cmd->len[i]; } - IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " + IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, - q->write_ptr, idx, priv->shrd->cmd_queue); + q->write_ptr, idx, trans->shrd->cmd_queue); - phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { + if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -666,7 +662,8 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, copy_size); - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); + iwlagn_txq_attach_buf_to_tfd(trans, txq, + phys_addr, copy_size, 1); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[0] = &out_cmd->hdr; trace_lens[0] = copy_size; @@ -678,17 +675,18 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], + phys_addr = dma_map_single(bus(trans)->dev, + (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(priv->bus->dev, phys_addr)) { - iwlagn_unmap_tfd(priv, out_meta, + if (dma_mapping_error(bus(trans)->dev, phys_addr)) { + iwlagn_unmap_tfd(trans, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, cmd->len[i], 0); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[trace_idx] = cmd->data[i]; @@ -768,17 +766,18 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) int cmd_index; struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; - struct iwl_tx_queue *txq = &priv->txq[priv->shrd->cmd_queue]; + struct iwl_trans *trans = trans(priv); + struct iwl_tx_queue *txq = &priv->txq[trans->shrd->cmd_queue]; unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != priv->shrd->cmd_queue, + if (WARN(txq_id != trans->shrd->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, priv->shrd->cmd_queue, sequence, - priv->txq[priv->shrd->cmd_queue].q.read_ptr, - priv->txq[priv->shrd->cmd_queue].q.write_ptr)) { + txq_id, trans->shrd->cmd_queue, sequence, + priv->txq[trans->shrd->cmd_queue].q.read_ptr, + priv->txq[trans->shrd->cmd_queue].q.write_ptr)) { iwl_print_hex_error(priv, pkt, 32); return; } @@ -787,7 +786,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], + DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { @@ -801,8 +801,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", + clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); + IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } @@ -920,7 +920,7 @@ static void iwl_generic_cmd_callback(struct iwl_priv *priv, #endif } -static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { int ret; @@ -932,77 +932,77 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!cmd->callback) cmd->callback = iwl_generic_cmd_callback; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) return -EBUSY; - ret = iwl_enqueue_hcmd(priv, cmd); + ret = iwl_enqueue_hcmd(trans, cmd); if (ret < 0) { - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", + IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } return 0; } -static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { int cmd_idx; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&trans->shrd->mutex); /* A synchronous command can not have a callback set. */ if (WARN_ON(cmd->callback)) return -EINVAL; - IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", + IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - set_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", + set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); + IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); - cmd_idx = iwl_enqueue_hcmd(priv, cmd); + cmd_idx = iwl_enqueue_hcmd(trans, cmd); if (cmd_idx < 0) { ret = cmd_idx; - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", + clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); + IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status), + ret = wait_event_interruptible_timeout(priv(trans)->wait_command_queue, + !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), HOST_COMPLETE_TIMEOUT); if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)) { - IWL_ERR(priv, + if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { + IWL_ERR(trans, "Error sending %s: time out after %dms.\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" + clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); + IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command" "%s\n", get_cmd_string(cmd->id)); ret = -ETIMEDOUT; goto cancel; } } - if (test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)) { - IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", + if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) { + IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); ret = -ECANCELED; goto fail; } - if (test_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - IWL_ERR(priv, "Command %s failed: FW Error\n", + if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { + IWL_ERR(trans, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); ret = -EIO; goto fail; } if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { - IWL_ERR(priv, "Error: Response NULL in '%s'\n", + IWL_ERR(trans, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; goto cancel; @@ -1018,27 +1018,27 @@ cancel: * in later, it will possibly set an invalid * address (cmd->meta.source). */ - priv->txq[priv->shrd->cmd_queue].meta[cmd_idx].flags &= + priv(trans)->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: if (cmd->reply_page) { - iwl_free_pages(priv->shrd, cmd->reply_page); + iwl_free_pages(trans->shrd, cmd->reply_page); cmd->reply_page = 0; } return ret; } -int iwl_trans_pcie_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { if (cmd->flags & CMD_ASYNC) - return iwl_send_cmd_async(priv, cmd); + return iwl_send_cmd_async(trans, cmd); - return iwl_send_cmd_sync(priv, cmd); + return iwl_send_cmd_sync(trans, cmd); } -int iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, +int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data) { struct iwl_host_cmd cmd = { @@ -1048,7 +1048,7 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, .flags = flags, }; - return iwl_trans_pcie_send_cmd(priv, &cmd); + return iwl_trans_pcie_send_cmd(trans, &cmd); } /* Frees buffers until index _not_ inclusive */ @@ -1096,8 +1096,8 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, tx_info->skb = NULL; - iwlagn_txq_inval_byte_cnt_tbl(priv(trans), txq); + iwlagn_txq_inval_byte_cnt_tbl(trans, txq); - iwlagn_txq_free_tfd(priv(trans), txq, txq->q.read_ptr); + iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 89560089a348..b448e79c259b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -62,6 +62,8 @@ *****************************************************************************/ #include #include +#include +#include #include "iwl-dev.h" #include "iwl-trans.h" @@ -263,22 +265,22 @@ static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) rxq->rb_stts = NULL; } -static int iwl_trans_rx_stop(struct iwl_priv *priv) +static int iwl_trans_rx_stop(struct iwl_trans *trans) { /* stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(priv(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(priv(trans), FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); } -static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, +static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr, size_t size) { if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(priv->bus->dev, size, + ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -286,20 +288,21 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, return 0; } -static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, +static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr) { if (unlikely(!ptr->addr)) return; - dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } -static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int slots_num, u32 txq_id) +static int iwl_trans_txq_alloc(struct iwl_trans *trans, + struct iwl_tx_queue *txq, int slots_num, + u32 txq_id) { - size_t tfd_sz = hw_params(priv).tfd_size * TFD_QUEUE_SIZE_MAX; + size_t tfd_sz = hw_params(trans).tfd_size * TFD_QUEUE_SIZE_MAX; int i; if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) @@ -325,11 +328,11 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (txq_id != priv->shrd->cmd_queue) { + if (txq_id != trans->shrd->cmd_queue) { txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { - IWL_ERR(priv, "kmalloc for auxiliary BD " + IWL_ERR(trans, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } @@ -339,10 +342,10 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr, - GFP_KERNEL); + txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, + &txq->q.dma_addr, GFP_KERNEL); if (!txq->tfds) { - IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); + IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); goto error; } txq->q.id = txq_id; @@ -365,7 +368,7 @@ error: } -static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, +static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { int ret; @@ -386,7 +389,7 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ - ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, + ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); if (ret) return ret; @@ -395,7 +398,7 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(priv(trans), FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); return 0; @@ -404,8 +407,9 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, /** * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's */ -static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) +static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) { + struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; @@ -414,7 +418,7 @@ static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) while (q->write_ptr != q->read_ptr) { /* The read_ptr needs to bound by q->n_window */ - iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); + iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr)); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -427,15 +431,16 @@ static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) +static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) { + struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct device *dev = priv->bus->dev; + struct device *dev = bus(trans)->dev; int i; if (WARN_ON(!txq)) return; - iwl_tx_queue_unmap(priv, txq_id); + iwl_tx_queue_unmap(trans, txq_id); /* De-alloc array of command/tx buffers */ for (i = 0; i < txq->q.n_window; i++) @@ -443,7 +448,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { - dma_free_coherent(dev, hw_params(priv).tfd_size * + dma_free_coherent(dev, hw_params(trans).tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); } @@ -467,26 +472,26 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) * * Destroy all TX DMA queues and structures */ -static void iwl_trans_pcie_tx_free(struct iwl_priv *priv) +static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) { int txq_id; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_priv *priv = priv(trans); /* Tx queues */ if (priv->txq) { for (txq_id = 0; - txq_id < hw_params(priv).max_txq_num; txq_id++) - iwl_tx_queue_free(priv, txq_id); + txq_id < hw_params(trans).max_txq_num; txq_id++) + iwl_tx_queue_free(trans, txq_id); } kfree(priv->txq); priv->txq = NULL; - iwlagn_free_dma_ptr(priv, &priv->kw); + iwlagn_free_dma_ptr(trans, &priv->kw); - iwlagn_free_dma_ptr(priv, &trans_pcie->scd_bc_tbls); + iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); } /** @@ -496,11 +501,11 @@ static void iwl_trans_pcie_tx_free(struct iwl_priv *priv) * @param priv * @return error code */ -static int iwl_trans_tx_alloc(struct iwl_priv *priv) +static int iwl_trans_tx_alloc(struct iwl_trans *trans) { int ret; int txq_id, slots_num; - struct iwl_trans *trans = trans(priv); + struct iwl_priv *priv = priv(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -511,36 +516,36 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) goto error; } - ret = iwlagn_alloc_dma_ptr(priv, &trans_pcie->scd_bc_tbls, - hw_params(priv).scd_bc_tbls_size); + ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, + hw_params(trans).scd_bc_tbls_size); if (ret) { - IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); + IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); goto error; } /* Alloc keep-warm buffer */ - ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); + ret = iwlagn_alloc_dma_ptr(trans, &priv->kw, IWL_KW_SIZE); if (ret) { - IWL_ERR(priv, "Keep Warm allocation failed\n"); + IWL_ERR(trans, "Keep Warm allocation failed\n"); goto error; } priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * priv->cfg->base_params->num_of_queues, GFP_KERNEL); if (!priv->txq) { - IWL_ERR(priv, "Not enough memory for txq\n"); + IWL_ERR(trans, "Not enough memory for txq\n"); ret = ENOMEM; goto error; } /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { - slots_num = (txq_id == priv->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { + slots_num = (txq_id == trans->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, + ret = iwl_trans_txq_alloc(trans, &priv->txq[txq_id], slots_num, txq_id); if (ret) { - IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id); + IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); goto error; } } @@ -548,25 +553,26 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) return 0; error: - iwl_trans_tx_free(trans(priv)); + iwl_trans_tx_free(trans); return ret; } -static int iwl_tx_init(struct iwl_priv *priv) +static int iwl_tx_init(struct iwl_trans *trans) { int ret; int txq_id, slots_num; unsigned long flags; bool alloc = false; + struct iwl_priv *priv = priv(trans); if (!priv->txq) { - ret = iwl_trans_tx_alloc(priv); + ret = iwl_trans_tx_alloc(trans); if (ret) goto error; alloc = true; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); /* Turn off all Tx DMA fifos */ iwl_write_prph(priv, SCD_TXFACT, 0); @@ -574,16 +580,16 @@ static int iwl_tx_init(struct iwl_priv *priv) /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) { - slots_num = (txq_id == priv->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { + slots_num = (txq_id == trans->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, + ret = iwl_trans_txq_init(trans, &priv->txq[txq_id], slots_num, txq_id); if (ret) { - IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); + IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); goto error; } } @@ -592,7 +598,7 @@ static int iwl_tx_init(struct iwl_priv *priv) error: /*Upon error, free only if we allocated something */ if (alloc) - iwl_trans_tx_free(trans(priv)); + iwl_trans_tx_free(trans); return ret; } @@ -613,28 +619,29 @@ static void iwl_set_pwr_vmain(struct iwl_priv *priv) ~APMG_PS_CTRL_MSK_PWR_SRC); } -static int iwl_nic_init(struct iwl_priv *priv) +static int iwl_nic_init(struct iwl_trans *trans) { unsigned long flags; + struct iwl_priv *priv = priv(trans); /* nic_init */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); iwl_apm_init(priv); /* Set interrupt coalescing calibration timer to default (512 usecs) */ iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); iwl_set_pwr_vmain(priv); priv->cfg->lib->nic_config(priv); /* Allocate the RX queue, or reset if it is already allocated */ - iwl_rx_init(trans(priv)); + iwl_rx_init(trans); /* Allocate or reset and init all Tx and Command queues */ - if (iwl_tx_init(priv)) + if (iwl_tx_init(trans)) return -ENOMEM; if (priv->cfg->base_params->shadow_reg_enable) { @@ -643,7 +650,7 @@ static int iwl_nic_init(struct iwl_priv *priv) 0x800FFFFF); } - set_bit(STATUS_INIT, &priv->shrd->status); + set_bit(STATUS_INIT, &trans->shrd->status); return 0; } @@ -651,39 +658,39 @@ static int iwl_nic_init(struct iwl_priv *priv) #define HW_READY_TIMEOUT (50) /* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_set_hw_ready(struct iwl_priv *priv) +static int iwl_set_hw_ready(struct iwl_trans *trans) { int ret; - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); - IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); return ret; } /* Note: returns standard 0/-ERROR code */ -static int iwl_trans_pcie_prepare_card_hw(struct iwl_priv *priv) +static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) { int ret; - IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n"); + IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); - ret = iwl_set_hw_ready(priv); + ret = iwl_set_hw_ready(trans); if (ret >= 0) return 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv(trans), CSR_HW_IF_CONFIG_REG, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); @@ -691,42 +698,43 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_priv *priv) return ret; /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(priv); + ret = iwl_set_hw_ready(trans); if (ret >= 0) return 0; return ret; } -static int iwl_trans_pcie_start_device(struct iwl_priv *priv) +static int iwl_trans_pcie_start_device(struct iwl_trans *trans) { int ret; + struct iwl_priv *priv = priv(trans); priv->ucode_owner = IWL_OWNERSHIP_DRIVER; if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_trans_pcie_prepare_card_hw(priv)) { - IWL_WARN(priv, "Exit HW not ready\n"); + iwl_trans_pcie_prepare_card_hw(trans)) { + IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; } /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); else - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(trans->shrd)) { wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(trans(priv)); + iwl_enable_interrupts(trans); return -ERFKILL; } iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - ret = iwl_nic_init(priv); + ret = iwl_nic_init(trans); if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); + IWL_ERR(trans, "Unable to init nic\n"); return ret; } @@ -737,7 +745,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) /* clear (again), then enable host interrupts */ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(trans(priv)); + iwl_enable_interrupts(trans); /* really make sure rfkill handshake bits are cleared */ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); @@ -750,9 +758,9 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask * must be called under priv->shrd->lock and mac access */ -static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) +static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) { - iwl_write_prph(priv, SCD_TXFACT, mask); + iwl_write_prph(priv(trans), SCD_TXFACT, mask); } #define IWL_AC_UNSET -1 @@ -788,11 +796,11 @@ static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, }; -static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) +static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_rxon_context *ctx; - struct iwl_trans *trans = trans(priv); + struct iwl_priv *priv = priv(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 a; @@ -856,7 +864,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) IWL_MASK(0, hw_params(trans).max_txq_num)); /* Activate all Tx DMA/FIFO channels */ - iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); + iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) @@ -864,7 +872,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwl_trans_set_wr_ptrs(priv, priv->shrd->cmd_queue, 0); + iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); @@ -895,7 +903,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); /* Enable L1-Active */ iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, @@ -905,50 +913,53 @@ static void iwl_trans_pcie_tx_start(struct iwl_priv *priv) /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ -static int iwl_trans_tx_stop(struct iwl_priv *priv) +static int iwl_trans_tx_stop(struct iwl_trans *trans) { int ch, txq_id; unsigned long flags; + struct iwl_priv *priv = priv(trans); /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_trans_txq_set_sched(priv, 0); + iwl_trans_txq_set_sched(trans, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, + iwl_write_direct32(priv(trans), + FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + if (iwl_poll_direct_bit(priv(trans), FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) - IWL_ERR(priv, "Failing on timeout while stopping" + IWL_ERR(trans, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, - iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); + iwl_read_direct32(priv(trans), + FH_TSSR_TX_STATUS_REG)); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); if (!priv->txq) { - IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); + IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); return 0; } /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) - iwl_tx_queue_unmap(priv, txq_id); + for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) + iwl_tx_queue_unmap(trans, txq_id); return 0; } -static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) +static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) { /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - iwl_trans_disable_sync_irq(trans(priv)); + iwl_trans_disable_sync_irq(trans); /* device going down, Stop using ICT table */ - iwl_disable_ict(trans(priv)); + iwl_disable_ict(trans); /* * If a HW restart happens during firmware loading, @@ -957,26 +968,28 @@ static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) * restart. So don't process again if the device is * already dead. */ - if (test_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status)) { - iwl_trans_tx_stop(priv); - iwl_trans_rx_stop(priv); + if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { + iwl_trans_tx_stop(trans); + iwl_trans_rx_stop(trans); /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, + iwl_write_prph(priv(trans), APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_clear_bit(priv(trans), CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv); + iwl_apm_stop(priv(trans)); } -static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_priv *priv, +static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_trans *trans, int txq_id) { + struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *dev_cmd; @@ -1072,9 +1085,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, } /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); + iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, txcmd_phys, + firstlen, 1); if (secondlen > 0) - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, phys_addr, secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + @@ -1094,7 +1108,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Set up entry for this TFD in Tx byte-count array */ if (ampdu) - iwl_trans_txq_update_byte_cnt_tbl(priv, txq, + iwl_trans_txq_update_byte_cnt_tbl(trans(priv), txq, le16_to_cpu(tx_cmd->len)); dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, @@ -1127,10 +1141,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } -static void iwl_trans_pcie_kick_nic(struct iwl_priv *priv) +static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) { /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); + iwl_write32(priv(trans), CSR_RESET, 0); } static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) @@ -1201,12 +1215,12 @@ static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) tasklet_kill(&trans_pcie->irq_tasklet); } -static void iwl_trans_pcie_free(struct iwl_priv *priv) +static void iwl_trans_pcie_free(struct iwl_trans *trans) { - free_irq(priv->bus->irq, trans(priv)); - iwl_free_isr_ict(trans(priv)); - kfree(trans(priv)); - trans(priv) = NULL; + free_irq(bus(trans)->irq, trans); + iwl_free_isr_ict(trans); + trans->shrd->trans = NULL; + kfree(trans); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7fd0296f155e..da6cc59dfa2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -109,18 +109,18 @@ struct iwl_trans_ops { struct iwl_trans *(*alloc)(struct iwl_shared *shrd); int (*request_irq)(struct iwl_trans *iwl_trans); - int (*start_device)(struct iwl_priv *priv); - int (*prepare_card_hw)(struct iwl_priv *priv); - void (*stop_device)(struct iwl_priv *priv); - void (*tx_start)(struct iwl_priv *priv); - void (*tx_free)(struct iwl_priv *priv); + int (*start_device)(struct iwl_trans *trans); + int (*prepare_card_hw)(struct iwl_trans *trans); + void (*stop_device)(struct iwl_trans *trans); + void (*tx_start)(struct iwl_trans *trans); + void (*tx_free)(struct iwl_trans *trans); void (*rx_free)(struct iwl_trans *trans); - int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); + int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); - int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data); - struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_trans *trans, int txq_id); int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); @@ -132,10 +132,10 @@ struct iwl_trans_ops { void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); - void (*kick_nic)(struct iwl_priv *priv); + void (*kick_nic)(struct iwl_trans *trans); void (*disable_sync_irq)(struct iwl_trans *trans); - void (*free)(struct iwl_priv *priv); + void (*free)(struct iwl_trans *trans); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); int (*suspend)(struct iwl_trans *trans); @@ -163,22 +163,22 @@ static inline int iwl_trans_request_irq(struct iwl_trans *trans) static inline int iwl_trans_start_device(struct iwl_trans *trans) { - return trans->ops->start_device(priv(trans)); + return trans->ops->start_device(trans); } static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) { - return trans->ops->prepare_card_hw(priv(trans)); + return trans->ops->prepare_card_hw(trans); } static inline void iwl_trans_stop_device(struct iwl_trans *trans) { - trans->ops->stop_device(priv(trans)); + trans->ops->stop_device(trans); } static inline void iwl_trans_tx_start(struct iwl_trans *trans) { - trans->ops->tx_start(priv(trans)); + trans->ops->tx_start(trans); } static inline void iwl_trans_rx_free(struct iwl_trans *trans) @@ -188,25 +188,25 @@ static inline void iwl_trans_rx_free(struct iwl_trans *trans) static inline void iwl_trans_tx_free(struct iwl_trans *trans) { - trans->ops->tx_free(priv(trans)); + trans->ops->tx_free(trans); } static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return trans->ops->send_cmd(priv(trans), cmd); + return trans->ops->send_cmd(trans, cmd); } static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data) { - return trans->ops->send_cmd_pdu(priv(trans), id, flags, len, data); + return trans->ops->send_cmd_pdu(trans, id, flags, len, data); } static inline struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_trans *trans, int txq_id) { - return trans->ops->get_tx_cmd(priv(trans), txq_id); + return trans->ops->get_tx_cmd(trans, txq_id); } static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, @@ -238,7 +238,7 @@ static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, static inline void iwl_trans_kick_nic(struct iwl_trans *trans) { - trans->ops->kick_nic(priv(trans)); + trans->ops->kick_nic(trans); } static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) @@ -248,7 +248,7 @@ static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) static inline void iwl_trans_free(struct iwl_trans *trans) { - trans->ops->free(priv(trans)); + trans->ops->free(trans); } static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, From 72012474b01e2f2d433e4253505f5dcfb3345d17 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:07 -0700 Subject: [PATCH 084/129] iwlagn: move hcmd_lock to transport layer Since it is needed for host commands only, it is needed in transport layer only Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-trans.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 2 ++ 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f559c6362a00..9c5f08a938eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3059,7 +3059,6 @@ static int iwl_init_drv(struct iwl_priv *priv) int ret; spin_lock_init(&priv->shrd->sta_lock); - spin_lock_init(&priv->hcmd_lock); mutex_init(&priv->shrd->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index eac25c507d30..de293cf02177 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1178,7 +1178,6 @@ struct iwl_priv { u8 mgmt_tx_ant; /* spinlock */ - spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ /*TODO: remove these pointers - use bus(priv) instead */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 1704eab8ddf2..835e3edb9cce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -601,10 +601,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EIO; } - spin_lock_irqsave(&priv->hcmd_lock, flags); + spin_lock_irqsave(&trans->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_irqrestore(&priv->hcmd_lock, flags); + spin_unlock_irqrestore(&trans->hcmd_lock, flags); IWL_ERR(trans, "No space in command queue\n"); is_ct_kill = iwl_check_for_ct_kill(priv); @@ -713,7 +713,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) iwl_txq_update_write_ptr(priv, txq); out: - spin_unlock_irqrestore(&priv->hcmd_lock, flags); + spin_unlock_irqrestore(&trans->hcmd_lock, flags); return idx; } @@ -796,7 +796,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } else if (meta->callback) meta->callback(priv, cmd, pkt); - spin_lock_irqsave(&priv->hcmd_lock, flags); + spin_lock_irqsave(&trans->hcmd_lock, flags); iwl_hcmd_queue_reclaim(priv, txq_id, index); @@ -809,7 +809,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) meta->flags = 0; - spin_unlock_irqrestore(&priv->hcmd_lock, flags); + spin_unlock_irqrestore(&trans->hcmd_lock, flags); } const char *get_cmd_string(u8 cmd) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index b448e79c259b..73883fe1c2d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1284,6 +1284,7 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) iwl_trans->ops = &trans_ops_pcie; iwl_trans->shrd = shrd; trans_pcie->trans = iwl_trans; + spin_lock_init(&iwl_trans->hcmd_lock); } return iwl_trans; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index da6cc59dfa2b..78bd2f636452 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -146,10 +146,12 @@ struct iwl_trans_ops { * struct iwl_trans - transport common data * @ops - pointer to iwl_trans_ops * @shrd - pointer to iwl_shared which holds shared data from the upper layer + * @hcmd_lock: protects HCMD */ struct iwl_trans { const struct iwl_trans_ops *ops; struct iwl_shared *shrd; + spinlock_t hcmd_lock; /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ From 16db88ba51d669ef63c58990771a47208913152c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:08 -0700 Subject: [PATCH 085/129] iwlagn: move dump_csr and dump_fh to transport layer These are transport layer related. Move also the corresponding debugfs handlers. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 130 ------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 44 ----- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 3 + .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 182 ++++++++++++++++++ 6 files changed, 187 insertions(+), 178 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index bca5f99377ac..359bd9060560 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1395,136 +1395,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) return ant; } -static const char *get_csr_string(int cmd) -{ - switch (cmd) { - IWL_CMD(CSR_HW_IF_CONFIG_REG); - IWL_CMD(CSR_INT_COALESCING); - IWL_CMD(CSR_INT); - IWL_CMD(CSR_INT_MASK); - IWL_CMD(CSR_FH_INT_STATUS); - IWL_CMD(CSR_GPIO_IN); - IWL_CMD(CSR_RESET); - IWL_CMD(CSR_GP_CNTRL); - IWL_CMD(CSR_HW_REV); - IWL_CMD(CSR_EEPROM_REG); - IWL_CMD(CSR_EEPROM_GP); - IWL_CMD(CSR_OTP_GP_REG); - IWL_CMD(CSR_GIO_REG); - IWL_CMD(CSR_GP_UCODE_REG); - IWL_CMD(CSR_GP_DRIVER_REG); - IWL_CMD(CSR_UCODE_DRV_GP1); - IWL_CMD(CSR_UCODE_DRV_GP2); - IWL_CMD(CSR_LED_REG); - IWL_CMD(CSR_DRAM_INT_TBL_REG); - IWL_CMD(CSR_GIO_CHICKEN_BITS); - IWL_CMD(CSR_ANA_PLL_CFG); - IWL_CMD(CSR_HW_REV_WA_REG); - IWL_CMD(CSR_DBG_HPET_MEM_REG); - default: - return "UNKNOWN"; - } -} - -void iwl_dump_csr(struct iwl_priv *priv) -{ - int i; - static const u32 csr_tbl[] = { - CSR_HW_IF_CONFIG_REG, - CSR_INT_COALESCING, - CSR_INT, - CSR_INT_MASK, - CSR_FH_INT_STATUS, - CSR_GPIO_IN, - CSR_RESET, - CSR_GP_CNTRL, - CSR_HW_REV, - CSR_EEPROM_REG, - CSR_EEPROM_GP, - CSR_OTP_GP_REG, - CSR_GIO_REG, - CSR_GP_UCODE_REG, - CSR_GP_DRIVER_REG, - CSR_UCODE_DRV_GP1, - CSR_UCODE_DRV_GP2, - CSR_LED_REG, - CSR_DRAM_INT_TBL_REG, - CSR_GIO_CHICKEN_BITS, - CSR_ANA_PLL_CFG, - CSR_HW_REV_WA_REG, - CSR_DBG_HPET_MEM_REG - }; - IWL_ERR(priv, "CSR values:\n"); - IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " - "CSR_INT_PERIODIC_REG)\n"); - for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { - IWL_ERR(priv, " %25s: 0X%08x\n", - get_csr_string(csr_tbl[i]), - iwl_read32(priv, csr_tbl[i])); - } -} - -static const char *get_fh_string(int cmd) -{ - switch (cmd) { - IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); - IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); - IWL_CMD(FH_RSCSR_CHNL0_WPTR); - IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); - IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); - IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); - IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - } -} - -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) -{ - int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif - static const u32 fh_tbl[] = { - FH_RSCSR_CHNL0_STTS_WPTR_REG, - FH_RSCSR_CHNL0_RBDCB_BASE_REG, - FH_RSCSR_CHNL0_WPTR, - FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_MEM_RSSR_SHARED_CTRL_REG, - FH_MEM_RSSR_RX_STATUS_REG, - FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG - }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - pos += scnprintf(*buf + pos, bufsz - pos, - "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - pos += scnprintf(*buf + pos, bufsz - pos, - " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv, fh_tbl[i])); - } - return pos; - } -#endif - IWL_ERR(priv, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - IWL_ERR(priv, " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv, fh_tbl[i])); - } - return 0; -} - /* notification wait support */ void iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e5b3c356b392..c3bdba5a48f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -375,8 +375,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, /***************************************************** * Error Handling Debugging ******************************************************/ -void iwl_dump_csr(struct iwl_priv *priv); -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 9ca429c23ad1..a12b8d47ccbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1991,27 +1991,6 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_csr_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int csr; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &csr) != 1) - return -EFAULT; - - iwl_dump_csr(priv); - - return count; -} - static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -2088,25 +2067,6 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } -static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -EFAULT; - - ret = pos = iwl_dump_fh(priv, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, - count, ppos, buf, pos); - kfree(buf); - } - - return ret; -} - static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -2391,9 +2351,7 @@ DEBUGFS_READ_FILE_OPS(chain_noise); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); -DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); -DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(force_reset); @@ -2448,8 +2406,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); - DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); - DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index b2af467430a9..0e4efb0e189b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -169,6 +169,9 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, ******************************************************/ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); +int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); +void iwl_dump_csr(struct iwl_trans *trans); + static inline void iwl_disable_interrupts(struct iwl_trans *trans) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index b1635eee24b7..0b6c5278e28b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -655,8 +655,8 @@ static void iwl_irq_handle_error(struct iwl_priv *priv) priv->hw->wiphy->fw_version); iwl_dump_nic_error_log(priv); - iwl_dump_csr(priv); - iwl_dump_fh(priv, NULL, false); + iwl_dump_csr(trans(priv)); + iwl_dump_fh(trans(priv), NULL, false); iwl_dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 73883fe1c2d1..e55636e1deaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1324,6 +1324,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .llseek = generic_file_llseek, \ }; +#define DEBUGFS_WRITE_FILE_OPS(name) \ + DEBUGFS_WRITE_FUNC(name); \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .write = iwl_dbgfs_##name##_write, \ + .open = iwl_dbgfs_open_file_generic, \ + .llseek = generic_file_llseek, \ +}; + #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ DEBUGFS_WRITE_FUNC(name); \ @@ -1635,11 +1643,183 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, return count; } +static const char *get_csr_string(int cmd) +{ + switch (cmd) { + IWL_CMD(CSR_HW_IF_CONFIG_REG); + IWL_CMD(CSR_INT_COALESCING); + IWL_CMD(CSR_INT); + IWL_CMD(CSR_INT_MASK); + IWL_CMD(CSR_FH_INT_STATUS); + IWL_CMD(CSR_GPIO_IN); + IWL_CMD(CSR_RESET); + IWL_CMD(CSR_GP_CNTRL); + IWL_CMD(CSR_HW_REV); + IWL_CMD(CSR_EEPROM_REG); + IWL_CMD(CSR_EEPROM_GP); + IWL_CMD(CSR_OTP_GP_REG); + IWL_CMD(CSR_GIO_REG); + IWL_CMD(CSR_GP_UCODE_REG); + IWL_CMD(CSR_GP_DRIVER_REG); + IWL_CMD(CSR_UCODE_DRV_GP1); + IWL_CMD(CSR_UCODE_DRV_GP2); + IWL_CMD(CSR_LED_REG); + IWL_CMD(CSR_DRAM_INT_TBL_REG); + IWL_CMD(CSR_GIO_CHICKEN_BITS); + IWL_CMD(CSR_ANA_PLL_CFG); + IWL_CMD(CSR_HW_REV_WA_REG); + IWL_CMD(CSR_DBG_HPET_MEM_REG); + default: + return "UNKNOWN"; + } +} + +void iwl_dump_csr(struct iwl_trans *trans) +{ + int i; + static const u32 csr_tbl[] = { + CSR_HW_IF_CONFIG_REG, + CSR_INT_COALESCING, + CSR_INT, + CSR_INT_MASK, + CSR_FH_INT_STATUS, + CSR_GPIO_IN, + CSR_RESET, + CSR_GP_CNTRL, + CSR_HW_REV, + CSR_EEPROM_REG, + CSR_EEPROM_GP, + CSR_OTP_GP_REG, + CSR_GIO_REG, + CSR_GP_UCODE_REG, + CSR_GP_DRIVER_REG, + CSR_UCODE_DRV_GP1, + CSR_UCODE_DRV_GP2, + CSR_LED_REG, + CSR_DRAM_INT_TBL_REG, + CSR_GIO_CHICKEN_BITS, + CSR_ANA_PLL_CFG, + CSR_HW_REV_WA_REG, + CSR_DBG_HPET_MEM_REG + }; + IWL_ERR(trans, "CSR values:\n"); + IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is " + "CSR_INT_PERIODIC_REG)\n"); + for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { + IWL_ERR(trans, " %25s: 0X%08x\n", + get_csr_string(csr_tbl[i]), + iwl_read32(priv(trans), csr_tbl[i])); + } +} + +static ssize_t iwl_dbgfs_csr_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_trans *trans = file->private_data; + char buf[8]; + int buf_size; + int csr; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &csr) != 1) + return -EFAULT; + + iwl_dump_csr(trans); + + return count; +} + +static const char *get_fh_string(int cmd) +{ + switch (cmd) { + IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); + IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); + IWL_CMD(FH_RSCSR_CHNL0_WPTR); + IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); + IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); + IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); + IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); + IWL_CMD(FH_TSSR_TX_STATUS_REG); + IWL_CMD(FH_TSSR_TX_ERROR_REG); + default: + return "UNKNOWN"; + } +} + +int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) +{ + int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif + static const u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, + FH_RSCSR_CHNL0_WPTR, + FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_MEM_RSSR_SHARED_CTRL_REG, + FH_MEM_RSSR_RX_STATUS_REG, + FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv(trans), fh_tbl[i])); + } + return pos; + } +#endif + IWL_ERR(trans, "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + IWL_ERR(trans, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv(trans), fh_tbl[i])); + } + return 0; +} + +static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_trans *trans = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -EFAULT; + + ret = pos = iwl_dump_fh(trans, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); + } + + return ret; +} + DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_WRITE_FILE_OPS(interrupt); +DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_READ_FILE_OPS(tx_queue); +DEBUGFS_WRITE_FILE_OPS(csr); /* * Create the debugfs files and directories @@ -1653,6 +1833,8 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); return 0; } #else From 6bb7884758965ad0afd67801f0f41cefd53d0b0c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:09 -0700 Subject: [PATCH 086/129] iwlagn: remove references to priv from the transport layer Continue to the clean up of the priv dereferencing from the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 7 +- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 124 +++++++++--------- drivers/net/wireless/iwlwifi/iwl-trans.c | 4 +- 5 files changed, 70 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9c5f08a938eb..bbdc475c74dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1402,7 +1402,7 @@ int iwl_alive_start(struct iwl_priv *priv) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; /*TODO: this should go to the transport layer */ - iwl_reset_ict(priv); + iwl_reset_ict(trans(priv)); IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index c30299da4daf..3508c12de25f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -111,7 +111,7 @@ extern struct iwl_cfg iwl135_bgn_cfg; extern struct ieee80211_ops iwlagn_hw_ops; -int iwl_reset_ict(struct iwl_priv *priv); +int iwl_reset_ict(struct iwl_trans *trans); static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 0e4efb0e189b..59c6b3c673e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -130,7 +130,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /***************************************************** * ICT ******************************************************/ -int iwl_reset_ict(struct iwl_priv *priv); +int iwl_reset_ict(struct iwl_trans *trans); void iwl_disable_ict(struct iwl_trans *trans); int iwl_alloc_isr_ict(struct iwl_trans *trans); void iwl_free_isr_ict(struct iwl_trans *trans); @@ -167,12 +167,11 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, /***************************************************** * Error handling ******************************************************/ -int iwl_dump_nic_event_log(struct iwl_priv *priv, - bool full_log, char **buf, bool display); +int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, + char **buf, bool display); int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); void iwl_dump_csr(struct iwl_trans *trans); - static inline void iwl_disable_interrupts(struct iwl_trans *trans) { clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 0b6c5278e28b..7f8ac2ed49ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -565,11 +565,11 @@ static const char *desc_lookup(u32 num) #define ERROR_START_OFFSET (1 * sizeof(u32)) #define ERROR_ELEM_SIZE (7 * sizeof(u32)) -static void iwl_dump_nic_error_log(struct iwl_priv *priv) +static void iwl_dump_nic_error_log(struct iwl_trans *trans) { u32 base; struct iwl_error_event_table table; - struct iwl_trans *trans = trans(priv); + struct iwl_priv *priv = priv(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -583,7 +583,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) } if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, + IWL_ERR(trans, "Not valid error log pointer 0x%08X for %s uCode\n", base, (priv->ucode_type == IWL_UCODE_INIT) @@ -594,9 +594,9 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); - IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->shrd->status, table.valid); + IWL_ERR(trans, "Start IWL Error Log Dump:\n"); + IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", + trans->shrd->status, table.valid); } trans_pcie->isr_stats.err_code = table.error_id; @@ -607,33 +607,34 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) table.ilink2, table.bcon_time, table.gp1, table.gp2, table.gp3, table.ucode_ver, table.hw_ver, table.brd_ver); - IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id, desc_lookup(table.error_id)); - IWL_ERR(priv, "0x%08X | uPc\n", table.pc); - IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); - IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); - IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); - IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); - IWL_ERR(priv, "0x%08X | data1\n", table.data1); - IWL_ERR(priv, "0x%08X | data2\n", table.data2); - IWL_ERR(priv, "0x%08X | line\n", table.line); - IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); - IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); - IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); - IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); - IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); - IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); - IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); - IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); - IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); - IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); + IWL_ERR(trans, "0x%08X | uPc\n", table.pc); + IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(trans, "0x%08X | data1\n", table.data1); + IWL_ERR(trans, "0x%08X | data2\n", table.data2); + IWL_ERR(trans, "0x%08X | line\n", table.line); + IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); } /** * iwl_irq_handle_error - called for HW or SW error interrupt from card */ -static void iwl_irq_handle_error(struct iwl_priv *priv) +static void iwl_irq_handle_error(struct iwl_trans *trans) { + struct iwl_priv *priv = priv(trans); /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (priv->cfg->internal_wimax_coex && (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & @@ -644,22 +645,22 @@ static void iwl_irq_handle_error(struct iwl_priv *priv) * Keep the restart process from trying to send host * commands by clearing the ready bit. */ - clear_bit(STATUS_READY, &priv->shrd->status); - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); + clear_bit(STATUS_READY, &trans->shrd->status); + clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); wake_up_interruptible(&priv->wait_command_queue); - IWL_ERR(priv, "RF is used by WiMAX\n"); + IWL_ERR(trans, "RF is used by WiMAX\n"); return; } - IWL_ERR(priv, "Loaded firmware version: %s\n", + IWL_ERR(trans, "Loaded firmware version: %s\n", priv->hw->wiphy->fw_version); - iwl_dump_nic_error_log(priv); - iwl_dump_csr(trans(priv)); - iwl_dump_fh(trans(priv), NULL, false); - iwl_dump_nic_event_log(priv, false, NULL, false); + iwl_dump_nic_error_log(trans); + iwl_dump_csr(trans); + iwl_dump_fh(trans, NULL, false); + iwl_dump_nic_event_log(trans, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) + if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) iwl_print_rx_config_cmd(priv, &priv->contexts[IWL_RXON_CTX_BSS]); #endif @@ -673,7 +674,7 @@ static void iwl_irq_handle_error(struct iwl_priv *priv) * iwl_print_event_log - Dump error event log to syslog * */ -static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, +static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, u32 num_events, u32 mode, int pos, char **buf, size_t bufsz) { @@ -683,6 +684,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 ptr; /* SRAM byte address of log data */ u32 ev, time, data; /* event log data */ unsigned long reg_flags; + struct iwl_priv *priv = priv(trans); if (num_events == 0) return pos; @@ -725,7 +727,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, } else { trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); - IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", + IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n", time, ev); } } else { @@ -735,7 +737,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, "EVT_LOGT:%010u:0x%08x:%04u\n", time, data, ev); } else { - IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n", time, data, ev); trace_iwlwifi_dev_ucode_event(priv, time, data, ev); @@ -752,7 +754,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, /** * iwl_print_last_event_logs - Dump the newest # of event log to syslog */ -static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, +static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity, u32 num_wraps, u32 next_entry, u32 size, u32 mode, int pos, char **buf, size_t bufsz) @@ -763,22 +765,22 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, */ if (num_wraps) { if (next_entry < size) { - pos = iwl_print_event_log(priv, + pos = iwl_print_event_log(trans, capacity - (size - next_entry), size - next_entry, mode, pos, buf, bufsz); - pos = iwl_print_event_log(priv, 0, + pos = iwl_print_event_log(trans, 0, next_entry, mode, pos, buf, bufsz); } else - pos = iwl_print_event_log(priv, next_entry - size, + pos = iwl_print_event_log(trans, next_entry - size, size, mode, pos, buf, bufsz); } else { if (next_entry < size) { - pos = iwl_print_event_log(priv, 0, next_entry, + pos = iwl_print_event_log(trans, 0, next_entry, mode, pos, buf, bufsz); } else { - pos = iwl_print_event_log(priv, next_entry - size, + pos = iwl_print_event_log(trans, next_entry - size, size, mode, pos, buf, bufsz); } } @@ -787,7 +789,7 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) -int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, +int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, char **buf, bool display) { u32 base; /* SRAM byte address of event log header */ @@ -799,6 +801,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, u32 logsize; int pos = 0; size_t bufsz = 0; + struct iwl_priv *priv = priv(trans); base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { @@ -812,7 +815,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, } if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, + IWL_ERR(trans, "Invalid event log pointer 0x%08X for %s uCode\n", base, (priv->ucode_type == IWL_UCODE_INIT) @@ -827,13 +830,13 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); if (capacity > logsize) { - IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, logsize); + IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " + "entries\n", capacity, logsize); capacity = logsize; } if (next_entry > logsize) { - IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", + IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", next_entry, logsize); next_entry = logsize; } @@ -842,7 +845,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, /* bail out if nothing in log */ if (size == 0) { - IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); + IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); return pos; } @@ -850,14 +853,14 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; #ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) && !full_log) + if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #endif - IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", + IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", size); #ifdef CONFIG_IWLWIFI_DEBUG @@ -870,25 +873,25 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, if (!*buf) return -ENOMEM; } - if ((iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) || full_log) { + if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) { /* * if uCode has wrapped back to top of log, * start at the oldest entry, * i.e the next one that uCode would fill. */ if (num_wraps) - pos = iwl_print_event_log(priv, next_entry, + pos = iwl_print_event_log(trans, next_entry, capacity - next_entry, mode, pos, buf, bufsz); /* (then/else) start at top of log */ - pos = iwl_print_event_log(priv, 0, + pos = iwl_print_event_log(trans, 0, next_entry, mode, pos, buf, bufsz); } else - pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #else - pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #endif @@ -951,7 +954,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) iwl_disable_interrupts(trans); isr_stats->hw++; - iwl_irq_handle_error(priv(trans)); + iwl_irq_handle_error(trans); handled |= CSR_INT_BIT_HW_ERR; @@ -1020,7 +1023,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) IWL_ERR(trans, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); isr_stats->sw++; - iwl_irq_handle_error(priv(trans)); + iwl_irq_handle_error(trans); handled |= CSR_INT_BIT_SW_ERR; } @@ -1188,11 +1191,10 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) /* Device is going up inform it about using ICT interrupt table, * also we need to tell the driver to start using ICT interrupt. */ -int iwl_reset_ict(struct iwl_priv *priv) +int iwl_reset_ict(struct iwl_trans *trans) { u32 val; unsigned long flags; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index e55636e1deaf..2ffacb2b2d77 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1528,7 +1528,7 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, int pos = 0; ssize_t ret = -ENOMEM; - ret = pos = iwl_dump_nic_event_log(priv(trans), true, &buf, true); + ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -1552,7 +1552,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, if (sscanf(buf, "%d", &event_log_flag) != 1) return -EFAULT; if (event_log_flag == 1) - iwl_dump_nic_event_log(priv(trans), true, NULL, false); + iwl_dump_nic_event_log(trans, true, NULL, false); return count; } From ab9e212e92aa2820a5b961c42142d36257b0742c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:10 -0700 Subject: [PATCH 087/129] iwlagn: remove unused parameters from hw_params Some of them weren't used at all, the others always had the same value since the driver split. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-5000.c | 8 -------- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 9 --------- drivers/net/wireless/iwlwifi/iwl-trans.c | 9 ++++++--- 9 files changed, 7 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index bd0ce3993b52..7d60cd2f49c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -129,10 +129,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).scd_bc_tbls_size = - priv->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - hw_params(priv).tfd_size = sizeof(struct iwl_tfd); hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 1a36edf05ee4..8d71eec36699 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -126,10 +126,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).scd_bc_tbls_size = - priv->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - hw_params(priv).tfd_size = sizeof(struct iwl_tfd); hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6048b3b8cd6a..55fdbf57df98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -157,10 +157,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).scd_bc_tbls_size = - priv->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - hw_params(priv).tfd_size = sizeof(struct iwl_tfd); hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; @@ -200,10 +196,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).scd_bc_tbls_size = - priv->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - hw_params(priv).tfd_size = sizeof(struct iwl_tfd); hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c2cba80fb73f..63089bc28d9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -146,10 +146,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).scd_bc_tbls_size = - priv->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - hw_params(priv).tfd_size = sizeof(struct iwl_tfd); hw_params(priv).max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bbdc475c74dd..61437438c843 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3191,8 +3191,6 @@ static u32 iwl_hw_detect(struct iwl_priv *priv) static int iwl_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_rxq_size = RX_QUEUE_SIZE; - hw_params(priv).max_rxq_log = RX_QUEUE_SIZE_LOG; if (iwlagn_mod_params.amsdu_size_8K) hw_params(priv).rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); @@ -3200,8 +3198,6 @@ static int iwl_set_hw_params(struct iwl_priv *priv) hw_params(priv).rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); - hw_params(priv).max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; - if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 86b974804ead..1426b2fb1c3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -673,7 +673,6 @@ struct iwl_rxon_assoc_cmd { #define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ -#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */ /* * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cfc23c25e979..048c8e2578f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -359,7 +359,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else { beacon_int = iwl_adjust_beacon_interval(beacon_int, - hw_params(priv).max_beacon_itrvl * TIME_UNIT); + IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 1229eb3c098c..7145e48bd014 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -121,12 +121,8 @@ struct iwl_mod_params { /** * struct iwl_hw_params * @max_txq_num: Max # Tx queues supported - * @scd_bc_tbls_size: size of scheduler byte count tables - * @tfd_size: TFD size * @tx/rx_chains_num: Number of TX/RX chains * @valid_tx/rx_ant: usable antennas - * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) - * @max_rxq_log: Log-base-2 of max_rxq_size * @rx_page_order: Rx buffer page order * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @max_stations: @@ -142,18 +138,13 @@ struct iwl_mod_params { */ struct iwl_hw_params { u8 max_txq_num; - u16 scd_bc_tbls_size; - u32 tfd_size; u8 tx_chains_num; u8 rx_chains_num; u8 valid_tx_ant; u8 valid_rx_ant; - u16 max_rxq_size; - u16 max_rxq_log; u32 rx_page_order; u8 max_stations; u8 ht40_channel; - u8 max_beacon_itrvl; /* in 1024 ms */ u32 max_inst_size; u32 max_data_size; u32 ct_kill_threshold; /* value in hw-dependent units */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 2ffacb2b2d77..4f3fdcaa63bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -302,7 +302,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - size_t tfd_sz = hw_params(trans).tfd_size * TFD_QUEUE_SIZE_MAX; + size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; int i; if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) @@ -448,7 +448,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { - dma_free_coherent(dev, hw_params(trans).tfd_size * + dma_free_coherent(dev, sizeof(struct iwl_tfd) * txq->q.n_bd, txq->tfds, txq->q.dma_addr); memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); } @@ -509,6 +509,9 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u16 scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ if (WARN_ON(priv->txq)) { @@ -517,7 +520,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) } ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, - hw_params(trans).scd_bc_tbls_size); + scd_bc_tbls_size); if (ret) { IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); goto error; From dda61a4482661d71034cc132d1f474f19ce34a4d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:11 -0700 Subject: [PATCH 088/129] iwlagn: iwl-dev.h doesn't include iwl-fh.h any more Since iwl-fh.h contains transport related data, it shouldn't be included by the upper layer. Only the transport layer and iwl-agn-ucode.c includes it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 13 ------------- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-fh.h | 18 ++++++++++++------ drivers/net/wireless/iwlwifi/iwl-sv-open.c | 1 - .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 2 ++ 8 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 47c43042ba4f..33951a11327d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -95,17 +95,4 @@ #define IWLAGN_NUM_AMPDU_QUEUES 9 #define IWLAGN_FIRST_AMPDU_QUEUE 11 -/* Fixed (non-configurable) rx data from phy */ - -/** - * struct iwlagn_schedq_bc_tbl scheduler byte count table - * base physical address provided by SCD_DRAM_BASE_ADDR - * @tfd_offset 0-12 - tx command byte count - * 12-16 - station index - */ -struct iwlagn_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __packed; - - #endif /* __iwl_agn_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a094b66541b1..033f595a6d55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -40,6 +40,7 @@ #include "iwl-agn.h" #include "iwl-agn-calib.h" #include "iwl-trans.h" +#include "iwl-fh.h" static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 61437438c843..5d2696257541 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3189,6 +3189,10 @@ static u32 iwl_hw_detect(struct iwl_priv *priv) return iwl_read32(priv, CSR_HW_REV); } +/* Size of one Rx buffer in host DRAM */ +#define IWL_RX_BUF_SIZE_4K (4 * 1024) +#define IWL_RX_BUF_SIZE_8K (8 * 1024) + static int iwl_set_hw_params(struct iwl_priv *priv) { if (iwlagn_mod_params.amsdu_size_8K) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 1426b2fb1c3a..56252897ab3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3911,6 +3911,7 @@ struct iwlagn_wowlan_kek_kck_material_cmd { * Union of all expected notifications/responses: * *****************************************************************************/ +#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ struct iwl_rx_packet { /* diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index de293cf02177..abc011834b9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -41,7 +41,6 @@ #include "iwl-eeprom.h" #include "iwl-csr.h" #include "iwl-prph.h" -#include "iwl-fh.h" #include "iwl-debug.h" #include "iwl-agn-hw.h" #include "iwl-led.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 0ad60b3c04db..c1b88376dad2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -266,8 +266,6 @@ #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) -#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ - /** * Rx Shared Status Registers (RSSR) * @@ -422,10 +420,6 @@ #define RX_FREE_BUFFERS 64 #define RX_LOW_WATERMARK 8 -/* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_4K (4 * 1024) -#define IWL_RX_BUF_SIZE_8K (8 * 1024) - /** * struct iwl_rb_status - reseve buffer status * host memory mapped FH registers @@ -508,4 +502,16 @@ struct iwl_tfd { /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ +/* Fixed (non-configurable) rx data from phy */ + +/** + * struct iwlagn_schedq_bc_tbl scheduler byte count table + * base physical address provided by SCD_DRAM_BASE_ADDR + * @tfd_offset 0-12 - tx command byte count + * 12-16 - station index + */ +struct iwlagn_scd_bc_tbl { + __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; +} __packed; + #endif /* !__iwl_fh_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 4d4358ae69a6..15c9be8d455f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -72,7 +72,6 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-debug.h" -#include "iwl-fh.h" #include "iwl-io.h" #include "iwl-agn.h" #include "iwl-testmode.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 59c6b3c673e4..af2d47820d05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -29,6 +29,8 @@ #ifndef __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__ +#include "iwl-fh.h" + /*This file includes the declaration that are internal to the * trans_pcie layer */ From 9d6b2cb1ccf9c1e00a0891eff78b93eb1a1fc372 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:12 -0700 Subject: [PATCH 089/129] iwlagn: move Keep Warm to transport layer It is relevant for PCIe only. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans.c | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index abc011834b9b..30963bba75c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1239,7 +1239,6 @@ struct iwl_priv { /* Tx DMA processing queues */ struct iwl_tx_queue *txq; unsigned long txq_ctx_active_msk; - struct iwl_dma_ptr kw; /* keep warm address */ /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index af2d47820d05..c258b3f47627 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -95,6 +95,7 @@ struct iwl_rx_queue { * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @scd_bc_tbls: pointer to the byte count table of the scheduler + * @kw: keep warm address */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -115,6 +116,7 @@ struct iwl_trans_pcie { u32 inta_mask; u32 scd_base_addr; struct iwl_dma_ptr scd_bc_tbls; + struct iwl_dma_ptr kw; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 4f3fdcaa63bc..14c22b7e8d6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -489,7 +489,7 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) kfree(priv->txq); priv->txq = NULL; - iwlagn_free_dma_ptr(trans, &priv->kw); + iwlagn_free_dma_ptr(trans, &trans_pcie->kw); iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); } @@ -527,7 +527,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) } /* Alloc keep-warm buffer */ - ret = iwlagn_alloc_dma_ptr(trans, &priv->kw, IWL_KW_SIZE); + ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); if (ret) { IWL_ERR(trans, "Keep Warm allocation failed\n"); goto error; @@ -567,6 +567,8 @@ static int iwl_tx_init(struct iwl_trans *trans) unsigned long flags; bool alloc = false; struct iwl_priv *priv = priv(trans); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); if (!priv->txq) { ret = iwl_trans_tx_alloc(trans); @@ -581,7 +583,7 @@ static int iwl_tx_init(struct iwl_trans *trans) iwl_write_prph(priv, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, trans_pcie->kw.dma >> 4); spin_unlock_irqrestore(&trans->shrd->lock, flags); From a72b8b088c3465b28192c1a14ba97be8223a8cec Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:13 -0700 Subject: [PATCH 090/129] iwlagn: add missing includes a few h files weren't self contained. Fix that. Move iwl_dma_ptr to transport layer since it is not used by the upper layer any more. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-bus.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ------- drivers/net/wireless/iwlwifi/iwl-fh.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-shared.h | 5 +++++ .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 19 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 1 - drivers/net/wireless/iwlwifi/iwl-trans.h | 4 ++++ 8 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index edec2f2647d8..e1cb65c45395 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -65,6 +65,8 @@ /*This file includes the declaration that are exported from the bus layer */ +#include + struct iwl_shared; struct iwl_bus; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 4b042e91f65c..7014f4124484 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -29,6 +29,7 @@ #ifndef __iwl_debug_h__ #define __iwl_debug_h__ +#include "iwl-bus.h" #include "iwl-shared.h" struct iwl_priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 30963bba75c1..12cca9deabdc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -641,13 +641,6 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) return index & (q->n_window - 1); } - -struct iwl_dma_ptr { - dma_addr_t dma; - void *addr; - size_t size; -}; - #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 #define IWL_OPERATION_MODE_MIXED 2 diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index c1b88376dad2..5bede9d7f955 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -63,6 +63,8 @@ #ifndef __iwl_fh_h__ #define __iwl_fh_h__ +#include + /****************************/ /* Flow Handler Definitions */ /****************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 7145e48bd014..45f8a33df6e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -63,6 +63,11 @@ #ifndef __iwl_shared_h__ #define __iwl_shared_h__ +#include +#include +#include +#include + /*This files includes all the types / functions that are exported by the * upper layer to the bus and transport layer */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index c258b3f47627..b77b0f79fcb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -29,7 +29,20 @@ #ifndef __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__ +#include +#include +#include + #include "iwl-fh.h" +#include "iwl-csr.h" +#include "iwl-shared.h" +#include "iwl-trans.h" +#include "iwl-debug.h" +#include "iwl-io.h" + +struct iwl_tx_queue; +struct iwl_queue; +struct iwl_host_cmd; /*This file includes the declaration that are internal to the * trans_pcie layer */ @@ -88,6 +101,12 @@ struct iwl_rx_queue { spinlock_t lock; }; +struct iwl_dma_ptr { + dma_addr_t dma; + void *addr; + size_t size; +}; + /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 14c22b7e8d6f..95c9e8794839 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -72,7 +72,6 @@ #include "iwl-trans-int-pcie.h" /*TODO remove uneeded includes when the transport layer tx_free will be here */ #include "iwl-agn.h" -#include "iwl-core.h" #include "iwl-shared.h" static int iwl_trans_rx_alloc(struct iwl_trans *trans) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 78bd2f636452..0da6ad593f05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -64,6 +64,10 @@ #define __iwl_trans_h__ #include +#include + +#include "iwl-shared.h" +#include "iwl-commands.h" /*This file includes the declaration that are exported from the transport * layer */ From 83ed90155f98bd949735c2cc22d832b557a6d7d1 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:14 -0700 Subject: [PATCH 091/129] iwlagn: all function iwl-io.c receive iwl_bus Which means that iwl-io.c doesn't need to include iwl-dev.h any more. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 14 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 20 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 59 +++--- drivers/net/wireless/iwlwifi/iwl-bus.h | 3 + drivers/net/wireless/iwlwifi/iwl-core.c | 27 +-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 - drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 + drivers/net/wireless/iwlwifi/iwl-eeprom.c | 58 +++--- drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +- drivers/net/wireless/iwlwifi/iwl-io.c | 192 +++++++++--------- drivers/net/wireless/iwlwifi/iwl-io.h | 61 +++--- drivers/net/wireless/iwlwifi/iwl-led.c | 6 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 4 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 8 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 6 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 8 +- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 72 +++---- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 34 ++-- drivers/net/wireless/iwlwifi/iwl-trans.c | 113 ++++++----- 24 files changed, 363 insertions(+), 351 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 7d60cd2f49c6..3368b8dea199 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -85,13 +85,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) static void iwl1000_nic_config(struct iwl_priv *priv) { /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); /* Setting digital SVR for 1000 card to 1.32V */ /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, + iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG, APMG_SVR_DIGITAL_VOLTAGE_1_32, ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 8d71eec36699..047c22b64285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -89,7 +89,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); if (priv->cfg->iq_invert) - iwl_set_bit(priv, CSR_GP_DRIVER_REG, + iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 55fdbf57df98..d2ef4be44c61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -75,7 +75,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv) * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 63089bc28d9c..955a99cef949 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -83,7 +83,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(priv, CSR_GP_DRIVER_REG, + iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); } @@ -91,9 +91,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(priv, CSR_GP_DRIVER_REG, + iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(priv, CSR_GP_DRIVER_REG, + iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_6050_1x2); } @@ -105,7 +105,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) /* no locking required for register write */ if (priv->cfg->pa_type == IWL_PA_INTERNAL) { /* 2x2 IPA phy type */ - iwl_write32(priv, CSR_GP_DRIVER_REG, + iwl_write32(bus(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* do additional nic configuration if needed */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 1a39aafb3b05..495f93664741 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -181,19 +181,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) if (tt->state == IWL_TI_CT_KILL) { if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; } else { - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = true; } - iwl_read32(priv, CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); + spin_lock_irqsave(&bus(priv)->reg_lock, flags); + if (!iwl_grab_nic_access(bus(priv))) + iwl_release_nic_access(bus(priv)); + spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); /* Reschedule the ct_kill timer to occur in * CT_KILL_EXIT_DURATION seconds to ensure we get a diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 033f595a6d55..02b00d177323 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -85,29 +85,29 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, priv->ucode_write_complete = 0; - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), (iwl_get_dma_hi_addr(phy_addr) << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - iwl_write_direct32(priv, + iwl_write_direct32(bus(priv), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | @@ -384,9 +384,9 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -405,14 +405,14 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); for (offs = 0; offs < len && errors < 20; offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERR(priv, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5d2696257541..37d2043fb7e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -329,14 +329,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (iwl_grab_nic_access(priv)) { - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); + if (iwl_grab_nic_access(bus(priv))) { + spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); return; } /* Set starting address; reads will auto-increment */ - iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -344,20 +344,20 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } } /* Allow device to power down */ - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + iwl_release_nic_access(bus(priv)); + spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); } static void iwl_continuous_event_trace(struct iwl_priv *priv) @@ -370,10 +370,12 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - capacity = iwl_read_targ_mem(priv, base); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(bus(priv), base); + num_wraps = iwl_read_targ_mem(bus(priv), + base + (2 * sizeof(u32))); + mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); + next_entry = iwl_read_targ_mem(bus(priv), + base + (3 * sizeof(u32))); } else return; @@ -1316,7 +1318,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) int ret = 0; spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); spin_unlock_irqrestore(&priv->shrd->lock, flags); priv->thermal_throttle.ct_kill_toggle = false; @@ -1934,7 +1936,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) /* User space software may expect getting rfkill changes * even if interface is down */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -2329,7 +2331,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, device_set_wakeup_enable(priv->bus->dev, true); /* Now let the ucode operate on its own */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); goto out; @@ -2355,19 +2357,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) mutex_lock(&priv->shrd->mutex); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - spin_lock_irqsave(&priv->reg_lock, flags); - ret = iwl_grab_nic_access_silent(priv); + spin_lock_irqsave(&bus(priv)->reg_lock, flags); + ret = iwl_grab_nic_access_silent(bus(priv)); if (ret == 0) { - iwl_write32(priv, HBUS_TARG_MEM_RADDR, base); - status = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(priv); + iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(bus(priv)); } - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); #ifdef CONFIG_IWLWIFI_DEBUGFS if (ret == 0) { @@ -2378,7 +2380,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) if (priv->wowlan_sram) _iwl_read_targ_mem_words( - priv, 0x800000, priv->wowlan_sram, + bus(priv), 0x800000, priv->wowlan_sram, priv->ucode_wowlan.data.len / 4); } #endif @@ -3186,7 +3188,7 @@ struct ieee80211_ops iwlagn_hw_ops = { static u32 iwl_hw_detect(struct iwl_priv *priv) { - return iwl_read32(priv, CSR_HW_REV); + return iwl_read32(bus(priv), CSR_HW_REV); } /* Size of one Rx buffer in host DRAM */ @@ -3286,7 +3288,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ - spin_lock_init(&priv->reg_lock); + spin_lock_init(&bus(priv)->reg_lock); spin_lock_init(&priv->shrd->lock); /* @@ -3294,7 +3296,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, * strange state ... like being left stranded by a primary kernel * and this is now the kdump kernel trying to start up */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /*********************** * 3. Read REV register @@ -3375,7 +3377,8 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + if (iwl_read32(bus(priv), + CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index e1cb65c45395..83aed46673e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -66,6 +66,7 @@ /*This file includes the declaration that are exported from the bus layer */ #include +#include struct iwl_shared; struct iwl_bus; @@ -96,6 +97,7 @@ struct iwl_bus_ops { * @ops - pointer to iwl_bus_ops * @shrd - pointer to iwl_shared which holds shared data from the upper layer * @irq - the irq number for the device + * @reg_lock - protect hw register access */ struct iwl_bus { /* Common data to all buses */ @@ -104,6 +106,7 @@ struct iwl_bus { struct iwl_shared *shrd; unsigned int irq; + spinlock_t reg_lock; /* pointer to bus specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 048c8e2578f5..411edc8f3f9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -907,9 +907,10 @@ static int iwl_apm_stop_master(struct iwl_priv *priv) int ret = 0; /* stop device's busmaster DMA activity */ - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, + ret = iwl_poll_bit(bus(priv), CSR_RESET, + CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (ret) IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); @@ -929,7 +930,7 @@ void iwl_apm_stop(struct iwl_priv *priv) iwl_apm_stop_master(priv); /* Reset the entire device */ - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -937,7 +938,7 @@ void iwl_apm_stop(struct iwl_priv *priv) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } @@ -957,45 +958,45 @@ int iwl_apm_init(struct iwl_priv *priv) */ /* Disable L0S exit timer (platform NMI Work/Around) */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); /* * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); bus_apm_config(priv->bus); /* Configure analog phase-lock-loop before activating to D0A */ if (priv->cfg->base_params->pll_cfg_val) - iwl_set_bit(priv, CSR_ANA_PLL_CFG, + iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG, priv->cfg->base_params->pll_cfg_val); /* * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. */ - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* * Wait for clock stabilization; once stabilized, access to * device-internal resources is supported, e.g. iwl_write_prph() * and accesses to uCode SRAM. */ - ret = iwl_poll_bit(priv, CSR_GP_CNTRL, + ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { @@ -1010,11 +1011,11 @@ int iwl_apm_init(struct iwl_priv *priv) * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, + iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a12b8d47ccbc..a01beb31d994 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -254,7 +254,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, sram = priv->dbgfs_sram_offset & ~0x3; /* read the first u32 from sram */ - val = iwl_read_targ_mem(priv, sram); + val = iwl_read_targ_mem(bus(priv), sram); for (; len; len--) { /* put the address at the start of every line */ @@ -273,7 +273,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, if (++offset == 4) { sram += 4; offset = 0; - val = iwl_read_targ_mem(priv, sram); + val = iwl_read_targ_mem(bus(priv), sram); } /* put in extra spaces and split lines for human readability */ @@ -1954,7 +1954,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, const size_t bufsz = sizeof(buf); u32 pwrsave_status; - pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & + pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 12cca9deabdc..711f2afceedd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1169,9 +1169,6 @@ struct iwl_priv { u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; - /* spinlock */ - spinlock_t reg_lock; /* protect hw register access */ - /*TODO: remove these pointers - use bus(priv) instead */ struct iwl_bus *bus; /* bus specific data */ diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 2c84ba95afca..8a51c5ccda1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -29,6 +29,8 @@ #include +struct iwl_priv; + #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c790f7f2ffaa..80ee65be9cd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -155,11 +155,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); @@ -176,14 +176,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) { - iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); } static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { - u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; + u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; int ret = 0; IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); @@ -216,13 +216,13 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { - iwl_read32(priv, CSR_OTP_GP_REG); + iwl_read32(bus(priv), CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) - iwl_clear_bit(priv, CSR_OTP_GP_REG, + iwl_clear_bit(bus(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); else - iwl_set_bit(priv, CSR_OTP_GP_REG, + iwl_set_bit(bus(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); } @@ -243,7 +243,7 @@ static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) nvm_type = NVM_DEVICE_TYPE_EEPROM; break; default: - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) nvm_type = NVM_DEVICE_TYPE_OTP; else @@ -258,22 +258,22 @@ static int iwl_init_otp_access(struct iwl_priv *priv) int ret; /* Enable 40MHz radio clock */ - iwl_write32(priv, CSR_GP_CNTRL, - iwl_read32(priv, CSR_GP_CNTRL) | + iwl_write32(bus(priv), CSR_GP_CNTRL, + iwl_read32(bus(priv), CSR_GP_CNTRL) | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ - ret = iwl_poll_bit(priv, CSR_GP_CNTRL, + ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { - iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_prph(bus(priv), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, + iwl_clear_bits_prph(bus(priv), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); /* @@ -281,7 +281,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) * this is only applicable for HW with OTP shadow RAM */ if (priv->cfg->base_params->shadow_ram_support) - iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, + iwl_set_bit(bus(priv), CSR_DBG_LINK_PWR_MGMT_REG, CSR_RESET_LINK_PWR_MGMT_DISABLED); } return ret; @@ -293,9 +293,9 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - iwl_write32(priv, CSR_EEPROM_REG, + iwl_write32(bus(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(priv, CSR_EEPROM_REG, + ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -303,13 +303,13 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(priv, CSR_EEPROM_REG); + r = iwl_read32(bus(priv), CSR_EEPROM_REG); /* check for ECC errors: */ - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgement */ - iwl_set_bit(priv, CSR_OTP_GP_REG, + iwl_set_bit(bus(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); return -EINVAL; @@ -317,7 +317,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { /* continue in this case */ /* set the correctable OTP ECC bit for acknowledgement */ - iwl_set_bit(priv, CSR_OTP_GP_REG, + iwl_set_bit(bus(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } @@ -424,7 +424,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { __le16 *e; - u32 gp = iwl_read32(priv, CSR_EEPROM_GP); + u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); int sz; int ret; u16 addr; @@ -469,11 +469,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - iwl_write32(priv, CSR_EEPROM_GP, - iwl_read32(priv, CSR_EEPROM_GP) & + iwl_write32(bus(priv), CSR_EEPROM_GP, + iwl_read32(bus(priv), CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - iwl_set_bit(priv, CSR_OTP_GP_REG, + iwl_set_bit(bus(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ @@ -498,10 +498,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(priv, CSR_EEPROM_REG, + iwl_write32(bus(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(priv, CSR_EEPROM_REG, + ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -509,7 +509,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = iwl_read32(priv, CSR_EEPROM_REG); + r = iwl_read32(bus(priv), CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } @@ -838,7 +838,7 @@ void iwl_rf_config(struct iwl_priv *priv) /* write radio config values to register */ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); @@ -850,7 +850,7 @@ void iwl_rf_config(struct iwl_priv *priv) WARN_ON(1); /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); } diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index f744fdc39a4d..8ca624d2a8b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -141,7 +141,7 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv, static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); - iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index aa4a90674452..3ffa8e62b856 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -25,46 +25,50 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ +#include +#include #include "iwl-io.h" +#include"iwl-csr.h" +#include "iwl-debug.h" #define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) { - iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); + iwl_write32(bus, reg, iwl_read32(bus, reg) | mask); } -static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) { - iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); + iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask); } -void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - __iwl_set_bit(priv, reg, mask); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + __iwl_set_bit(bus, reg, mask); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - __iwl_clear_bit(priv, reg, mask); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + __iwl_clear_bit(bus, reg, mask); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -int iwl_poll_bit(struct iwl_priv *priv, u32 addr, +int iwl_poll_bit(struct iwl_bus *bus, u32 addr, u32 bits, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read32(priv, addr) & mask) == (bits & mask)) + if ((iwl_read32(bus, addr) & mask) == (bits & mask)) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -73,14 +77,14 @@ int iwl_poll_bit(struct iwl_priv *priv, u32 addr, return -ETIMEDOUT; } -int iwl_grab_nic_access_silent(struct iwl_priv *priv) +int iwl_grab_nic_access_silent(struct iwl_bus *bus) { int ret; - lockdep_assert_held(&priv->reg_lock); + lockdep_assert_held(&bus->reg_lock); /* this bit wakes up the NIC */ - __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * These bits say the device is running, and should keep running for @@ -101,70 +105,70 @@ int iwl_grab_nic_access_silent(struct iwl_priv *priv) * 5000 series and later (including 1000 series) have non-volatile SRAM, * and do not save/restore SRAM when power cycling. */ - ret = iwl_poll_bit(priv, CSR_GP_CNTRL, + ret = iwl_poll_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } return 0; } -int iwl_grab_nic_access(struct iwl_priv *priv) +int iwl_grab_nic_access(struct iwl_bus *bus) { - int ret = iwl_grab_nic_access_silent(priv); + int ret = iwl_grab_nic_access_silent(bus); if (ret) { - u32 val = iwl_read32(priv, CSR_GP_CNTRL); - IWL_ERR(priv, + u32 val = iwl_read32(bus, CSR_GP_CNTRL); + IWL_ERR(bus, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); } return ret; } -void iwl_release_nic_access(struct iwl_priv *priv) +void iwl_release_nic_access(struct iwl_bus *bus) { - lockdep_assert_held(&priv->reg_lock); - __iwl_clear_bit(priv, CSR_GP_CNTRL, + lockdep_assert_held(&bus->reg_lock); + __iwl_clear_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } -u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg) { u32 value; unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - value = iwl_read32(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); + value = iwl_read32(bus(bus), reg); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); return value; } -void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) +void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write32(priv, reg, value); - iwl_release_nic_access(priv); + spin_lock_irqsave(&bus->reg_lock, flags); + if (!iwl_grab_nic_access(bus)) { + iwl_write32(bus, reg, value); + iwl_release_nic_access(bus); } - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read_direct32(priv, addr) & mask) == mask) + if ((iwl_read_direct32(bus, addr) & mask) == mask) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -173,122 +177,122 @@ int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, return -ETIMEDOUT; } -static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) +static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg) { - iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); rmb(); - return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); + return iwl_read32(bus, HBUS_TARG_PRPH_RDAT); } -static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) { - iwl_write32(priv, HBUS_TARG_PRPH_WADDR, + iwl_write32(bus, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); wmb(); - iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); + iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val); } -u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) +u32 iwl_read_prph(struct iwl_bus *bus, u32 reg) { unsigned long flags; u32 val; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - val = __iwl_read_prph(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); + val = __iwl_read_prph(bus, reg); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); return val; } -void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - __iwl_write_prph(priv, addr, val); - iwl_release_nic_access(priv); + spin_lock_irqsave(&bus->reg_lock, flags); + if (!iwl_grab_nic_access(bus)) { + __iwl_write_prph(bus, addr, val); + iwl_release_nic_access(bus); } - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); + __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, +void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, u32 bits, u32 mask) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - __iwl_write_prph(priv, reg, - (__iwl_read_prph(priv, reg) & mask) | bits); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); + __iwl_write_prph(bus, reg, + (__iwl_read_prph(bus, reg) & mask) | bits); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - val = __iwl_read_prph(priv, reg); - __iwl_write_prph(priv, reg, (val & ~mask)); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); + val = __iwl_read_prph(bus, reg); + __iwl_write_prph(bus, reg, (val & ~mask)); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, void *buf, int words) { unsigned long flags; int offs; u32 *vals = buf; - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); + spin_lock_irqsave(&bus->reg_lock, flags); + iwl_grab_nic_access(bus); - iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); + iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr); rmb(); for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); + iwl_release_nic_access(bus); + spin_unlock_irqrestore(&bus->reg_lock, flags); } -u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) { u32 value; - _iwl_read_targ_mem_words(priv, addr, &value, 1); + _iwl_read_targ_mem_words(bus, addr, &value, 1); return value; } -void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) +void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); + spin_lock_irqsave(&bus->reg_lock, flags); + if (!iwl_grab_nic_access(bus)) { + iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr); wmb(); - iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(priv); + iwl_write32(bus, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(bus); } - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&bus->reg_lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 19a093101122..ced2cbeb6eae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -29,65 +29,62 @@ #ifndef __iwl_io_h__ #define __iwl_io_h__ -#include - -#include "iwl-dev.h" -#include "iwl-debug.h" #include "iwl-devtrace.h" +#include "iwl-shared.h" #include "iwl-bus.h" -static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) +static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) { - trace_iwlwifi_dev_iowrite8(priv, ofs, val); - bus_write8(priv->bus, ofs, val); + trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); + bus_write8(bus, ofs, val); } -static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) +static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) { - trace_iwlwifi_dev_iowrite32(priv, ofs, val); - bus_write32(priv->bus, ofs, val); + trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); + bus_write32(bus, ofs, val); } -static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) +static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) { - u32 val = bus_read32(priv->bus, ofs); - trace_iwlwifi_dev_ioread32(priv, ofs, val); + u32 val = bus_read32(bus, ofs); + trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); return val; } -void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); -void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask); -int iwl_poll_bit(struct iwl_priv *priv, u32 addr, +int iwl_poll_bit(struct iwl_bus *bus, u32 addr, u32 bits, u32 mask, int timeout); -int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, int timeout); -int iwl_grab_nic_access_silent(struct iwl_priv *priv); -int iwl_grab_nic_access(struct iwl_priv *priv); -void iwl_release_nic_access(struct iwl_priv *priv); +int iwl_grab_nic_access_silent(struct iwl_bus *bus); +int iwl_grab_nic_access(struct iwl_bus *bus); +void iwl_release_nic_access(struct iwl_bus *bus); -u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); -void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); +u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg); +void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value); -u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); -void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); -void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, +u32 iwl_read_prph(struct iwl_bus *bus, u32 reg); +void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val); +void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); -void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, void *buf, int words); -#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ +#define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \ do { \ BUILD_BUG_ON((bufsize) % sizeof(u32)); \ - _iwl_read_targ_mem_words(priv, addr, buf, \ + _iwl_read_targ_mem_words(bus, addr, buf, \ (bufsize) / sizeof(u32));\ } while (0) -u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); -void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); +u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr); +void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 4bc7389b1a6f..7dffed186f0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* Set led register off */ void iwlagn_led_enable(struct iwl_priv *priv) { - iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); + iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); } /* @@ -108,9 +108,9 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) }; u32 reg; - reg = iwl_read32(priv, CSR_LED_REG); + reg = iwl_read32(bus(priv), CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); return iwl_trans_send_cmd(trans(priv), &cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 191c16adeeb3..17f3fb241b6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -124,12 +124,12 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(priv(bus), CSR_GIO_REG, + iwl_set_bit(bus, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(priv(bus), CSR_GIO_REG, + iwl_clear_bit(bus, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index d7c7c93b2daf..2c6659c82f92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -531,16 +531,16 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(priv, HBUS_TARG_MBX_C, + iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(priv, HBUS_TARG_MBX_C, + iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } if (flags & CT_CARD_DISABLED) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 15c9be8d455f..b53d77b131d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -276,7 +276,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_REG_READ32: - val32 = iwl_read32(priv, ofs); + val32 = iwl_read32(bus(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -298,7 +298,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(priv, ofs, val32); + iwl_write32(bus(priv), ofs, val32); } break; case IWL_TM_CMD_APP2DEV_REG_WRITE8: @@ -308,7 +308,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); IWL_INFO(priv, "8bit value to write 0x%x\n", val8); - iwl_write8(priv, ofs, val8); + iwl_write8(bus(priv), ofs, val8); } break; default: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index b77b0f79fcb0..bd6e64026a06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -200,12 +200,12 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans) clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); /* disable interrupts from uCode/NIC to host */ - iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); + iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); /* acknowledge/clear/reset any interrupts still pending * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(priv(trans), CSR_INT, 0xffffffff); - iwl_write32(priv(trans), CSR_FH_INT_STATUS, 0xffffffff); + iwl_write32(bus(trans), CSR_INT, 0xffffffff); + iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff); IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); } @@ -216,7 +216,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &trans->shrd->status); - iwl_write32(priv(trans), CSR_INT_MASK, trans_pcie->inta_mask); + iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); } #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 7f8ac2ed49ab..5cff771af92f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -143,30 +143,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); + iwl_write32(bus(priv), FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); - iwl_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(bus(priv), FH_RSCSR_CHNL0_WPTR, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(bus(priv), FH_RSCSR_CHNL0_WPTR, q->write_actual); } } @@ -591,7 +591,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) return; } - iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); + iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table)); if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(trans, "Start IWL Error Log Dump:\n"); @@ -637,9 +637,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) struct iwl_priv *priv = priv(trans); /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (priv->cfg->internal_wimax_coex && - (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & + (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) & APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(priv, APMG_PS_CTRL_REG) & + (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) & APMG_PS_CTRL_VAL_RESET_REQ))) { /* * Keep the restart process from trying to send host @@ -706,18 +706,18 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, ptr = base + EVENT_START_OFFSET + (start_idx * event_size); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); + spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); + iwl_grab_nic_access(bus(priv)); /* Set starting address; reads will auto-increment */ - iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); rmb(); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ if (bufsz) { @@ -731,7 +731,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, time, ev); } } else { - data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (bufsz) { pos += scnprintf(*buf + pos, bufsz - pos, "EVT_LOGT:%010u:0x%08x:%04u\n", @@ -746,8 +746,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, } /* Allow device to power down */ - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + iwl_release_nic_access(bus(priv)); + spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); return pos; } @@ -824,10 +824,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, } /* event log header */ - capacity = iwl_read_targ_mem(priv, base); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(bus(priv), base); + mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(bus(priv), base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(bus(priv), base + (3 * sizeof(u32))); if (capacity > logsize) { IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " @@ -927,7 +927,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(priv(trans), CSR_INT, + iwl_write32(bus(trans), CSR_INT, trans_pcie->inta | ~trans_pcie->inta_mask); inta = trans_pcie->inta; @@ -935,7 +935,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); + inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", inta, inta_mask); } @@ -983,7 +983,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; @@ -1048,12 +1048,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(priv(trans), CSR_FH_INT_STATUS, + iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(priv(trans), + iwl_write32(bus(trans), CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the @@ -1068,7 +1068,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, + iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); iwl_rx_handle(trans); @@ -1080,7 +1080,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, + iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); isr_stats->rx++; @@ -1088,7 +1088,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; @@ -1216,10 +1216,10 @@ int iwl_reset_ict(struct iwl_trans *trans) val, (unsigned long long)trans_pcie->aligned_ict_tbl_dma); - iwl_write32(priv(trans), CSR_DRAM_INT_TBL_REG, val); + iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; trans_pcie->ict_index = 0; - iwl_write32(priv(trans), CSR_INT, trans_pcie->inta_mask); + iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); iwl_enable_interrupts(trans); spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -1259,11 +1259,11 @@ static irqreturn_t iwl_isr(int irq, void *data) * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ + iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv(trans), CSR_INT); + inta = iwl_read32(bus(trans), CSR_INT); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, @@ -1282,7 +1282,7 @@ static irqreturn_t iwl_isr(int irq, void *data) #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(priv(trans), CSR_FH_INT_STATUS); + inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS); IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -1345,8 +1345,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data) * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ + iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 835e3edb9cce..3105409bd3cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -96,7 +96,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) if (priv->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ - iwl_write32(priv, HBUS_TARG_WRPTR, + iwl_write32(bus(priv), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ @@ -104,18 +104,18 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup," " GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return; } - iwl_write_direct32(priv, HBUS_TARG_WRPTR, + iwl_write_direct32(bus(priv), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); /* @@ -124,7 +124,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl_write32(priv, HBUS_TARG_WRPTR, + iwl_write32(bus(priv), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } txq->need_update = 0; @@ -374,14 +374,14 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, tbl_dw_addr = trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl_read_targ_mem(priv(trans), tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl_write_targ_mem(priv(trans), tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw); return 0; } @@ -390,7 +390,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv(trans), + iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); @@ -399,9 +399,9 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index) { - iwl_write_direct32(priv(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv(trans), SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); } void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, @@ -411,7 +411,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, int txq_id = txq->q.id; int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(bus(priv), SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -459,10 +459,10 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<scd_base_addr + + iwl_write_targ_mem(bus(priv), trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << @@ -481,7 +481,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(bus(priv), SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); @@ -509,14 +509,14 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwlagn_tx_queue_stop_scheduler(trans, txq_id); - iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); + iwl_clear_bits_prph(bus(priv), SCD_AGGR_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); - iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(bus(priv), SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv, txq_id); iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 95c9e8794839..b95e71389b7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -144,6 +144,7 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, u32 rb_size; const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ + struct iwl_trans *trans = trans(priv); rb_timeout = RX_RB_TIMEOUT; @@ -153,17 +154,17 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; /* Stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* Reset driver's Rx queue write index */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, + iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4); /* Enable Rx DMA @@ -174,7 +175,7 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, * RB timeout 0x10 * 256 RBDs */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, + iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | @@ -184,7 +185,7 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } static int iwl_rx_init(struct iwl_trans *trans) @@ -268,8 +269,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans) { /* stop Rx DMA */ - iwl_write_direct32(priv(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(priv(trans), FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); } @@ -397,7 +398,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv(trans), FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); return 0; @@ -579,10 +580,11 @@ static int iwl_tx_init(struct iwl_trans *trans) spin_lock_irqsave(&trans->shrd->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(priv, SCD_TXFACT, 0); + iwl_write_prph(bus(trans), SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, trans_pcie->kw.dma >> 4); + iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -608,17 +610,18 @@ error: static void iwl_set_pwr_vmain(struct iwl_priv *priv) { + struct iwl_trans *trans = trans(priv); /* * (for documentation purposes) * to set power to V_AUX, do: if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); */ - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); } @@ -633,7 +636,8 @@ static int iwl_nic_init(struct iwl_trans *trans) iwl_apm_init(priv); /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); + iwl_write8(bus(trans), CSR_INT_COALESCING, + IWL_HOST_INT_CALIB_TIMEOUT_DEF); spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -650,7 +654,7 @@ static int iwl_nic_init(struct iwl_trans *trans) if (priv->cfg->base_params->shadow_reg_enable) { /* enable shadow regs in HW */ - iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, + iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); } @@ -666,11 +670,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) { int ret; - iwl_set_bit(priv(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = iwl_poll_bit(priv(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); @@ -691,10 +695,10 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) return 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); - ret = iwl_poll_bit(priv(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); @@ -722,7 +726,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & + if (iwl_read32(bus(trans), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); else @@ -734,7 +738,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) return -ERFKILL; } - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); ret = iwl_nic_init(trans); if (ret) { @@ -743,17 +747,17 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) } /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); iwl_enable_interrupts(trans); /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); return 0; } @@ -764,7 +768,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) */ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) { - iwl_write_prph(priv(trans), SCD_TXFACT, mask); + iwl_write_prph(bus(trans), SCD_TXFACT, mask); } #define IWL_AC_UNSET -1 @@ -814,46 +818,47 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) spin_lock_irqsave(&trans->shrd->lock, flags); - trans_pcie->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + trans_pcie->scd_base_addr = + iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; /* reset conext data memory */ for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(bus(trans), a, 0); /* reset tx status memory */ for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(bus(trans), a, 0); for (; a < trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(priv).max_txq_num); a += 4) - iwl_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(bus(trans), a, 0); - iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, + iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, trans_pcie->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, + reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - iwl_write_prph(priv, SCD_QUEUECHAIN_SEL, + iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, SCD_QUEUECHAIN_SEL_ALL(priv)); - iwl_write_prph(priv, SCD_AGGR_SEL, 0); + iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); /* initiate the queues */ for (i = 0; i < hw_params(priv).max_txq_num; i++) { - iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + + iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, trans_pcie->scd_base_addr + + iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << @@ -864,7 +869,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); } - iwl_write_prph(priv, SCD_INTERRUPT_MASK, + iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, IWL_MASK(0, hw_params(trans).max_txq_num)); /* Activate all Tx DMA/FIFO channels */ @@ -910,7 +915,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) spin_unlock_irqrestore(&trans->shrd->lock, flags); /* Enable L1-Active */ - iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, + iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } @@ -930,14 +935,14 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(priv(trans), + iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(priv(trans), FH_TSSR_TX_STATUS_REG, + if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) IWL_ERR(trans, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, - iwl_read_direct32(priv(trans), + iwl_read_direct32(bus(trans), FH_TSSR_TX_STATUS_REG)); } spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -957,7 +962,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) { /* stop and reset the on-board processor */ - iwl_write32(priv(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ iwl_trans_disable_sync_irq(trans); @@ -977,13 +982,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) iwl_trans_rx_stop(trans); /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv(trans), APMG_CLK_DIS_REG, + iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv(trans), CSR_GP_CNTRL, + iwl_clear_bit(bus(trans), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ @@ -1148,7 +1153,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) { /* Remove all resets to allow NIC to operate */ - iwl_write32(priv(trans), CSR_RESET, 0); + iwl_write32(bus(trans), CSR_RESET, 0); } static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) @@ -1253,7 +1258,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) iwl_enable_interrupts(trans); - if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rfkill = true; @@ -1712,7 +1717,7 @@ void iwl_dump_csr(struct iwl_trans *trans) for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { IWL_ERR(trans, " %25s: 0X%08x\n", get_csr_string(csr_tbl[i]), - iwl_read32(priv(trans), csr_tbl[i])); + iwl_read32(bus(trans), csr_tbl[i])); } } @@ -1784,7 +1789,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) pos += scnprintf(*buf + pos, bufsz - pos, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv(trans), fh_tbl[i])); + iwl_read_direct32(bus(trans), fh_tbl[i])); } return pos; } @@ -1793,7 +1798,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { IWL_ERR(trans, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv(trans), fh_tbl[i])); + iwl_read_direct32(bus(trans), fh_tbl[i])); } return 0; } From f090fba305658fe6e464e2fbd25fad81957ece26 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Thu, 25 Aug 2011 23:11:15 -0700 Subject: [PATCH 092/129] iwlagn: fix compile warnings when CONFIG_PM_SLEEP is not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/iwlwifi/iwl-pci.o drivers/net/wireless/iwlwifi/iwl-pci.c:506: warning: ‘iwl_pci_suspend’ defined but not used drivers/net/wireless/iwlwifi/iwl-pci.c:519: warning: ‘iwl_pci_resume’ defined but not used These are only used if CONFIG_PM_SLEEP is enabled. CONFIG_PM depends (CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME), so it can be set without CONFIG_PM_SLEEP selected. Signed-off-by: Daniel Halperin Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 17f3fb241b6f..62c35a5fea80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -506,7 +506,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_pci_down(bus); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int iwl_pci_suspend(struct device *device) { From 332a4bad975616f33c2d1bf94c4ace2ea4113835 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:16 -0700 Subject: [PATCH 093/129] iwlagn: iwl-pci doesn't include iwl-dev any more Move all the iwlXXX_abgn_cfg forward declaration to a separate file so that iwl-pci.c doesn't need to include iwl-agn.h that includes all iwl-dev.h This allows to provide real encapsulation. Dereferencing iwl_priv in the bus layer will now lead to a compilation error. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-2000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.h | 44 --------- drivers/net/wireless/iwlwifi/iwl-core.h | 5 - drivers/net/wireless/iwlwifi/iwl-dev.h | 2 - drivers/net/wireless/iwlwifi/iwl-pci.c | 11 +-- drivers/net/wireless/iwlwifi/iwl-pci.h | 115 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 5 + 10 files changed, 129 insertions(+), 57 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-pci.h diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3368b8dea199..4766c3a1a2f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -44,6 +44,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-shared.h" +#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 6 diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 047c22b64285..75ded3402e26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -45,6 +45,7 @@ #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-shared.h" +#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 6 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index d2ef4be44c61..7cb4d69e0c37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -47,6 +47,7 @@ #include "iwl-5000-hw.h" #include "iwl-trans.h" #include "iwl-shared.h" +#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 955a99cef949..2a98e65ca84c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,6 +46,7 @@ #include "iwl-6000-hw.h" #include "iwl-trans.h" #include "iwl-shared.h" +#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 3508c12de25f..2b94a10561d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,50 +65,6 @@ #include "iwl-dev.h" -/* configuration for the _agn devices */ -extern struct iwl_cfg iwl5300_agn_cfg; -extern struct iwl_cfg iwl5100_agn_cfg; -extern struct iwl_cfg iwl5350_agn_cfg; -extern struct iwl_cfg iwl5100_bgn_cfg; -extern struct iwl_cfg iwl5100_abg_cfg; -extern struct iwl_cfg iwl5150_agn_cfg; -extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6005_2agn_cfg; -extern struct iwl_cfg iwl6005_2abg_cfg; -extern struct iwl_cfg iwl6005_2bg_cfg; -extern struct iwl_cfg iwl6005_2agn_sff_cfg; -extern struct iwl_cfg iwl1030_bgn_cfg; -extern struct iwl_cfg iwl1030_bg_cfg; -extern struct iwl_cfg iwl6030_2agn_cfg; -extern struct iwl_cfg iwl6030_2abg_cfg; -extern struct iwl_cfg iwl6030_2bgn_cfg; -extern struct iwl_cfg iwl6030_2bg_cfg; -extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_2abg_cfg; -extern struct iwl_cfg iwl6000i_2bg_cfg; -extern struct iwl_cfg iwl6000_3agn_cfg; -extern struct iwl_cfg iwl6050_2agn_cfg; -extern struct iwl_cfg iwl6050_2abg_cfg; -extern struct iwl_cfg iwl6150_bgn_cfg; -extern struct iwl_cfg iwl6150_bg_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; -extern struct iwl_cfg iwl1000_bg_cfg; -extern struct iwl_cfg iwl100_bgn_cfg; -extern struct iwl_cfg iwl100_bg_cfg; -extern struct iwl_cfg iwl130_bgn_cfg; -extern struct iwl_cfg iwl130_bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_cfg; -extern struct iwl_cfg iwl2000_2bg_cfg; -extern struct iwl_cfg iwl2030_2bgn_cfg; -extern struct iwl_cfg iwl2030_2bg_cfg; -extern struct iwl_cfg iwl6035_2agn_cfg; -extern struct iwl_cfg iwl6035_2abg_cfg; -extern struct iwl_cfg iwl6035_2bg_cfg; -extern struct iwl_cfg iwl105_bg_cfg; -extern struct iwl_cfg iwl105_bgn_cfg; -extern struct iwl_cfg iwl135_bg_cfg; -extern struct iwl_cfg iwl135_bgn_cfg; - extern struct ieee80211_ops iwlagn_hw_ops; int iwl_reset_ict(struct iwl_trans *trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c3bdba5a48f2..2ea8a2e0dfbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -71,11 +71,6 @@ struct iwl_host_cmd; struct iwl_cmd; - -#define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" -#define DRV_AUTHOR "" - #define TIME_UNIT 1024 #define IWL_CMD(x) case x: return #x diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 711f2afceedd..eb98df6e883b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -51,8 +51,6 @@ #include "iwl-trans.h" #include "iwl-shared.h" -#define DRV_NAME "iwlagn" - struct iwl_tx_queue; /* CT-KILL constants */ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 62c35a5fea80..7210ff68ffbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -64,13 +64,11 @@ #include #include "iwl-bus.h" -#include "iwl-shared.h" -#include "iwl-agn.h" -#include "iwl-trans.h" - -/* TODO: iwl_set_bit and friends should be implemented in bus layer - * this would allow us not to include iwl-io.h here */ #include "iwl-io.h" +#include "iwl-shared.h" +#include "iwl-trans.h" +#include "iwl-csr.h" +#include "iwl-pci.h" /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -95,6 +93,7 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) { int pos; u16 pci_lnk_ctl; + struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); pos = pci_pcie_cap(pci_dev); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h new file mode 100644 index 000000000000..be692763e913 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-pci.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_pci_h__ +#define __iwl_pci_h__ + + +/* This file includes the declaration that are internal to the PCI + * implementation of the bus layer + */ + +/* configuration for the _agn devices */ +extern struct iwl_cfg iwl5300_agn_cfg; +extern struct iwl_cfg iwl5100_agn_cfg; +extern struct iwl_cfg iwl5350_agn_cfg; +extern struct iwl_cfg iwl5100_bgn_cfg; +extern struct iwl_cfg iwl5100_abg_cfg; +extern struct iwl_cfg iwl5150_agn_cfg; +extern struct iwl_cfg iwl5150_abg_cfg; +extern struct iwl_cfg iwl6005_2agn_cfg; +extern struct iwl_cfg iwl6005_2abg_cfg; +extern struct iwl_cfg iwl6005_2bg_cfg; +extern struct iwl_cfg iwl6005_2agn_sff_cfg; +extern struct iwl_cfg iwl1030_bgn_cfg; +extern struct iwl_cfg iwl1030_bg_cfg; +extern struct iwl_cfg iwl6030_2agn_cfg; +extern struct iwl_cfg iwl6030_2abg_cfg; +extern struct iwl_cfg iwl6030_2bgn_cfg; +extern struct iwl_cfg iwl6030_2bg_cfg; +extern struct iwl_cfg iwl6000i_2agn_cfg; +extern struct iwl_cfg iwl6000i_2abg_cfg; +extern struct iwl_cfg iwl6000i_2bg_cfg; +extern struct iwl_cfg iwl6000_3agn_cfg; +extern struct iwl_cfg iwl6050_2agn_cfg; +extern struct iwl_cfg iwl6050_2abg_cfg; +extern struct iwl_cfg iwl6150_bgn_cfg; +extern struct iwl_cfg iwl6150_bg_cfg; +extern struct iwl_cfg iwl1000_bgn_cfg; +extern struct iwl_cfg iwl1000_bg_cfg; +extern struct iwl_cfg iwl100_bgn_cfg; +extern struct iwl_cfg iwl100_bg_cfg; +extern struct iwl_cfg iwl130_bgn_cfg; +extern struct iwl_cfg iwl130_bg_cfg; +extern struct iwl_cfg iwl2000_2bgn_cfg; +extern struct iwl_cfg iwl2000_2bg_cfg; +extern struct iwl_cfg iwl2030_2bgn_cfg; +extern struct iwl_cfg iwl2030_2bg_cfg; +extern struct iwl_cfg iwl6035_2agn_cfg; +extern struct iwl_cfg iwl6035_2abg_cfg; +extern struct iwl_cfg iwl6035_2bg_cfg; +extern struct iwl_cfg iwl105_bg_cfg; +extern struct iwl_cfg iwl105_bgn_cfg; +extern struct iwl_cfg iwl135_bg_cfg; +extern struct iwl_cfg iwl135_bgn_cfg; + +#endif /* __iwl_pci_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 45f8a33df6e4..27aee528ce3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -77,6 +77,11 @@ struct iwl_priv; struct iwl_sensitivity_ranges; struct iwl_trans_ops; +#define DRV_NAME "iwlagn" +#define IWLWIFI_VERSION "in-tree:" +#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_AUTHOR "" + extern struct iwl_mod_params iwlagn_mod_params; /** From 1603dd495f87ae97763870d57237744d90bc2bab Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 25 Aug 2011 23:11:17 -0700 Subject: [PATCH 094/129] iwlagn: adding special "D" SKU for 2000 series One more sku for 2000 series with different Subsystem ID Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-pci.c | 1 + drivers/net/wireless/iwlwifi/iwl-pci.h | 1 + 3 files changed, 7 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 75ded3402e26..764d3104e128 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -282,6 +282,11 @@ struct iwl_cfg iwl2000_2bg_cfg = { IWL_DEVICE_2000, }; +struct iwl_cfg iwl2000_2bgn_d_cfg = { + .name = "2000D Series 2x2 BGN", + IWL_DEVICE_2000, +}; + #define IWL_DEVICE_2030 \ .fw_name_pre = IWL2030_FW_PRE, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 7210ff68ffbc..e41f53e5c307 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -332,6 +332,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, + {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)}, /* 2x30 Series */ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h index be692763e913..c0aea9e092cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.h +++ b/drivers/net/wireless/iwlwifi/iwl-pci.h @@ -102,6 +102,7 @@ extern struct iwl_cfg iwl130_bgn_cfg; extern struct iwl_cfg iwl130_bg_cfg; extern struct iwl_cfg iwl2000_2bgn_cfg; extern struct iwl_cfg iwl2000_2bg_cfg; +extern struct iwl_cfg iwl2000_2bgn_d_cfg; extern struct iwl_cfg iwl2030_2bgn_cfg; extern struct iwl_cfg iwl2030_2bg_cfg; extern struct iwl_cfg iwl6035_2agn_cfg; From 5f85a7890cbfd2be8f4c6620b2a6774d6b5ac647 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:18 -0700 Subject: [PATCH 095/129] iwlagn: iwl_tid_data moves to iwl-shared The rate scaling and the transport need to access the data in iwl_tid_data, hence the move. Note that the only component in the upper layer that needs this data is the rate scaling. Refactoring the rate scaling may help to move iwl_tid_data from the shared area to the transport area. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 18 +++---- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 47 ++++++++++--------- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 23 ++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 39 --------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 32 +++++++++++++ .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 2 +- 9 files changed, 82 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3870b723c8c2..356762f21d2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -297,10 +297,10 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, u8 *qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } else - return MAX_TID_COUNT; + return IWL_MAX_TID_COUNT; if (unlikely(tid >= TID_MAX_LOAD_COUNT)) - return MAX_TID_COUNT; + return IWL_MAX_TID_COUNT; tl = &lq_data->load[tid]; @@ -313,7 +313,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, tl->queue_count = 1; tl->head = 0; tl->packet_count[0] = 1; - return MAX_TID_COUNT; + return IWL_MAX_TID_COUNT; } time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); @@ -2261,7 +2261,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 done_search = 0; u16 high_low; s32 sr; - u8 tid = MAX_TID_COUNT; + u8 tid = IWL_MAX_TID_COUNT; struct iwl_tid_data *tid_data; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_rxon_context *ctx = sta_priv->common.ctx; @@ -2280,8 +2280,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); - if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { - tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; + if ((tid != IWL_MAX_TID_COUNT) && + (lq_sta->tx_agg_tid_en & (1 << tid))) { + tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid]; if (tid_data->agg.state == IWL_AGG_OFF) lq_sta->is_agg = 0; else @@ -2651,9 +2652,10 @@ lq_update: iwl_ht_enabled(priv)) { if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && - (tid != MAX_TID_COUNT)) { + (tid != IWL_MAX_TID_COUNT)) { + u8 sta_id = lq_sta->lq.sta_id; tid_data = - &priv->stations[lq_sta->lq.sta_id].tid[tid]; + &priv->shrd->tid_data[sta_id][tid]; if (tid_data->agg.state == IWL_AGG_OFF) { IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 97d03a85d579..bb6605b51956 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -410,13 +410,15 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { u8 *qc = NULL; + struct iwl_tid_data *tid_data; qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + tid_data = &priv->shrd->tid_data[sta_id][tid]; - if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) + if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) goto drop_unlock_sta; - seq_number = priv->stations[sta_id].tid[tid].seq_number; + seq_number = tid_data->seq_number; seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl = hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG); @@ -424,8 +426,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) seq_number += 0x10; /* aggregation is on for this */ if (info->flags & IEEE80211_TX_CTL_AMPDU && - priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { - txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + tid_data->agg.state == IWL_AGG_ON) { + txq_id = tid_data->agg.txq_id; is_agg = true; } } @@ -456,9 +458,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { - priv->stations[sta_id].tid[tid].tfds_in_queue++; + priv->shrd->tid_data[sta_id][tid].tfds_in_queue++; if (!ieee80211_has_morefrags(fc)) - priv->stations[sta_id].tid[tid].seq_number = seq_number; + priv->shrd->tid_data[sta_id][tid].seq_number = + seq_number; } spin_unlock(&priv->shrd->sta_lock); @@ -521,10 +524,10 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; } - if (unlikely(tid >= MAX_TID_COUNT)) + if (unlikely(tid >= IWL_MAX_TID_COUNT)) return -EINVAL; - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { + if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); return -ENXIO; } @@ -536,7 +539,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, } spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; + tid_data = &priv->shrd->tid_data[sta_id][tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; tid_data->agg.tx_fifo = tx_fifo; @@ -548,7 +551,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, return ret; spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; + tid_data = &priv->shrd->tid_data[sta_id][tid]; if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; @@ -583,11 +586,11 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; + tid_data = &priv->shrd->tid_data[sta_id][tid]; ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; txq_id = tid_data->agg.txq_id; - switch (priv->stations[sta_id].tid[tid].agg.state) { + switch (priv->shrd->tid_data[sta_id][tid].agg.state) { case IWL_EMPTYING_HW_QUEUE_ADDBA: /* * This can happen if the peer stops aggregation @@ -609,7 +612,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, /* The queue is not empty */ if (write_ptr != read_ptr) { IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); - priv->stations[sta_id].tid[tid].agg.state = + priv->shrd->tid_data[sta_id][tid].agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return 0; @@ -617,7 +620,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_DEBUG_HT(priv, "HW queue is empty\n"); turn_off: - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + priv->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; /* do not restore/save irqs */ spin_unlock(&priv->shrd->sta_lock); @@ -643,14 +646,14 @@ static int iwlagn_txq_check_empty(struct iwl_priv *priv, { struct iwl_queue *q = &priv->txq[txq_id].q; u8 *addr = priv->stations[sta_id].sta.sta.addr; - struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid]; struct iwl_rxon_context *ctx; ctx = &priv->contexts[priv->stations[sta_id].ctxid]; lockdep_assert_held(&priv->shrd->sta_lock); - switch (priv->stations[sta_id].tid[tid].agg.state) { + switch (priv->shrd->tid_data[sta_id][tid].agg.state) { case IWL_EMPTYING_HW_QUEUE_DELBA: /* We are reclaiming the last packet of the */ /* aggregated HW queue */ @@ -815,7 +818,7 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, IWLAGN_TX_RES_TID_POS; int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> IWLAGN_TX_RES_RA_POS; - struct iwl_ht_agg *agg = &priv->stations[sta_id].tid[tid].agg; + struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg; u32 status = le16_to_cpu(tx_resp->status.status); int i; @@ -893,13 +896,13 @@ static void iwl_free_tfds_in_queue(struct iwl_priv *priv, { lockdep_assert_held(&priv->shrd->sta_lock); - if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + if (priv->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) + priv->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; else { IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->stations[sta_id].tid[tid].tfds_in_queue, + priv->shrd->tid_data[sta_id][tid].tfds_in_queue, freed); - priv->stations[sta_id].tid[tid].tfds_in_queue = 0; + priv->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; } } @@ -1149,7 +1152,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, txq = &priv->txq[scd_flow]; sta_id = ba_resp->sta_id; tid = ba_resp->tid; - agg = &priv->stations[sta_id].tid[tid].agg; + agg = &priv->shrd->tid_data[sta_id][tid].agg; /* Find index of block-ack window */ index = ba_resp_scd_ssn & (txq->q.n_bd - 1); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 37d2043fb7e9..1cf36783c1c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2203,7 +2203,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * since the uCode will add 0x10 before using the value. */ for (i = 0; i < 8; i++) { - seq = priv->stations[IWL_AP_ID].tid[i].seq_number; + seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; seq -= 0x10; wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); } diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 56252897ab3e..cb06196e0e80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -808,6 +808,7 @@ struct iwl_qosparam_cmd { #define IWLAGN_STATION_COUNT 16 #define IWL_INVALID_STATION 255 +#define IWL_MAX_TID_COUNT 9 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a01beb31d994..e320cc10167e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -340,6 +340,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = file->private_data; struct iwl_station_entry *station; + struct iwl_tid_data *tid_data; int max_sta = hw_params(priv).max_stations; char *buf; int i, j, pos = 0; @@ -363,22 +364,18 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, i, station->sta.sta.addr, station->sta.station_flags_msk); pos += scnprintf(buf + pos, bufsz - pos, - "TID\tseq_num\ttxq_id\tframes\ttfds\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "start_idx\tbitmap\t\t\trate_n_flags\n"); + "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n"); - for (j = 0; j < MAX_TID_COUNT; j++) { + for (j = 0; j < IWL_MAX_TID_COUNT; j++) { + tid_data = &priv->shrd->tid_data[i][j]; pos += scnprintf(buf + pos, bufsz - pos, - "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", - j, station->tid[j].seq_number, - station->tid[j].agg.txq_id, - station->tid[j].agg.frame_count, - station->tid[j].tfds_in_queue, - station->tid[j].agg.start_idx, - station->tid[j].agg.bitmap, - station->tid[j].agg.rate_n_flags); + "%d:\t%#x\t%#x\t%u\t%#x", + j, tid_data->seq_number, + tid_data->agg.txq_id, + tid_data->tfds_in_queue, + tid_data->agg.rate_n_flags); - if (station->tid[j].agg.wait_for_ba) + if (tid_data->agg.wait_for_ba) pos += scnprintf(buf + pos, bufsz - pos, " - waitforba"); pos += scnprintf(buf + pos, bufsz - pos, "\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index eb98df6e883b..6a6aba052782 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -331,47 +331,9 @@ struct iwl_host_cmd { #define IWL_SUPPORTED_RATES_IE_LEN 8 -#define MAX_TID_COUNT 9 - #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 -/** - * struct iwl_ht_agg -- aggregation status while waiting for block-ack - * @txq_id: Tx queue used for Tx attempt - * @frame_count: # frames attempted by Tx command - * @wait_for_ba: Expect block-ack before next Tx reply - * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window - * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window - * @bitmap1: High order, one bit for each frame pending ACK in Tx window - * @rate_n_flags: Rate at which Tx was attempted - * - * If REPLY_TX indicates that aggregation was attempted, driver must wait - * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info - * until block ack arrives. - */ -struct iwl_ht_agg { - u16 txq_id; - u16 frame_count; - u16 wait_for_ba; - u16 start_idx; - u64 bitmap; - u32 rate_n_flags; -#define IWL_AGG_OFF 0 -#define IWL_AGG_ON 1 -#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 -#define IWL_EMPTYING_HW_QUEUE_DELBA 3 - u8 state; - u8 tx_fifo; -}; - - -struct iwl_tid_data { - u16 seq_number; /* agn only */ - u16 tfds_in_queue; - struct iwl_ht_agg agg; -}; - union iwl_ht_rate_supp { u16 rates; struct { @@ -422,7 +384,6 @@ struct iwl_qos_info { */ struct iwl_station_entry { struct iwl_addsta_cmd sta; - struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used, ctxid; struct iwl_link_quality_cmd *lq; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 27aee528ce3a..bb61c13d4998 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -68,6 +68,8 @@ #include #include +#include "iwl-commands.h" + /*This files includes all the types / functions that are exported by the * upper layer to the bus and transport layer */ @@ -166,6 +168,34 @@ struct iwl_hw_params { const struct iwl_sensitivity_ranges *sens; }; +/** + * struct iwl_ht_agg - aggregation status while waiting for block-ack + * @txq_id: Tx queue used for Tx attempt + * @wait_for_ba: Expect block-ack before next Tx reply + * @rate_n_flags: Rate at which Tx was attempted + * + * If REPLY_TX indicates that aggregation was attempted, driver must wait + * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info + * until block ack arrives. + */ +struct iwl_ht_agg { + u16 txq_id; + u16 wait_for_ba; + u32 rate_n_flags; +#define IWL_AGG_OFF 0 +#define IWL_AGG_ON 1 +#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 +#define IWL_EMPTYING_HW_QUEUE_DELBA 3 + u8 state; + u8 tx_fifo; +}; + +struct iwl_tid_data { + u16 seq_number; /* agn only */ + u16 tfds_in_queue; + struct iwl_ht_agg agg; +}; + /** * struct iwl_shared - shared fields for all the layers of the driver * @@ -200,6 +230,8 @@ struct iwl_shared { spinlock_t lock; spinlock_t sta_lock; struct mutex mutex; + + struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 3105409bd3cc..9f4ffebfa56d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -438,11 +438,11 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, if (WARN_ON(sta_id == IWL_INVALID_STATION)) return; - if (WARN_ON(tid >= MAX_TID_COUNT)) + if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) return; spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; + tid_data = &priv->shrd->tid_data[sta_id][tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; tx_fifo = tid_data->agg.tx_fifo; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index b95e71389b7c..a18ed425c24c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1193,7 +1193,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, if (txq->sched_retry) { agg_state = - priv->stations[txq->sta_id].tid[txq->tid].agg.state; + priv->shrd->tid_data[txq->sta_id][txq->tid].agg.state; cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); } else { cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); From fd656935cd05f522d7db97386633f6a0d7751218 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:19 -0700 Subject: [PATCH 096/129] iwlagn: remove dereferences of priv from transport There are still quite a few, but much less. A few fields have been moved /copied to hw_params which sits in the shared area: * priv->cfg->base_params->num_of_ampdu_queues * priv->cfg->base_params->shadow_reg_enable * priv->cfg->sku * priv->ucode_owner Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ---- drivers/net/wireless/iwlwifi/iwl-power.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-shared.h | 21 +++++++---- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 3 +- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 15 ++++---- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 35 +++++++++---------- drivers/net/wireless/iwlwifi/iwl-trans.c | 24 ++++++------- 10 files changed, 64 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index bb6605b51956..8edb3f89b22d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -102,12 +102,12 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + hw_params(priv).num_ampdu_queues <= txq_id)) { IWL_WARN(priv, "queue number out of range: %d, must be %d to %d\n", txq_id, IWLAGN_FIRST_AMPDU_QUEUE, IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues - 1); + hw_params(priv).num_ampdu_queues - 1); return -EINVAL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1cf36783c1c3..65a6db5e9a2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3207,6 +3207,13 @@ static int iwl_set_hw_params(struct iwl_priv *priv) if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; + hw_params(priv).num_ampdu_queues = + priv->cfg->base_params->num_of_ampdu_queues; + hw_params(priv).shadow_reg_enable = + priv->cfg->base_params->shadow_reg_enable; + hw_params(priv).sku = + priv->cfg->sku; + /* Device-specific setup */ return priv->cfg->lib->set_hw_params(priv); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6a6aba052782..413340498997 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1056,10 +1056,6 @@ struct iwl_testmode_trace { }; #endif -/* uCode ownership */ -#define IWL_OWNERSHIP_DRIVER 0 -#define IWL_OWNERSHIP_TM 1 - struct iwl_priv { /*data shared among all the driver's layers */ @@ -1147,9 +1143,6 @@ struct iwl_priv { u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ - /* uCode owner: default: IWL_OWNERSHIP_DRIVER */ - u8 ucode_owner; - struct fw_img ucode_rt; struct fw_img ucode_init; struct fw_img ucode_wowlan; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2c91a48b8010..62cd781192b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -215,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - if (priv->cfg->base_params->shadow_reg_enable) + if (hw_params(priv).shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -301,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.bus_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; - if (priv->cfg->base_params->shadow_reg_enable) + if (hw_params(priv).shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index bb61c13d4998..db606a6857c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -133,36 +133,41 @@ struct iwl_mod_params { /** * struct iwl_hw_params * @max_txq_num: Max # Tx queues supported + * @num_ampdu_queues: num of ampdu queues * @tx/rx_chains_num: Number of TX/RX chains * @valid_tx/rx_ant: usable antennas - * @rx_page_order: Rx buffer page order - * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @max_stations: * @ht40_channel: is 40MHz width possible in band 2.4 + * @beacon_time_tsf_bits: number of valid tsf bits for beacon time + * @sku: + * @rx_page_order: Rx buffer page order + * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) * @sw_crypto: 0 for hw, 1 for sw * @max_xxx_size: for ucode uses * @ct_kill_threshold: temperature threshold - * @beacon_time_tsf_bits: number of valid tsf bits for beacon time * @calib_init_cfg: setup initial calibrations for the hw * @calib_rt_cfg: setup runtime calibrations for the hw * @struct iwl_sensitivity_ranges: range of sensitivity values */ struct iwl_hw_params { - u8 max_txq_num; + u8 max_txq_num; + u8 num_ampdu_queues; u8 tx_chains_num; u8 rx_chains_num; u8 valid_tx_ant; u8 valid_rx_ant; - u32 rx_page_order; u8 max_stations; u8 ht40_channel; + bool shadow_reg_enable; + u16 beacon_time_tsf_bits; + u16 sku; + u32 rx_page_order; u32 max_inst_size; u32 max_data_size; u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_exit_threshold; /* value in hw-dependent units */ /* for 1000, 6000 series and up */ - u16 beacon_time_tsf_bits; u32 calib_init_cfg; u32 calib_rt_cfg; const struct iwl_sensitivity_ranges *sens; @@ -201,6 +206,7 @@ struct iwl_tid_data { * * @dbg_level_dev: dbg level set per device. Prevails on * iwlagn_mod_params.debug_level if set (!= 0) + * @ucode_owner: IWL_OWNERSHIP_* * @cmd_queue: command queue number * @status: STATUS_* * @bus: pointer to the bus layer data @@ -217,6 +223,9 @@ struct iwl_shared { u32 dbg_level_dev; #endif /* CONFIG_IWLWIFI_DEBUG */ +#define IWL_OWNERSHIP_DRIVER 0 +#define IWL_OWNERSHIP_TM 1 + u8 ucode_owner; u8 cmd_queue; unsigned long status; bool wowlan; diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index b53d77b131d5..848fc18befc2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -612,7 +612,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) - priv->ucode_owner = owner; + priv->shrd->ucode_owner = owner; else { IWL_DEBUG_INFO(priv, "Invalid owner\n"); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index bd6e64026a06..269d9e3188b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -162,7 +162,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data); /***************************************************** * TX / HCMD ******************************************************/ -void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwl_txq_update_write_ptr(struct iwl_trans *trans, + struct iwl_tx_queue *txq); int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 5cff771af92f..a0699c0ef4f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -130,7 +130,6 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q) void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, struct iwl_rx_queue *q) { - struct iwl_priv *priv = priv(trans); unsigned long flags; u32 reg; @@ -139,34 +138,34 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, if (q->need_update == 0) goto exit_unlock; - if (priv->cfg->base_params->shadow_reg_enable) { + if (hw_params(trans).shadow_reg_enable) { /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write32(bus(priv), FH_RSCSR_CHNL0_WPTR, q->write_actual); + iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { - reg = iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); + reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); - iwl_set_bit(bus(priv), CSR_GP_CNTRL, + iwl_set_bit(bus(trans), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(priv), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(priv), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); } } @@ -1032,7 +1031,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); for (i = 0; i < hw_params(trans).max_txq_num; i++) - iwl_txq_update_write_ptr(priv(trans), + iwl_txq_update_write_ptr(trans, &priv(trans)->txq[i]); isr_stats->wakeup++; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 9f4ffebfa56d..8c18a7545afd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -86,7 +86,7 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, /** * iwl_txq_update_write_ptr - Send new write index to hardware */ -void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) +void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) { u32 reg = 0; int txq_id = txq->q.id; @@ -94,28 +94,28 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - if (priv->cfg->base_params->shadow_reg_enable) { + if (hw_params(trans).shadow_reg_enable) { /* shadow register enabled */ - iwl_write32(bus(priv), HBUS_TARG_WRPTR, + iwl_write32(bus(trans), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); + reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, + IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup," " GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(bus(priv), CSR_GP_CNTRL, + iwl_set_bit(bus(trans), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return; } - iwl_write_direct32(bus(priv), HBUS_TARG_WRPTR, + iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); /* @@ -124,7 +124,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl_write32(bus(priv), HBUS_TARG_WRPTR, + iwl_write32(bus(trans), HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } txq->need_update = 0; @@ -498,12 +498,12 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, struct iwl_trans *trans = trans(priv); if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + hw_params(priv).num_ampdu_queues <= txq_id)) { IWL_ERR(priv, "queue number out of range: %d, must be %d to %d\n", txq_id, IWLAGN_FIRST_AMPDU_QUEUE, IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues - 1); + hw_params(priv).num_ampdu_queues - 1); return -EINVAL; } @@ -536,8 +536,7 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, */ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq = &priv->txq[priv->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &priv(trans)->txq[trans->shrd->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -560,7 +559,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EIO; } - if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && + if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) && !(cmd->flags & CMD_ON_DEMAND)) { IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n"); return -EIO; @@ -607,10 +606,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) spin_unlock_irqrestore(&trans->hcmd_lock, flags); IWL_ERR(trans, "No space in command queue\n"); - is_ct_kill = iwl_check_for_ct_kill(priv); + is_ct_kill = iwl_check_for_ct_kill(priv(trans)); if (!is_ct_kill) { IWL_ERR(trans, "Restarting adapter queue is full\n"); - iwlagn_fw_error(priv, false); + iwlagn_fw_error(priv(trans), false); } return -ENOSPC; } @@ -702,7 +701,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* check that tracing gets all possible blocks */ BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING - trace_iwlwifi_dev_hcmd(priv, cmd->flags, + trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags, trace_bufs[0], trace_lens[0], trace_bufs[1], trace_lens[1], trace_bufs[2], trace_lens[2]); @@ -710,7 +709,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(trans, txq); out: spin_unlock_irqrestore(&trans->hcmd_lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index a18ed425c24c..ac401b805c69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -138,13 +138,12 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) } } -static void iwl_trans_rx_hw_init(struct iwl_priv *priv, +static void iwl_trans_rx_hw_init(struct iwl_trans *trans, struct iwl_rx_queue *rxq) { u32 rb_size; const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - struct iwl_trans *trans = trans(priv); rb_timeout = RX_RB_TIMEOUT; @@ -221,7 +220,7 @@ static int iwl_rx_init(struct iwl_trans *trans) iwlagn_rx_replenish(trans); - iwl_trans_rx_hw_init(priv(trans), rxq); + iwl_trans_rx_hw_init(trans, rxq); spin_lock_irqsave(&trans->shrd->lock, flags); rxq->need_update = 1; @@ -509,7 +508,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 scd_bc_tbls_size = priv->cfg->base_params->num_of_queues * + u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. @@ -534,7 +533,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) } priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * - priv->cfg->base_params->num_of_queues, GFP_KERNEL); + hw_params(trans).max_txq_num, GFP_KERNEL); if (!priv->txq) { IWL_ERR(trans, "Not enough memory for txq\n"); ret = ENOMEM; @@ -652,7 +651,7 @@ static int iwl_nic_init(struct iwl_trans *trans) if (iwl_tx_init(trans)) return -ENOMEM; - if (priv->cfg->base_params->shadow_reg_enable) { + if (hw_params(trans).shadow_reg_enable) { /* enable shadow regs in HW */ iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); @@ -717,9 +716,9 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) int ret; struct iwl_priv *priv = priv(trans); - priv->ucode_owner = IWL_OWNERSHIP_DRIVER; + priv->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; - if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && + if ((hw_params(priv).sku & EEPROM_SKU_CAP_AMT_ENABLE) && iwl_trans_pcie_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; @@ -1131,7 +1130,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(trans(priv), txq); /* * At this point the frame is "transmitted" successfully @@ -1142,7 +1141,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, if (iwl_queue_space(q) < q->high_mark) { if (wait_write_ptr) { txq->need_update = 1; - iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(trans(priv), txq); } else { iwl_stop_queue(priv, txq); } @@ -1366,7 +1365,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, struct iwl_rx_queue *rxq = &trans_pcie->rxq; char *buf; int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; + (hw_params(trans).max_txq_num * 32 * 8) + 400; const u8 *ptr; ssize_t ret; @@ -1468,8 +1467,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, int pos = 0; int cnt; int ret; - const size_t bufsz = sizeof(char) * 64 * - priv->cfg->base_params->num_of_queues; + const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; if (!priv->txq) { IWL_ERR(priv, "txq not ready\n"); From ae2c30bfcd29c6f1215d58a1c5663d58978011b8 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:20 -0700 Subject: [PATCH 097/129] iwlagn: stop the device before freeing it When we remove the module, we free all the tx and rx resources. Before doing that, we'd better stop the tx / rx activity. Calling iwl_trans_stop_device in iwl_remove helps also to remove a few API functions: * rx_free: happens in iwl_trans_free * tx_free: happens in iwl_trans_free * disable_sync_irq: happens in iwl_trans_stop_device Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 ++----- drivers/net/wireless/iwlwifi/iwl-trans.c | 42 +++++++++++------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 23 ------------- 3 files changed, 22 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 65a6db5e9a2d..e19ff11c8dc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3443,20 +3443,13 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->mac80211_registered = 0; } - /* Reset to low power before unloading driver. */ - iwl_apm_stop(priv); - iwl_tt_exit(priv); - /* make sure we flush any pending irq or - * tasklet for the driver */ - iwl_trans_disable_sync_irq(trans(priv)); + /*This will stop the queues, move the device to low power state */ + iwl_trans_stop_device(trans(priv)); iwl_dealloc_ucode(priv); - iwl_trans_rx_free(trans(priv)); - iwl_trans_tx_free(trans(priv)); - iwl_eeprom_free(priv); /*netif_stop_queue(dev); */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ac401b805c69..0a3dd6bfd26a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -555,7 +555,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) return 0; error: - iwl_trans_tx_free(trans); + iwl_trans_pcie_tx_free(trans); return ret; } @@ -603,7 +603,7 @@ static int iwl_tx_init(struct iwl_trans *trans) error: /*Upon error, free only if we allocated something */ if (alloc) - iwl_trans_tx_free(trans); + iwl_trans_pcie_tx_free(trans); return ret; } @@ -958,13 +958,28 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) return 0; } +static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) +{ + unsigned long flags; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans->shrd->lock, flags); + iwl_disable_interrupts(trans); + spin_unlock_irqrestore(&trans->shrd->lock, flags); + + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(bus(trans)->irq); + tasklet_kill(&trans_pcie->irq_tasklet); +} + static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) { /* stop and reset the on-board processor */ iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - iwl_trans_disable_sync_irq(trans); + iwl_trans_pcie_disable_sync_irq(trans); /* device going down, Stop using ICT table */ iwl_disable_ict(trans); @@ -1208,23 +1223,10 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, } } -static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) -{ - unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); - - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(bus(trans)->irq); - tasklet_kill(&trans_pcie->irq_tasklet); -} - static void iwl_trans_pcie_free(struct iwl_trans *trans) { + iwl_trans_pcie_tx_free(trans); + iwl_trans_pcie_rx_free(trans); free_irq(bus(trans)->irq, trans); iwl_free_isr_ict(trans); trans->shrd->trans = NULL; @@ -1860,9 +1862,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx_start = iwl_trans_pcie_tx_start, - .rx_free = iwl_trans_pcie_rx_free, - .tx_free = iwl_trans_pcie_tx_free, - .send_cmd = iwl_trans_pcie_send_cmd, .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, @@ -1875,7 +1874,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .kick_nic = iwl_trans_pcie_kick_nic, - .disable_sync_irq = iwl_trans_pcie_disable_sync_irq, .free = iwl_trans_pcie_free, .dbgfs_register = iwl_trans_pcie_dbgfs_register, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0da6ad593f05..e72e4809a410 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -88,8 +88,6 @@ struct iwl_shared; * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. * @stop_device:stops the whole device (embedded CPU put to reset) - * @rx_free: frees the rx memory - * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use @@ -99,9 +97,6 @@ struct iwl_shared; * ready and a successful ADDBA response has been received. * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run - * @disable_sync_irq: Disable and sync: after this handler returns, it is - * guaranteed that all the ISR / tasklet etc... have finished running - * and the transport layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... * @dbgfs_register: add the dbgfs files under this directory. Files will be @@ -117,8 +112,6 @@ struct iwl_trans_ops { int (*prepare_card_hw)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); void (*tx_start)(struct iwl_trans *trans); - void (*tx_free)(struct iwl_trans *trans); - void (*rx_free)(struct iwl_trans *trans); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); @@ -138,7 +131,6 @@ struct iwl_trans_ops { void (*kick_nic)(struct iwl_trans *trans); - void (*disable_sync_irq)(struct iwl_trans *trans); void (*free)(struct iwl_trans *trans); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); @@ -187,16 +179,6 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) trans->ops->tx_start(trans); } -static inline void iwl_trans_rx_free(struct iwl_trans *trans) -{ - trans->ops->rx_free(trans); -} - -static inline void iwl_trans_tx_free(struct iwl_trans *trans) -{ - trans->ops->tx_free(trans); -} - static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { @@ -247,11 +229,6 @@ static inline void iwl_trans_kick_nic(struct iwl_trans *trans) trans->ops->kick_nic(trans); } -static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) -{ - trans->ops->disable_sync_irq(trans); -} - static inline void iwl_trans_free(struct iwl_trans *trans) { trans->ops->free(trans); From 2c452297ff3eaafad41d24fa03d54a169ced8de1 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:21 -0700 Subject: [PATCH 098/129] iwlagn: upper layer stores iwl_rxon_context in skb's CB This removes the need for iwl_tx_info. Each tx queue holds an array of skbs, the transport layer doesn't need to know anything about the context in which a specific skb is sent. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 4 +++- drivers/net/wireless/iwlwifi/iwl-dev.h | 12 +++------- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 19 +++++---------- drivers/net/wireless/iwlwifi/iwl-trans.c | 23 ++++++++----------- drivers/net/wireless/iwlwifi/iwl-trans.h | 8 +++---- 5 files changed, 25 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 8edb3f89b22d..60ba4f84285a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -454,7 +454,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - if (iwl_trans_tx(trans(priv), skb, tx_cmd, txq_id, fc, is_agg, ctx)) + info->driver_data[0] = ctx; + + if (iwl_trans_tx(trans(priv), skb, tx_cmd, txq_id, fc, is_agg)) goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 413340498997..aa56736aebb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -146,12 +146,6 @@ struct iwl_queue { * space less than this */ }; -/* One for each TFD */ -struct iwl_tx_info { - struct sk_buff *skb; - struct iwl_rxon_context *ctx; -}; - /** * struct iwl_tx_queue - Tx Queue for DMA * @q: generic Rx/Tx queue descriptor @@ -177,7 +171,7 @@ struct iwl_tx_queue { struct iwl_tfd *tfds; struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; - struct iwl_tx_info *txb; + struct sk_buff **skbs; unsigned long time_stamp; u8 need_update; u8 sched_retry; @@ -1373,9 +1367,9 @@ extern struct iwl_mod_params iwlagn_mod_params; static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, int txq_id, int idx) { - if (priv->txq[txq_id].txb[idx].skb) + if (priv->txq[txq_id].skbs[idx]) return (struct ieee80211_hdr *)priv->txq[txq_id]. - txb[idx].skb->data; + skbs[idx]->data; return NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 8c18a7545afd..cc518afd39e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -215,15 +215,15 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, DMA_TO_DEVICE); /* free SKB */ - if (txq->txb) { + if (txq->skbs) { struct sk_buff *skb; - skb = txq->txb[index].skb; + skb = txq->skbs[index]; /* can be called from irqs-disabled context */ if (skb) { dev_kfree_skb_any(skb); - txq->txb[index].skb = NULL; + txq->skbs[index] = NULL; } } } @@ -1056,8 +1056,6 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, { struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; struct iwl_queue *q = &txq->q; - struct iwl_tx_info *tx_info; - struct ieee80211_tx_info *info; int last_to_free; /*Since we free until index _not_ inclusive, the one before index is @@ -1083,17 +1081,12 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, q->read_ptr != index; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - tx_info = &txq->txb[txq->q.read_ptr]; - - if (WARN_ON_ONCE(tx_info->skb == NULL)) + if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL)) continue; - info = IEEE80211_SKB_CB(tx_info->skb); - info->driver_data[0] = tx_info->ctx; + __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]); - __skb_queue_tail(skbs, tx_info->skb); - - tx_info->skb = NULL; + txq->skbs[txq->q.read_ptr] = NULL; iwlagn_txq_inval_byte_cnt_tbl(trans, txq); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 0a3dd6bfd26a..e545898cddb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -304,7 +304,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; int i; - if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) + if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) return -EINVAL; txq->q.n_window = slots_num; @@ -328,15 +328,15 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, /* Driver private data, only for Tx (not command) queues, * not shared with device. */ if (txq_id != trans->shrd->cmd_queue) { - txq->txb = kzalloc(sizeof(txq->txb[0]) * + txq->skbs = kzalloc(sizeof(txq->skbs[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); - if (!txq->txb) { + if (!txq->skbs) { IWL_ERR(trans, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } } else { - txq->txb = NULL; + txq->skbs = NULL; } /* Circular buffer of transmit frame descriptors (TFDs), @@ -351,8 +351,8 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, return 0; error: - kfree(txq->txb); - txq->txb = NULL; + kfree(txq->skbs); + txq->skbs = NULL; /* since txq->cmd has been zeroed, * all non allocated cmd[i] will be NULL */ if (txq->cmd) @@ -453,8 +453,8 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) } /* De-alloc array of per-TFD driver data */ - kfree(txq->txb); - txq->txb = NULL; + kfree(txq->skbs); + txq->skbs = NULL; /* deallocate arrays */ kfree(txq->cmd); @@ -1035,8 +1035,7 @@ static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_trans *trans, } static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, - struct iwl_rxon_context *ctx) + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; @@ -1051,9 +1050,7 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, u8 hdr_len = ieee80211_hdrlen(fc); /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb = skb; - txq->txb[q->write_ptr].ctx = ctx; + txq->skbs[q->write_ptr] = skb; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_meta = &txq->meta[q->write_ptr]; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index e72e4809a410..2385de267bb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -119,8 +119,7 @@ struct iwl_trans_ops { const void *data); struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_trans *trans, int txq_id); int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, - struct iwl_rxon_context *ctx); + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu); void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs); @@ -198,10 +197,9 @@ static inline struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_trans *trans, } static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, - struct iwl_rxon_context *ctx) + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu) { - return trans->ops->tx(priv(trans), skb, tx_cmd, txq_id, fc, ampdu, ctx); + return trans->ops->tx(priv(trans), skb, tx_cmd, txq_id, fc, ampdu); } static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, From ba562f71198a2cb03bb8d20640ffdf996275c3f0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:22 -0700 Subject: [PATCH 099/129] iwlagn: set tx_fifo for ampdu in transport layer the mapping tx_queue -> fifo is really transport related. The upper layer should be involved in such things. Note that upon agg_disable, the queue is always mapped to fifo 0, but this doesn't matter since when the queue will be setup again for a new BA session, it will be configured to the good fifo anyway. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 65 +------------------ drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 7 -- drivers/net/wireless/iwlwifi/iwl-shared.h | 46 ++++++++++++- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 8 +-- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 32 ++++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 22 +++---- 7 files changed, 89 insertions(+), 96 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 60ba4f84285a..9787f0f2a4fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -42,43 +42,6 @@ #include "iwl-agn.h" #include "iwl-trans.h" -/* - * mac80211 queues, ACs, hardware queues, FIFOs. - * - * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues - * - * Mac80211 uses the following numbers, which we get as from it - * by way of skb_get_queue_mapping(skb): - * - * VO 0 - * VI 1 - * BE 2 - * BK 3 - * - * - * Regular (not A-MPDU) frames are put into hardware queues corresponding - * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their - * own queue per aggregation session (RA/TID combination), such queues are - * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In - * order to map frames to the right queue, we also need an AC->hw queue - * mapping. This is implemented here. - * - * Due to the way hw queues are set up (by the hw specific modules like - * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity - * mapping. - */ - -static const u8 tid_to_ac[] = { - IEEE80211_AC_BE, - IEEE80211_AC_BK, - IEEE80211_AC_BK, - IEEE80211_AC_BE, - IEEE80211_AC_VI, - IEEE80211_AC_VI, - IEEE80211_AC_VO, - IEEE80211_AC_VO -}; - static inline int get_ac_from_tid(u16 tid) { if (likely(tid < ARRAY_SIZE(tid_to_ac))) @@ -88,15 +51,6 @@ static inline int get_ac_from_tid(u16 tid) return -EINVAL; } -static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return ctx->ac_to_fifo[tid_to_ac[tid]]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) { @@ -508,16 +462,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { int sta_id; - int tx_fifo; int txq_id; int ret; unsigned long flags; struct iwl_tid_data *tid_data; - tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); - if (unlikely(tx_fifo < 0)) - return tx_fifo; - IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", sta->addr, tid); @@ -544,7 +493,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data = &priv->shrd->tid_data[sta_id][tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - tid_data->agg.tx_fifo = tx_fifo; iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); @@ -570,15 +518,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - int tx_fifo_id, txq_id, sta_id, ssn; + int txq_id, sta_id, ssn; struct iwl_tid_data *tid_data; int write_ptr, read_ptr; unsigned long flags; - tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); - if (unlikely(tx_fifo_id < 0)) - return tx_fifo_id; - sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { @@ -635,7 +579,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - iwl_trans_txq_agg_disable(trans(priv), txq_id, ssn, tx_fifo_id); + iwl_trans_txq_agg_disable(trans(priv), txq_id); spin_unlock_irqrestore(&priv->shrd->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -661,11 +605,8 @@ static int iwlagn_txq_check_empty(struct iwl_priv *priv, /* aggregated HW queue */ if ((txq_id == tid_data->agg.txq_id) && (q->read_ptr == q->write_ptr)) { - u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - iwl_trans_txq_agg_disable(trans(priv), txq_id, - ssn, tx_fifo); + iwl_trans_txq_agg_disable(trans(priv), txq_id); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e19ff11c8dc8..d3e103c1b1c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2534,6 +2534,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; int ret = -EINVAL; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; + struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); @@ -2587,8 +2588,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwl_trans_txq_agg_setup(trans(priv), iwl_sta_id(sta), tid, - buf_size); + iwl_trans_txq_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), + tid, buf_size); /* * If the limit is 0, then it wasn't initialised yet, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index aa56736aebb3..5e79c140ac1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -961,13 +961,6 @@ struct iwl_notification_wait { bool triggered, aborted; }; -enum iwl_rxon_context_id { - IWL_RXON_CTX_BSS, - IWL_RXON_CTX_PAN, - - NUM_IWL_RXON_CTX -}; - struct iwl_rxon_context { struct ieee80211_vif *vif; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index db606a6857c2..4cfa31e2529d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -67,6 +67,7 @@ #include #include #include +#include #include "iwl-commands.h" @@ -192,7 +193,6 @@ struct iwl_ht_agg { #define IWL_EMPTYING_HW_QUEUE_ADDBA 2 #define IWL_EMPTYING_HW_QUEUE_DELBA 3 u8 state; - u8 tx_fifo; }; struct iwl_tid_data { @@ -284,6 +284,50 @@ struct iwl_rx_mem_buffer { #define rxb_addr(r) page_address(r->page) +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific modules like + * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity + * mapping. + */ + +static const u8 tid_to_ac[] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO +}; + +enum iwl_rxon_context_id { + IWL_RXON_CTX_BSS, + IWL_RXON_CTX_PAN, + + NUM_IWL_RXON_CTX +}; + #ifdef CONFIG_PM int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 269d9e3188b3..f443c106291a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -175,14 +175,14 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt); -int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); +int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id); void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, - int frame_limit); +void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, + int sta_id, int tid, int frame_limit); void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index); void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index cc518afd39e6..96ad0afd185e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -424,8 +424,18 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, - int frame_limit) +static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return ctx->ac_to_fifo[tid_to_ac[tid]]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + +void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, int sta_id, + int tid, int frame_limit) { int tx_fifo, txq_id, ssn_idx; u16 ra_tid; @@ -441,11 +451,16 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) return; + tx_fifo = get_fifo_from_tid(&priv->contexts[ctx], tid); + if (WARN_ON(tx_fifo < 0)) { + IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); + return; + } + spin_lock_irqsave(&priv->shrd->sta_lock, flags); tid_data = &priv->shrd->tid_data[sta_id][tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; - tx_fifo = tid_data->agg.tx_fifo; spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); ra_tid = BUILD_RAxTID(sta_id, tid); @@ -492,8 +507,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, spin_unlock_irqrestore(&priv->shrd->lock, flags); } -int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) +int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id) { struct iwl_trans *trans = trans(priv); if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || @@ -511,14 +525,14 @@ int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwl_clear_bits_prph(bus(priv), SCD_AGGR_SEL, (1 << txq_id)); - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.read_ptr = 0; + priv->txq[txq_id].q.write_ptr = 0; /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); + iwl_trans_set_wr_ptrs(trans, txq_id, 0); iwl_clear_bits_prph(bus(priv), SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv, txq_id); - iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], 0, 0); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 2385de267bb7..011c82444566 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -123,10 +123,10 @@ struct iwl_trans_ops { void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs); - int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); - void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, - int frame_limit); + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id); + void (*txq_agg_setup)(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, int sta_id, + int tid, int frame_limit); void (*kick_nic)(struct iwl_trans *trans); @@ -209,17 +209,17 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, trans->ops->reclaim(trans, txq_id, ssn, status, skbs); } -static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) +static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id) { - return trans->ops->txq_agg_disable(priv(trans), txq_id, - ssn_idx, tx_fifo); + return trans->ops->txq_agg_disable(priv(trans), txq_id); } -static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, - int tid, int frame_limit) +static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, + int sta_id, int tid, + int frame_limit) { - trans->ops->txq_agg_setup(priv(trans), sta_id, tid, frame_limit); + trans->ops->txq_agg_setup(priv(trans), ctx, sta_id, tid, frame_limit); } static inline void iwl_trans_kick_nic(struct iwl_trans *trans) From dfa2bdbab70901ddda3ec41f2e55f8396af9095f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:23 -0700 Subject: [PATCH 100/129] iwlagn: upper layer uses slabs to allocate tx cmds In a near future, the upper layer won't be aware of the tx queues. This allows to remove one place where the upper layer needed to provide the tx queue index to the transport layer. This also saves around 1.5MB. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 19 +++++-- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 9 ++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 2 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-trans.c | 57 +++++++------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 17 +++--- 6 files changed, 55 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 9787f0f2a4fd..b02125a6a437 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -276,6 +276,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_station_priv *sta_priv = NULL; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwl_device_cmd *dev_cmd = NULL; struct iwl_tx_cmd *tx_cmd; int txq_id; @@ -386,10 +387,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } } - tx_cmd = iwl_trans_get_tx_cmd(trans(priv), txq_id); - if (unlikely(!tx_cmd)) + dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); + + if (unlikely(!dev_cmd)) goto drop_unlock_sta; + memset(dev_cmd, 0, sizeof(*dev_cmd)); + tx_cmd = &dev_cmd->cmd.tx; + /* Copy MAC header from skb into command buffer */ memcpy(tx_cmd->hdr, hdr, hdr_len); @@ -409,8 +414,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); info->driver_data[0] = ctx; + info->driver_data[1] = dev_cmd; - if (iwl_trans_tx(trans(priv), skb, tx_cmd, txq_id, fc, is_agg)) + if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id, fc, is_agg)) goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { @@ -436,6 +442,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) return 0; drop_unlock_sta: + if (dev_cmd) + kmem_cache_free(priv->tx_cmd_pool, dev_cmd); spin_unlock(&priv->shrd->sta_lock); drop_unlock_priv: spin_unlock_irqrestore(&priv->shrd->lock, flags); @@ -1010,6 +1018,8 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) info = IEEE80211_SKB_CB(skb); ctx = info->driver_data[0]; + kmem_cache_free(priv->tx_cmd_pool, + (info->driver_data[1])); memset(&info->status, 0, sizeof(info->status)); @@ -1184,6 +1194,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, info); } + info = IEEE80211_SKB_CB(skb); + kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); + ieee80211_tx_status_irqsafe(priv->hw, skb); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 02b00d177323..ddb255a575df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -351,6 +351,15 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) { int ret; + if (!priv->tx_cmd_pool) + priv->tx_cmd_pool = + kmem_cache_create("iwlagn_dev_cmd", + sizeof(struct iwl_device_cmd), + sizeof(void *), 0, NULL); + + if (!priv->tx_cmd_pool) + return -ENOMEM; + iwl_trans_tx_start(trans(priv)); ret = iwlagn_send_wimax_coex(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d3e103c1b1c7..cfb4a4ae52ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3124,6 +3124,8 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwl_calib_free_results(priv); iwl_free_geos(priv); iwl_free_channel_map(priv); + if (priv->tx_cmd_pool) + kmem_cache_destroy(priv->tx_cmd_pool); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5e79c140ac1a..977015b47c64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "iwl-eeprom.h" @@ -1053,6 +1054,7 @@ struct iwl_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; + struct kmem_cache *tx_cmd_pool; struct iwl_cfg *cfg; enum ieee80211_band band; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index e545898cddb3..7de042c6c258 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -317,12 +317,13 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, if (!txq->meta || !txq->cmd) goto error; - for (i = 0; i < slots_num; i++) { - txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), - GFP_KERNEL); - if (!txq->cmd[i]) - goto error; - } + if (txq_id == trans->shrd->cmd_queue) + for (i = 0; i < slots_num; i++) { + txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), + GFP_KERNEL); + if (!txq->cmd[i]) + goto error; + } /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, @@ -355,7 +356,7 @@ error: txq->skbs = NULL; /* since txq->cmd has been zeroed, * all non allocated cmd[i] will be NULL */ - if (txq->cmd) + if (txq->cmd && txq_id == trans->shrd->cmd_queue) for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); kfree(txq->meta); @@ -442,8 +443,10 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) iwl_tx_queue_unmap(trans, txq_id); /* De-alloc array of command/tx buffers */ - for (i = 0; i < txq->q.n_window; i++) - kfree(txq->cmd[i]); + + if (txq_id == trans->shrd->cmd_queue) + for (i = 0; i < txq->q.n_window; i++) + kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { @@ -1009,37 +1012,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) iwl_apm_stop(priv(trans)); } -static struct iwl_tx_cmd *iwl_trans_pcie_get_tx_cmd(struct iwl_trans *trans, - int txq_id) -{ - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct iwl_device_cmd *dev_cmd; - - if (unlikely(iwl_queue_space(q) < q->high_mark)) - return NULL; - - /* - * Set up the Tx-command (not MAC!) header. - * Store the chosen Tx queue and TFD index within the sequence field; - * after Tx, uCode's Tx response will return this value so driver can - * locate the frame within the tx queue and do post-tx processing. - */ - dev_cmd = txq->cmd[q->write_ptr]; - memset(dev_cmd, 0, sizeof(*dev_cmd)); - dev_cmd->hdr.cmd = REPLY_TX; - dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - return &dev_cmd->cmd.tx; -} - static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu) + struct iwl_device_cmd *dev_cmd, int txq_id, + __le16 fc, bool ampdu) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; - struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr]; + struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; struct iwl_cmd_meta *out_meta; dma_addr_t phys_addr = 0; @@ -1051,6 +1030,11 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Set up driver data for this TFD */ txq->skbs[q->write_ptr] = skb; + txq->cmd[q->write_ptr] = dev_cmd; + + dev_cmd->hdr.cmd = REPLY_TX; + dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_meta = &txq->meta[q->write_ptr]; @@ -1862,7 +1846,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .send_cmd = iwl_trans_pcie_send_cmd, .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, - .get_tx_cmd = iwl_trans_pcie_get_tx_cmd, .tx = iwl_trans_pcie_tx, .reclaim = iwl_trans_pcie_reclaim, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 011c82444566..0691d39bce05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -76,6 +76,7 @@ struct iwl_priv; struct iwl_rxon_context; struct iwl_host_cmd; struct iwl_shared; +struct iwl_device_cmd; /** * struct iwl_trans_ops - transport specific operations @@ -90,7 +91,6 @@ struct iwl_shared; * @stop_device:stops the whole device (embedded CPU put to reset) * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* - * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb * @reclaim: free packet until ssn. Returns a list of freed packets. * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is @@ -117,9 +117,9 @@ struct iwl_trans_ops { int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data); - struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_trans *trans, int txq_id); int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu); + struct iwl_device_cmd *dev_cmd, + int txq_id, __le16 fc, bool ampdu); void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs); @@ -190,16 +190,11 @@ static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, return trans->ops->send_cmd_pdu(trans, id, flags, len, data); } -static inline struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_trans *trans, - int txq_id) -{ - return trans->ops->get_tx_cmd(trans, txq_id); -} - static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu) + struct iwl_device_cmd *dev_cmd, + int txq_id, __le16 fc, bool ampdu) { - return trans->ops->tx(priv(trans), skb, tx_cmd, txq_id, fc, ampdu); + return trans->ops->tx(priv(trans), skb, dev_cmd, txq_id, fc, ampdu); } static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, From e13c0c59e0ec38558ac853d56555e915b4dc7dc2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:24 -0700 Subject: [PATCH 101/129] iwlagn: move the mapping ac to queue / fifo to transport This mapping is transport related. This allows us to remove the notion of tx queue from the tx path in the upper layer. iwl_wake_any_queue moved to transport layer since it needs to access these mappings. The TX API is nicer now: int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 53 +---- drivers/net/wireless/iwlwifi/iwl-agn.c | 23 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 11 - drivers/net/wireless/iwlwifi/iwl-helpers.h | 13 - drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 14 ++ .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 8 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 223 +++++++++++++----- drivers/net/wireless/iwlwifi/iwl-trans.h | 19 +- 10 files changed, 201 insertions(+), 168 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 7ce56ff4a525..b4d7460f05ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -835,7 +835,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, */ if (ctx->last_tx_rejected) { ctx->last_tx_rejected = false; - iwl_wake_any_queue(priv, ctx); + iwl_trans_wake_any_queue(trans(priv), + ctx->ctxid); } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index b02125a6a437..32e39059b9bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -278,14 +278,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_device_cmd *dev_cmd = NULL; struct iwl_tx_cmd *tx_cmd; - int txq_id; - u16 seq_number = 0; __le16 fc; u8 hdr_len; u16 len; u8 sta_id; - u8 tid = 0; unsigned long flags; bool is_agg = false; @@ -343,50 +340,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - /* - * Send this frame after DTIM -- there's a special queue - * reserved for this for contexts that support AP mode. - */ - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - txq_id = ctx->mcast_queue; - /* - * The microcode will clear the more data - * bit in the last frame it transmits. - */ - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) - txq_id = IWL_AUX_QUEUE; - else - txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; - /* irqs already disabled/saved above when locking priv->shrd->lock */ spin_lock(&priv->shrd->sta_lock); - if (ieee80211_is_data_qos(fc)) { - u8 *qc = NULL; - struct iwl_tid_data *tid_data; - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - tid_data = &priv->shrd->tid_data[sta_id][tid]; - - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) - goto drop_unlock_sta; - - seq_number = tid_data->seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); - seq_number += 0x10; - /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - tid_data->agg.state == IWL_AGG_ON) { - txq_id = tid_data->agg.txq_id; - is_agg = true; - } - } - dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); if (unlikely(!dev_cmd)) @@ -416,16 +372,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) info->driver_data[0] = ctx; info->driver_data[1] = dev_cmd; - if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id, fc, is_agg)) + if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id)) goto drop_unlock_sta; - if (ieee80211_is_data_qos(fc)) { - priv->shrd->tid_data[sta_id][tid].tfds_in_queue++; - if (!ieee80211_has_morefrags(fc)) - priv->shrd->tid_data[sta_id][tid].seq_number = - seq_number; - } - spin_unlock(&priv->shrd->sta_lock); spin_unlock_irqrestore(&priv->shrd->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cfb4a4ae52ce..60b964bd5cf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -617,24 +617,6 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) { - static const u8 iwlagn_bss_ac_to_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, - }; - static const u8 iwlagn_bss_ac_to_queue[] = { - 0, 1, 2, 3, - }; - static const u8 iwlagn_pan_ac_to_fifo[] = { - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_BK_IPAN, - }; - static const u8 iwlagn_pan_ac_to_queue[] = { - 7, 6, 5, 4, - }; int i; /* @@ -656,8 +638,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; - priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; - priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = @@ -677,9 +657,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; - priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; - priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; - priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; priv->contexts[IWL_RXON_CTX_PAN].interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 977015b47c64..2e75429f5ac6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -244,13 +244,6 @@ struct iwl_channel_info { #define IWL_DEFAULT_CMD_QUEUE_NUM 4 #define IWL_IPAN_CMD_QUEUE_NUM 9 -/* - * This queue number is required for proper operation - * because the ucode will stop/start the scheduler as - * required. - */ -#define IWL_IPAN_MCAST_QUEUE 8 - #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) @@ -965,10 +958,6 @@ struct iwl_notification_wait { struct iwl_rxon_context { struct ieee80211_vif *vif; - const u8 *ac_to_fifo; - const u8 *ac_to_queue; - u8 mcast_queue; - /* * We could use the vif to indicate active, but we * also need it to be active during disabling when diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 8ca624d2a8b0..7f92d14083ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -113,19 +113,6 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, ieee80211_stop_queue(priv->hw, ac); } -static inline void iwl_wake_any_queue(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - u8 ac; - - for (ac = 0; ac < AC_NUM; ac++) { - IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", - ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) - ? "stopped" : "awake"); - iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); - } -} - #ifdef ieee80211_stop_queue #undef ieee80211_stop_queue #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 2c6659c82f92..8572548dd4a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -699,7 +699,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, ctx->active.bssid_addr)) continue; ctx->last_tx_rejected = false; - iwl_wake_any_queue(priv, ctx); + iwl_trans_wake_any_queue(trans(priv), ctx->ctxid); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index f443c106291a..d73ebefa7d05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -107,6 +107,13 @@ struct iwl_dma_ptr { size_t size; }; +/* + * This queue number is required for proper operation + * because the ucode will stop/start the scheduler as + * required. + */ +#define IWL_IPAN_MCAST_QUEUE 8 + /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data @@ -115,6 +122,9 @@ struct iwl_dma_ptr { * @scd_base_addr: scheduler sram base address in SRAM * @scd_bc_tbls: pointer to the byte count table of the scheduler * @kw: keep warm address + * @ac_to_fifo: to what fifo is a specifc AC mapped ? + * @ac_to_queue: to what tx queue is a specifc AC mapped ? + * @mcast_queue: */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -136,6 +146,10 @@ struct iwl_trans_pcie { u32 scd_base_addr; struct iwl_dma_ptr scd_bc_tbls; struct iwl_dma_ptr kw; + + const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; + const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; + u8 mcast_queue[NUM_IWL_RXON_CTX]; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 96ad0afd185e..6af33104228a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -424,10 +424,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) +static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, + u8 ctx, u16 tid) { + const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx]; if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return ctx->ac_to_fifo[tid_to_ac[tid]]; + return ac_to_fifo[tid_to_ac[tid]]; /* no support for TIDs 8-15 yet */ return -EINVAL; @@ -451,7 +453,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) return; - tx_fifo = get_fifo_from_tid(&priv->contexts[ctx], tid); + tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid); if (WARN_ON(tx_fifo < 0)) { IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 7de042c6c258..133b227cb64d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -714,12 +714,75 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) return ret; } +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, +}; + +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, +}; + +static const u8 iwlagn_bss_ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, +}; +static const u8 iwlagn_bss_ac_to_queue[] = { + 0, 1, 2, 3, +}; +static const u8 iwlagn_pan_ac_to_fifo[] = { + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_BK_IPAN, +}; +static const u8 iwlagn_pan_ac_to_queue[] = { + 7, 6, 5, 4, +}; + static int iwl_trans_pcie_start_device(struct iwl_trans *trans) { int ret; struct iwl_priv *priv = priv(trans); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); priv->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; + trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; + trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; + + trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; + trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; + + trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; + trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; if ((hw_params(priv).sku & EEPROM_SKU_CAP_AMT_ENABLE) && iwl_trans_pcie_prepare_card_hw(trans)) { @@ -773,39 +836,6 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) iwl_write_prph(bus(trans), SCD_TXFACT, mask); } -#define IWL_AC_UNSET -1 - -struct queue_to_fifo_ac { - s8 fifo, ac; -}; - -static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, -}; - -static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_BE_IPAN, 2, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, -}; static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) { const struct queue_to_fifo_ac *queue_to_fifo; @@ -1012,22 +1042,75 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) iwl_apm_stop(priv(trans)); } -static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, int txq_id, - __le16 fc, bool ampdu) +static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) { - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; struct iwl_cmd_meta *out_meta; + struct iwl_tx_queue *txq; + struct iwl_queue *q; dma_addr_t phys_addr = 0; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; u16 len, firstlen, secondlen; + u16 seq_number = 0; u8 wait_write_ptr = 0; + u8 txq_id; + u8 tid = 0; + bool is_agg = false; + __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); + /* + * Send this frame after DTIM -- there's a special queue + * reserved for this for contexts that support AP mode. + */ + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + txq_id = trans_pcie->mcast_queue[ctx]; + + /* + * The microcode will clear the more data + * bit in the last frame it transmits. + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) + txq_id = IWL_AUX_QUEUE; + else + txq_id = + trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; + + if (ieee80211_is_data_qos(fc)) { + u8 *qc = NULL; + struct iwl_tid_data *tid_data; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + tid_data = &trans->shrd->tid_data[sta_id][tid]; + + if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) + return -1; + + seq_number = tid_data->seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number += 0x10; + /* aggregation is on for this */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + tid_data->agg.state == IWL_AGG_ON) { + txq_id = tid_data->agg.txq_id; + is_agg = true; + } + } + + txq = &priv(trans)->txq[txq_id]; + q = &txq->q; + /* Set up driver data for this TFD */ txq->skbs[q->write_ptr] = skb; txq->cmd[q->write_ptr] = dev_cmd; @@ -1058,10 +1141,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = dma_map_single(priv->bus->dev, + txcmd_phys = dma_map_single(bus(trans)->dev, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) + if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) return -1; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1077,10 +1160,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, * if any (802.11 null frames have no payload). */ secondlen = skb->len - hdr_len; if (secondlen > 0) { - phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, + phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { - dma_unmap_single(priv->bus->dev, + if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { + dma_unmap_single(bus(trans)->dev, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); @@ -1089,36 +1172,35 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, } /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, txcmd_phys, - firstlen, 1); + iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); if (secondlen > 0) - iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, + dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", + IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", le16_to_cpu(dev_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); /* Set up entry for this TFD in Tx byte-count array */ - if (ampdu) - iwl_trans_txq_update_byte_cnt_tbl(trans(priv), txq, + if (is_agg) + iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); - dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, + dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); - trace_iwlwifi_dev_tx(priv, + trace_iwlwifi_dev_tx(priv(trans), &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], sizeof(struct iwl_tfd), &dev_cmd->hdr, firstlen, @@ -1126,7 +1208,14 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(trans(priv), txq); + iwl_txq_update_write_ptr(trans, txq); + + if (ieee80211_is_data_qos(fc)) { + trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; + if (!ieee80211_has_morefrags(fc)) + trans->shrd->tid_data[sta_id][tid].seq_number = + seq_number; + } /* * At this point the frame is "transmitted" successfully @@ -1137,9 +1226,9 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, if (iwl_queue_space(q) < q->high_mark) { if (wait_write_ptr) { txq->need_update = 1; - iwl_txq_update_write_ptr(trans(priv), txq); + iwl_txq_update_write_ptr(trans, txq); } else { - iwl_stop_queue(priv, txq); + iwl_stop_queue(priv(trans), txq); } } return 0; @@ -1262,6 +1351,23 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) #endif /* CONFIG_PM */ +static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, + u8 ctx) +{ + u8 ac, txq_id; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + for (ac = 0; ac < AC_NUM; ac++) { + txq_id = trans_pcie->ac_to_queue[ctx][ac]; + IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", + ac, + (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0) + ? "stopped" : "awake"); + iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); + } +} + const struct iwl_trans_ops trans_ops_pcie; static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) @@ -1842,6 +1948,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .stop_device = iwl_trans_pcie_stop_device, .tx_start = iwl_trans_pcie_tx_start, + .wake_any_queue = iwl_trans_pcie_wake_any_queue, .send_cmd = iwl_trans_pcie_send_cmd, .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0691d39bce05..0fee8840c0aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -88,6 +88,7 @@ struct iwl_device_cmd; * probe. * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. + * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* @@ -113,13 +114,14 @@ struct iwl_trans_ops { void (*stop_device)(struct iwl_trans *trans); void (*tx_start)(struct iwl_trans *trans); + void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx); + int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data); - int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, - int txq_id, __le16 fc, bool ampdu); + int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs); @@ -178,6 +180,12 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) trans->ops->tx_start(trans); } +static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx) +{ + trans->ops->wake_any_queue(trans, ctx); +} + + static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { @@ -191,10 +199,9 @@ static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, } static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, - int txq_id, __le16 fc, bool ampdu) + struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) { - return trans->ops->tx(priv(trans), skb, dev_cmd, txq_id, fc, ampdu); + return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); } static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, From 288712a6ccf47b9df104f800616f6659ecadc940 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:25 -0700 Subject: [PATCH 102/129] iwlagn: allocate resources for TX BA session in transport The queues and all the related logic suits to the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 77 ++----------------- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++ drivers/net/wireless/iwlwifi/iwl-shared.h | 12 +++ .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 3 + .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 53 ++++++++++++- drivers/net/wireless/iwlwifi/iwl-trans.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 12 +++ 7 files changed, 93 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 32e39059b9bf..e91a0ee1189b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -42,33 +42,6 @@ #include "iwl-agn.h" #include "iwl-trans.h" -static inline int get_ac_from_tid(u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return tid_to_ac[tid]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, - int tid) -{ - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(priv).num_ampdu_queues <= txq_id)) { - IWL_WARN(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWLAGN_FIRST_AMPDU_QUEUE, - IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(priv).num_ampdu_queues - 1); - return -EINVAL; - } - - /* Modify device's station table to Tx this TID */ - return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); -} - static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) @@ -399,30 +372,12 @@ drop_unlock_priv: return -1; } -/* - * Find first available (lowest unused) Tx Queue, mark it "active". - * Called only when finding queue for aggregation. - * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) - */ -static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) -{ - int txq_id; - - for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++) - if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) - return txq_id; - return -1; -} - int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int sta_id; - int txq_id; int ret; - unsigned long flags; - struct iwl_tid_data *tid_data; IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", sta->addr, tid); @@ -440,35 +395,13 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - txq_id = iwlagn_txq_ctx_activate_free(priv); - if (txq_id == -1) { - IWL_ERR(priv, "No free aggregation queue available\n"); - return -ENXIO; - } - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->shrd->tid_data[sta_id][tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; - iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - - ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); + ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); if (ret) return ret; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->shrd->tid_data[sta_id][tid]; - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); - } else { - IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", - tid_data->tfds_in_queue); - tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; - } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id, + tid, ssn); + return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 411edc8f3f9d..38a3c3187ea3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1858,3 +1858,11 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, return cpu_to_le32(res); } +void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, + u8 sta_id, u8 tid) +{ + struct ieee80211_vif *vif = priv->contexts[ctx].vif; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + + ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 4cfa31e2529d..a2be28a925ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -321,6 +321,15 @@ static const u8 tid_to_ac[] = { IEEE80211_AC_VO }; +static inline int get_ac_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return tid_to_ac[tid]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + enum iwl_rxon_context_id { IWL_RXON_CTX_BSS, IWL_RXON_CTX_PAN, @@ -337,6 +346,9 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); +void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, + u8 sta_id, u8 tid); + /***************************************************** * DRIVER STATUS FUNCTIONS ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index d73ebefa7d05..ece9408262b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -194,6 +194,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); +int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid, u16 *ssn); void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, enum iwl_rxon_context_id ctx, int sta_id, int tid, int frame_limit); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 6af33104228a..93922265feb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -29,7 +29,6 @@ #include #include #include -#include #include "iwl-agn.h" #include "iwl-dev.h" @@ -509,6 +508,58 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->shrd->lock, flags); } +/* + * Find first available (lowest unused) Tx Queue, mark it "active". + * Called only when finding queue for aggregation. + * Should never return anything < 7, because they should already + * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) + */ +static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) +{ + int txq_id; + + for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) + if (!test_and_set_bit(txq_id, + &priv(trans)->txq_ctx_active_msk)) + return txq_id; + return -1; +} + +int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid, u16 *ssn) +{ + struct iwl_tid_data *tid_data; + unsigned long flags; + u16 txq_id; + struct iwl_priv *priv = priv(trans); + + txq_id = iwlagn_txq_ctx_activate_free(trans); + if (txq_id == -1) { + IWL_ERR(trans, "No free aggregation queue available\n"); + return -ENXIO; + } + + spin_lock_irqsave(&trans->shrd->sta_lock, flags); + tid_data = &trans->shrd->tid_data[sta_id][tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.txq_id = txq_id; + iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); + + tid_data = &trans->shrd->tid_data[sta_id][tid]; + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(trans, "HW queue is empty\n"); + tid_data->agg.state = IWL_AGG_ON; + iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); + } else { + IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW" + "queue\n", tid_data->tfds_in_queue); + tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; + } + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + + return 0; +} int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id) { struct iwl_trans *trans = trans(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 133b227cb64d..13e8fdc4c012 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1957,6 +1957,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .reclaim = iwl_trans_pcie_reclaim, .txq_agg_disable = iwl_trans_pcie_txq_agg_disable, + .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, .txq_agg_setup = iwl_trans_pcie_txq_agg_setup, .kick_nic = iwl_trans_pcie_kick_nic, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0fee8840c0aa..8aaab087ba54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -94,6 +94,7 @@ struct iwl_device_cmd; * @send_cmd_pdu:send a host command: flags can be CMD_* * @tx: send an skb * @reclaim: free packet until ssn. Returns a list of freed packets. + * @tx_agg_alloc: allocate resources for a TX BA session * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. * @txq_agg_disable: de-configure a Tx queue to send AMPDUs @@ -126,6 +127,9 @@ struct iwl_trans_ops { u32 status, struct sk_buff_head *skbs); int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id); + int (*tx_agg_alloc)(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, int tid, + u16 *ssn); void (*txq_agg_setup)(struct iwl_priv *priv, enum iwl_rxon_context_id ctx, int sta_id, int tid, int frame_limit); @@ -216,6 +220,14 @@ static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id) return trans->ops->txq_agg_disable(priv(trans), txq_id); } +static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, + int sta_id, int tid, u16 *ssn) +{ + return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn); +} + + static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, From 464021ffc1c080283e67729d966d76612728a08c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:26 -0700 Subject: [PATCH 103/129] iwlagn: move the check_empty logic to the transport layer This logic is responsible to tell mac80211 when the HW queues are empty and the BA session can be started / torn down. Fix a bug on the way: When the the Tx BA session is stopped and the HW queues aren't empty, we stop the SW queue to drain the HW queue and then switch to the legacy HW queue. This is the IWL_EMPTYING_HW_QUEUE_DELBA state. While in this state, we never wake the SW queue, even when the HW queue is almost empty, since we need to drain it completely. Look at iwl_trans_pcie_reclaim regarding this. Once the HW queue is really empty, we must wake the SW queue in order to get traffic to the legacy queue. This step was missing leading to an odd situation were the traffic would just stall after we tore down a Tx BA session while the HW queue was not empty. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 65 +---------------- drivers/net/wireless/iwlwifi/iwl-core.c | 21 +++++- drivers/net/wireless/iwlwifi/iwl-shared.h | 6 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 4 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 11 ++- drivers/net/wireless/iwlwifi/iwl-trans.c | 73 +++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 11 +-- 7 files changed, 110 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index e91a0ee1189b..45eb45af5953 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -477,43 +477,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return 0; } -static int iwlagn_txq_check_empty(struct iwl_priv *priv, - int sta_id, u8 tid, int txq_id) -{ - struct iwl_queue *q = &priv->txq[txq_id].q; - u8 *addr = priv->stations[sta_id].sta.sta.addr; - struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid]; - struct iwl_rxon_context *ctx; - - ctx = &priv->contexts[priv->stations[sta_id].ctxid]; - - lockdep_assert_held(&priv->shrd->sta_lock); - - switch (priv->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_DELBA: - /* We are reclaiming the last packet of the */ - /* aggregated HW queue */ - if ((txq_id == tid_data->agg.txq_id) && - (q->read_ptr == q->write_ptr)) { - IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - iwl_trans_txq_agg_disable(trans(priv), txq_id); - tid_data->agg.state = IWL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); - } - break; - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* We are reclaiming the last packet of the queue */ - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); - } - break; - } - - return 0; -} - static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr1) @@ -724,21 +687,6 @@ static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) tx_resp->frame_count) & MAX_SN; } -static void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed) -{ - lockdep_assert_held(&priv->shrd->sta_lock); - - if (priv->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) - priv->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->shrd->tid_data[sta_id][tid].tfds_in_queue, - freed); - priv->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; - } -} - static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) { status &= TX_STATUS_MSK; @@ -889,7 +837,8 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) __skb_queue_head_init(&skbs); /*we can free until ssn % q.n_bd not inclusive */ - iwl_trans_reclaim(trans(priv), txq_id, ssn, status, &skbs); + iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, + ssn, status, &skbs); freed = 0; while (!skb_queue_empty(&skbs)) { skb = __skb_dequeue(&skbs); @@ -939,9 +888,6 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } WARN_ON(!is_agg && freed != 1); - - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); } iwl_check_abort_status(priv, tx_resp->frame_count, status); @@ -1050,8 +996,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, /* Release all TFDs before the SSN, i.e. all TFDs in front of * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ - iwl_trans_reclaim(trans(priv), scd_flow, ba_resp_scd_ssn, 0, - &reclaimed_skbs); + iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn, + 0, &reclaimed_skbs); freed = 0; while (!skb_queue_empty(&reclaimed_skbs)) { @@ -1082,8 +1028,5 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, ieee80211_tx_status_irqsafe(priv->hw, skb); } - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 38a3c3187ea3..c6f8e682d03c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1858,11 +1858,30 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, return cpu_to_le32(res); } -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, +void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, u8 sta_id, u8 tid) { struct ieee80211_vif *vif = priv->contexts[ctx].vif; u8 *addr = priv->stations[sta_id].sta.sta.addr; + if (ctx == NUM_IWL_RXON_CTX) + ctx = priv->stations[sta_id].ctxid; + vif = priv->contexts[ctx].vif; + ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); } + +void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, + u8 sta_id, u8 tid) +{ + struct ieee80211_vif *vif; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + + if (ctx == NUM_IWL_RXON_CTX) + ctx = priv->stations[sta_id].ctxid; + vif = priv->contexts[ctx].vif; + + ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a2be28a925ee..0bd6f7d54433 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -346,8 +346,12 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, +void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, u8 sta_id, u8 tid); +void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, + enum iwl_rxon_context_id ctx, + u8 sta_id, u8 tid); /***************************************************** * DRIVER STATUS FUNCTIONS diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index ece9408262b1..ba82c8bca242 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -202,8 +202,8 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int frame_limit); void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index); -void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs); +int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs); /***************************************************** * Error handling diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 93922265feb3..da8d79eb4dc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -1118,12 +1118,13 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, } /* Frees buffers until index _not_ inclusive */ -void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs) +int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs) { struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; struct iwl_queue *q = &txq->q; int last_to_free; + int freed = 0; /*Since we free until index _not_ inclusive, the one before index is * the last we will free. This one must be used */ @@ -1135,14 +1136,14 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, "last_to_free %d is out of range [0-%d] %d %d.\n", __func__, txq_id, last_to_free, q->n_bd, q->write_ptr, q->read_ptr); - return; + return 0; } IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id, q->read_ptr, index); if (WARN_ON(!skb_queue_empty(skbs))) - return; + return 0; for (; q->read_ptr != index; @@ -1158,5 +1159,7 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, iwlagn_txq_inval_byte_cnt_tbl(trans, txq); iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); + freed++; } + return freed; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 13e8fdc4c012..0256454427fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1265,19 +1265,75 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) return 0; } -static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, - int ssn, u32 status, struct sk_buff_head *skbs) +static int iwlagn_txq_check_empty(struct iwl_trans *trans, + int sta_id, u8 tid, int txq_id) { - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &priv(trans)->txq[txq_id].q; + struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; + + lockdep_assert_held(&trans->shrd->sta_lock); + + switch (trans->shrd->tid_data[sta_id][tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_DELBA: + /* We are reclaiming the last packet of the */ + /* aggregated HW queue */ + if ((txq_id == tid_data->agg.txq_id) && + (q->read_ptr == q->write_ptr)) { + IWL_DEBUG_HT(trans, + "HW queue empty: continue DELBA flow\n"); + iwl_trans_pcie_txq_agg_disable(priv(trans), txq_id); + tid_data->agg.state = IWL_AGG_OFF; + iwl_stop_tx_ba_trans_ready(priv(trans), + NUM_IWL_RXON_CTX, + sta_id, tid); + iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* We are reclaiming the last packet of the queue */ + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(trans, + "HW queue empty: continue ADDBA flow\n"); + tid_data->agg.state = IWL_AGG_ON; + iwl_start_tx_ba_trans_ready(priv(trans), + NUM_IWL_RXON_CTX, + sta_id, tid); + } + break; + } + + return 0; +} + +static void iwl_free_tfds_in_queue(struct iwl_trans *trans, + int sta_id, int tid, int freed) +{ + lockdep_assert_held(&trans->shrd->sta_lock); + + if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) + trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; + else { + IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n", + trans->shrd->tid_data[sta_id][tid].tfds_in_queue, + freed); + trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; + } +} + +static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, + int txq_id, int ssn, u32 status, + struct sk_buff_head *skbs) +{ + struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; /* n_bd is usually 256 => n_bd - 1 = 0xff */ int tfd_num = ssn & (txq->q.n_bd - 1); + int freed = 0; u8 agg_state; bool cond; if (txq->sched_retry) { agg_state = - priv->shrd->tid_data[txq->sta_id][txq->tid].agg.state; + trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); } else { cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); @@ -1287,10 +1343,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " "scd_ssn=%d idx=%d txq=%d swq=%d\n", ssn , tfd_num, txq_id, txq->swq_id); - iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); + freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) - iwl_wake_queue(priv, txq); + iwl_wake_queue(priv(trans), txq); } + + iwl_free_tfds_in_queue(trans, sta_id, tid, freed); + iwlagn_txq_check_empty(trans, sta_id, tid, txq_id); } static void iwl_trans_pcie_free(struct iwl_trans *trans) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8aaab087ba54..7586a1512e84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -123,8 +123,9 @@ struct iwl_trans_ops { const void *data); int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); - void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, - u32 status, struct sk_buff_head *skbs); + void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, + int txq_id, int ssn, u32 status, + struct sk_buff_head *skbs); int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id); int (*tx_agg_alloc)(struct iwl_trans *trans, @@ -208,11 +209,11 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); } -static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, - int ssn, u32 status, +static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, + int tid, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs) { - trans->ops->reclaim(trans, txq_id, ssn, status, skbs); + trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs); } static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id) From 7f01d567c5b9e136d9b070e00be88169d5b2227e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:27 -0700 Subject: [PATCH 104/129] iwlagn: move the disable agg logic to transport layer Since all the check_empty logic is now in the transport layer, the upper layer doesn't need to know anything about tx queues. The disable aggregation flow was the last to know what a tx queue is, so move it too. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 63 +----------- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 5 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 98 +++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-trans.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 12 ++- 5 files changed, 97 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 45eb45af5953..bc3268a0c752 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -408,10 +408,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - int txq_id, sta_id, ssn; - struct iwl_tid_data *tid_data; - int write_ptr, read_ptr; - unsigned long flags; + int sta_id; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; sta_id = iwl_sta_id(sta); @@ -420,61 +418,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - - tid_data = &priv->shrd->tid_data[sta_id][tid]; - ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; - txq_id = tid_data->agg.txq_id; - - switch (priv->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* - * This can happen if the peer stops aggregation - * again before we've had a chance to drain the - * queue we selected previously, i.e. before the - * session was really started completely. - */ - IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - goto turn_off; - case IWL_AGG_ON: - break; - default: - IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); - } - - write_ptr = priv->txq[txq_id].q.write_ptr; - read_ptr = priv->txq[txq_id].q.read_ptr; - - /* The queue is not empty */ - if (write_ptr != read_ptr) { - IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); - priv->shrd->tid_data[sta_id][tid].agg.state = - IWL_EMPTYING_HW_QUEUE_DELBA; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return 0; - } - - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - turn_off: - priv->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; - - /* do not restore/save irqs */ - spin_unlock(&priv->shrd->sta_lock); - spin_lock(&priv->shrd->lock); - - /* - * the only reason this call can fail is queue number out of range, - * which can happen if uCode is reloaded and all the station - * information are lost. if it is outside the range, there is no need - * to deactivate the uCode queue, just return "success" to allow - * mac80211 to clean up it own data. - */ - iwl_trans_txq_agg_disable(trans(priv), txq_id); - spin_unlock_irqrestore(&priv->shrd->lock, flags); - - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); - - return 0; + return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid, + sta_id, tid); } static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index ba82c8bca242..a31083125faa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -189,7 +189,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt); -int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id); +void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id); +int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid); void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index da8d79eb4dc5..aa44b9242d07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -560,32 +560,92 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, return 0; } -int iwl_trans_pcie_txq_agg_disable(struct iwl_priv *priv, u16 txq_id) -{ - struct iwl_trans *trans = trans(priv); - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(priv).num_ampdu_queues <= txq_id)) { - IWL_ERR(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWLAGN_FIRST_AMPDU_QUEUE, - IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(priv).num_ampdu_queues - 1); - return -EINVAL; - } +void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id) +{ iwlagn_tx_queue_stop_scheduler(trans, txq_id); - iwl_clear_bits_prph(bus(priv), SCD_AGGR_SEL, (1 << txq_id)); + iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); - priv->txq[txq_id].q.read_ptr = 0; - priv->txq[txq_id].q.write_ptr = 0; + priv(trans)->txq[txq_id].q.read_ptr = 0; + priv(trans)->txq[txq_id].q.write_ptr = 0; /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl_trans_set_wr_ptrs(trans, txq_id, 0); - iwl_clear_bits_prph(bus(priv), SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], 0, 0); + iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv(trans), txq_id); + iwl_trans_tx_queue_set_status(priv(trans), + &priv(trans)->txq[txq_id], 0, 0); +} + +int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid) +{ + unsigned long flags; + int read_ptr, write_ptr; + struct iwl_tid_data *tid_data; + int txq_id; + + spin_lock_irqsave(&trans->shrd->sta_lock, flags); + + tid_data = &trans->shrd->tid_data[sta_id][tid]; + txq_id = tid_data->agg.txq_id; + + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + + hw_params(trans).num_ampdu_queues <= txq_id)) { + IWL_ERR(trans, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + + hw_params(trans).num_ampdu_queues - 1); + spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + return -EINVAL; + } + + switch (trans->shrd->tid_data[sta_id][tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* + * This can happen if the peer stops aggregation + * again before we've had a chance to drain the + * queue we selected previously, i.e. before the + * session was really started completely. + */ + IWL_DEBUG_HT(trans, "AGG stop before setup done\n"); + goto turn_off; + case IWL_AGG_ON: + break; + default: + IWL_WARN(trans, "Stopping AGG while state not ON" + "or starting\n"); + } + + write_ptr = priv(trans)->txq[txq_id].q.write_ptr; + read_ptr = priv(trans)->txq[txq_id].q.read_ptr; + + /* The queue is not empty */ + if (write_ptr != read_ptr) { + IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n"); + trans->shrd->tid_data[sta_id][tid].agg.state = + IWL_EMPTYING_HW_QUEUE_DELBA; + spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + return 0; + } + + IWL_DEBUG_HT(trans, "HW queue is empty\n"); +turn_off: + trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; + + /* do not restore/save irqs */ + spin_unlock(&trans->shrd->sta_lock); + spin_lock(&trans->shrd->lock); + + iwl_trans_pcie_txq_agg_disable(trans, txq_id); + + spin_unlock_irqrestore(&trans->shrd->lock, flags); + + iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 0256454427fd..ab35fd827bdc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1281,7 +1281,7 @@ static int iwlagn_txq_check_empty(struct iwl_trans *trans, (q->read_ptr == q->write_ptr)) { IWL_DEBUG_HT(trans, "HW queue empty: continue DELBA flow\n"); - iwl_trans_pcie_txq_agg_disable(priv(trans), txq_id); + iwl_trans_pcie_txq_agg_disable(trans, txq_id); tid_data->agg.state = IWL_AGG_OFF; iwl_stop_tx_ba_trans_ready(priv(trans), NUM_IWL_RXON_CTX, @@ -2015,7 +2015,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx = iwl_trans_pcie_tx, .reclaim = iwl_trans_pcie_reclaim, - .txq_agg_disable = iwl_trans_pcie_txq_agg_disable, + .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, .txq_agg_setup = iwl_trans_pcie_txq_agg_setup, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7586a1512e84..1fd6bde42a7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -97,7 +97,7 @@ struct iwl_device_cmd; * @tx_agg_alloc: allocate resources for a TX BA session * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. - * @txq_agg_disable: de-configure a Tx queue to send AMPDUs + * @tx_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... @@ -127,7 +127,9 @@ struct iwl_trans_ops { int txq_id, int ssn, u32 status, struct sk_buff_head *skbs); - int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id); + int (*tx_agg_disable)(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid); int (*tx_agg_alloc)(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, u16 *ssn); @@ -216,9 +218,11 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs); } -static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id) +static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, + int sta_id, int tid) { - return trans->ops->txq_agg_disable(priv(trans), txq_id); + return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid); } static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, From c91bd12489f50809af94c46d7c4c4d98b70c6f47 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:28 -0700 Subject: [PATCH 105/129] iwlagn: cosmetics in iwl-trans.h Remove a few dereferences of priv from the transport layer while at it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 8 ++-- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 48 +++++++++---------- drivers/net/wireless/iwlwifi/iwl-trans.c | 14 +++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 16 +++---- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 60b964bd5cf8..724c50a069dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2565,7 +2565,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwl_trans_txq_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), + iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), tid, buf_size); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index a31083125faa..abb2ce68deec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -194,15 +194,15 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid); void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); -void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, +void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, u16 *ssn); -void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, int frame_limit); +void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, + int sta_id, int tid, int frame_limit); void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index); int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index aa44b9242d07..28c606cade3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -403,14 +403,15 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); } -void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, +void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry) { int txq_id = txq->q.id; - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; + int active = + test_bit(txq_id, &priv(trans)->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(bus(priv), SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -418,7 +419,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", + IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n", active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } @@ -434,16 +435,15 @@ static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, return -EINVAL; } -void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, int frame_limit) +void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, + int tid, int frame_limit) { int tx_fifo, txq_id, ssn_idx; u16 ra_tid; unsigned long flags; struct iwl_tid_data *tid_data; - struct iwl_trans *trans = trans(priv); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -458,15 +458,15 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, return; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - tid_data = &priv->shrd->tid_data[sta_id][tid]; + spin_lock_irqsave(&trans->shrd->sta_lock, flags); + tid_data = &trans->shrd->tid_data[sta_id][tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); ra_tid = BUILD_RAxTID(sta_id, tid); - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&trans->shrd->lock, flags); /* Stop this Tx queue before configuring it */ iwlagn_tx_queue_stop_scheduler(trans, txq_id); @@ -475,19 +475,19 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(bus(priv), SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + priv(trans)->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv(trans)->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(bus(priv), trans_pcie->scd_base_addr + + iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << @@ -497,15 +497,16 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(bus(priv), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + iwl_trans_tx_queue_set_status(trans, &priv(trans)->txq[txq_id], + tx_fifo, 1); - priv->txq[txq_id].sta_id = sta_id; - priv->txq[txq_id].tid = tid; + priv(trans)->txq[txq_id].sta_id = sta_id; + priv(trans)->txq[txq_id].tid = tid; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&trans->shrd->lock, flags); } /* @@ -574,8 +575,7 @@ void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id) iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv(trans), txq_id); - iwl_trans_tx_queue_set_status(priv(trans), - &priv(trans)->txq[txq_id], 0, 0); + iwl_trans_tx_queue_set_status(trans, &priv(trans)->txq[txq_id], 0, 0); } int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ab35fd827bdc..9b0ecd4b1e1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -774,7 +774,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - priv->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; + trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; @@ -784,7 +784,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; - if ((hw_params(priv).sku & EEPROM_SKU_CAP_AMT_ENABLE) && + if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && iwl_trans_pcie_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; @@ -862,7 +862,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) a += 4) iwl_write_targ_mem(bus(trans), a, 0); for (; a < trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(priv).max_txq_num); + SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); a += 4) iwl_write_targ_mem(bus(trans), a, 0); @@ -881,11 +881,11 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, - SCD_QUEUECHAIN_SEL_ALL(priv)); + SCD_QUEUECHAIN_SEL_ALL(trans)); iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); /* initiate the queues */ - for (i = 0; i < hw_params(priv).max_txq_num; i++) { + for (i = 0; i < hw_params(trans).max_txq_num; i++) { iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + @@ -941,7 +941,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) if (ac != IWL_AC_UNSET) iwl_set_swq_id(&priv->txq[i], ac, i); - iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); + iwl_trans_tx_queue_set_status(trans, &priv->txq[i], fifo, 0); } spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -2017,7 +2017,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, - .txq_agg_setup = iwl_trans_pcie_txq_agg_setup, + .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, .kick_nic = iwl_trans_pcie_kick_nic, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 1fd6bde42a7c..c92c9fed8fea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -95,7 +95,7 @@ struct iwl_device_cmd; * @tx: send an skb * @reclaim: free packet until ssn. Returns a list of freed packets. * @tx_agg_alloc: allocate resources for a TX BA session - * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. * @tx_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run @@ -128,14 +128,14 @@ struct iwl_trans_ops { struct sk_buff_head *skbs); int (*tx_agg_disable)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid); + enum iwl_rxon_context_id ctx, int sta_id, + int tid); int (*tx_agg_alloc)(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, u16 *ssn); - void (*txq_agg_setup)(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, int frame_limit); + void (*tx_agg_setup)(struct iwl_trans *trans, + enum iwl_rxon_context_id ctx, int sta_id, int tid, + int frame_limit); void (*kick_nic)(struct iwl_trans *trans); @@ -233,12 +233,12 @@ static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, } -static inline void iwl_trans_txq_agg_setup(struct iwl_trans *trans, +static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, int frame_limit) { - trans->ops->txq_agg_setup(priv(trans), ctx, sta_id, tid, frame_limit); + trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit); } static inline void iwl_trans_kick_nic(struct iwl_trans *trans) From 5f178cd2ebe8ac196b245428c574f1def1964b14 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:29 -0700 Subject: [PATCH 106/129] iwlagn: move wait_for_tx_queue_empty to transport layer This one is really transport related. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 33 +--------------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans.c | 32 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 8 ++++++ 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 359bd9060560..7c036b9c2b30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -634,37 +634,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, vif->bss_conf.bssid); } -#define IWL_FLUSH_WAIT_MS 2000 - -int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) -{ - struct iwl_tx_queue *txq; - struct iwl_queue *q; - int cnt; - unsigned long now = jiffies; - int ret = 0; - - /* waiting for all the tx frames complete might take a while */ - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - if (cnt == priv->shrd->cmd_queue) - continue; - txq = &priv->txq[cnt]; - q = &txq->q; - while (q->read_ptr != q->write_ptr && !time_after(jiffies, - now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) - msleep(1); - - if (q->read_ptr != q->write_ptr) { - IWL_ERR(priv, "fail to flush all tx fifo queues\n"); - ret = -ETIMEDOUT; - break; - } - } - return ret; -} - -#define IWL_TX_QUEUE_MSK 0xfffff - /** * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode * @@ -715,7 +684,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) goto done; } IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); - iwlagn_wait_tx_queue_empty(priv); + iwl_trans_wait_tx_queue_empty(trans(priv)); done: ieee80211_wake_queues(priv->hw); mutex_unlock(&priv->shrd->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 724c50a069dc..5d0888a7fbc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2833,7 +2833,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) } } IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); - iwlagn_wait_tx_queue_empty(priv); + iwl_trans_wait_tx_queue_empty(trans(priv)); done: mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2b94a10561d1..a7b4948e43da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -102,7 +102,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); -int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); int iwlagn_send_beacon_cmd(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 9b0ecd4b1e1c..7b868c7b523a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1446,6 +1446,35 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) return iwl_trans; } +#define IWL_FLUSH_WAIT_MS 2000 + +static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) +{ + struct iwl_tx_queue *txq; + struct iwl_queue *q; + int cnt; + unsigned long now = jiffies; + int ret = 0; + + /* waiting for all the tx frames complete might take a while */ + for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { + if (cnt == trans->shrd->cmd_queue) + continue; + txq = &priv(trans)->txq[cnt]; + q = &txq->q; + while (q->read_ptr != q->write_ptr && !time_after(jiffies, + now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) + msleep(1); + + if (q->read_ptr != q->write_ptr) { + IWL_ERR(trans, "fail to flush all tx fifo queues\n"); + ret = -ETIMEDOUT; + break; + } + } + return ret; +} + #ifdef CONFIG_IWLWIFI_DEBUGFS /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ @@ -2024,6 +2053,9 @@ const struct iwl_trans_ops trans_ops_pcie = { .free = iwl_trans_pcie_free, .dbgfs_register = iwl_trans_pcie_dbgfs_register, + + .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, + .suspend = iwl_trans_pcie_suspend, .resume = iwl_trans_pcie_resume, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c92c9fed8fea..45d6dff47ebb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -101,6 +101,7 @@ struct iwl_device_cmd; * @kick_nic: remove the RESET from the embedded CPU and let it run * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... + * @wait_tx_queue_empty: wait until all tx queues are empty * @dbgfs_register: add the dbgfs files under this directory. Files will be * automatically deleted. * @suspend: stop the device unless WoWLAN is configured @@ -142,6 +143,8 @@ struct iwl_trans_ops { void (*free)(struct iwl_trans *trans); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); + int (*wait_tx_queue_empty)(struct iwl_trans *trans); + int (*suspend)(struct iwl_trans *trans); int (*resume)(struct iwl_trans *trans); }; @@ -251,6 +254,11 @@ static inline void iwl_trans_free(struct iwl_trans *trans) trans->ops->free(trans); } +static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) +{ + return trans->ops->wait_tx_queue_empty(trans); +} + static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, struct dentry *dir) { From f22be624c29b7f714e5a82ad13dc33a0cd1443a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:30 -0700 Subject: [PATCH 107/129] iwlagn: move check_stuck_queue to transport layer This one is really transport related. ==== moves Stanislaw's code to BSD area ==== Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 26 +++------------------ drivers/net/wireless/iwlwifi/iwl-shared.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-trans.c | 28 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 6 +++++ 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5d0888a7fbc0..5fdf9b10b470 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3191,8 +3191,8 @@ static int iwl_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_ampdu_queues; hw_params(priv).shadow_reg_enable = priv->cfg->base_params->shadow_reg_enable; - hw_params(priv).sku = - priv->cfg->sku; + hw_params(priv).sku = priv->cfg->sku; + hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout; /* Device-specific setup */ return priv->cfg->lib->set_hw_params(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c6f8e682d03c..20dd1a5506ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1724,32 +1724,12 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return err; } -/* - * On every watchdog tick we check (latest) time stamp. If it does not - * change during timeout period and queue is not empty we reset firmware. - */ -static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) +static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq) { - struct iwl_tx_queue *txq = &priv->txq[cnt]; - struct iwl_queue *q = &txq->q; - unsigned long timeout; - int ret; - - if (q->read_ptr == q->write_ptr) { - txq->time_stamp = jiffies; - return 0; - } - - timeout = txq->time_stamp + - msecs_to_jiffies(priv->cfg->base_params->wd_timeout); - - if (time_after(jiffies, timeout)) { - IWL_ERR(priv, "Queue %d stuck for %u ms.\n", - q->id, priv->cfg->base_params->wd_timeout); - ret = iwl_force_reset(priv, IWL_FW_RESET, false); + if (iwl_trans_check_stuck_queue(trans(priv), txq)) { + int ret = iwl_force_reset(priv, IWL_FW_RESET, false); return (ret == -EAGAIN) ? 0 : 1; } - return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 0bd6f7d54433..17a02a76f8b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -147,6 +147,7 @@ struct iwl_mod_params { * @sw_crypto: 0 for hw, 1 for sw * @max_xxx_size: for ucode uses * @ct_kill_threshold: temperature threshold + * @wd_timeout: TX queues watchdog timeout * @calib_init_cfg: setup initial calibrations for the hw * @calib_rt_cfg: setup runtime calibrations for the hw * @struct iwl_sensitivity_ranges: range of sensitivity values @@ -169,6 +170,8 @@ struct iwl_hw_params { u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_exit_threshold; /* value in hw-dependent units */ /* for 1000, 6000 series and up */ + unsigned int wd_timeout; + u32 calib_init_cfg; u32 calib_rt_cfg; const struct iwl_sensitivity_ranges *sens; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 7b868c7b523a..646170400e16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1475,6 +1475,33 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) return ret; } +/* + * On every watchdog tick we check (latest) time stamp. If it does not + * change during timeout period and queue is not empty we reset firmware. + */ +static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) +{ + struct iwl_tx_queue *txq = &priv(trans)->txq[cnt]; + struct iwl_queue *q = &txq->q; + unsigned long timeout; + + if (q->read_ptr == q->write_ptr) { + txq->time_stamp = jiffies; + return 0; + } + + timeout = txq->time_stamp + + msecs_to_jiffies(hw_params(trans).wd_timeout); + + if (time_after(jiffies, timeout)) { + IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, + hw_params(trans).wd_timeout); + return 1; + } + + return 0; +} + #ifdef CONFIG_IWLWIFI_DEBUGFS /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ @@ -2055,6 +2082,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .dbgfs_register = iwl_trans_pcie_dbgfs_register, .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, + .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, .suspend = iwl_trans_pcie_suspend, .resume = iwl_trans_pcie_resume, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 45d6dff47ebb..6edf2e0dadab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -101,6 +101,7 @@ struct iwl_device_cmd; * @kick_nic: remove the RESET from the embedded CPU and let it run * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... + * @check_stuck_queue: check if a specific queue is stuck * @wait_tx_queue_empty: wait until all tx queues are empty * @dbgfs_register: add the dbgfs files under this directory. Files will be * automatically deleted. @@ -143,6 +144,7 @@ struct iwl_trans_ops { void (*free)(struct iwl_trans *trans); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); + int (*check_stuck_queue)(struct iwl_trans *trans, int q); int (*wait_tx_queue_empty)(struct iwl_trans *trans); int (*suspend)(struct iwl_trans *trans); @@ -259,6 +261,10 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) return trans->ops->wait_tx_queue_empty(trans); } +static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q) +{ + return trans->ops->check_stuck_queue(trans, q); +} static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, struct dentry *dir) { From e20d434170c3a7f388d5e916825499c9c0738606 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:31 -0700 Subject: [PATCH 108/129] iwlagn: move the stop / wake queue logic to transport layer priv->mac80211_registered and priv->hw needed to move to shared. stop_queue API was added in order to allow the upper layer to stop the SW queues for regulatory purposes. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 - drivers/net/wireless/iwlwifi/iwl-helpers.h | 61 ------------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 6 ++ .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 61 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 14 +++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 8 +++ 9 files changed, 93 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 495f93664741..92ba8cd0ecd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, { if (stop) { IWL_DEBUG_TEMP(priv, "Stop all queues\n"); - if (priv->mac80211_registered) + if (priv->shrd->mac80211_registered) ieee80211_stop_queues(priv->hw); IWL_DEBUG_TEMP(priv, "Schedule 5 seconds CT_KILL Timer\n"); @@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, jiffies + CT_KILL_EXIT_DURATION * HZ); } else { IWL_DEBUG_TEMP(priv, "Wake all queues\n"); - if (priv->mac80211_registered) + if (priv->shrd->mac80211_registered) ieee80211_wake_queues(priv->hw); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index bc3268a0c752..009c35a8d20b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -803,7 +803,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) iwl_is_associated_ctx(ctx) && ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) { ctx->last_tx_rejected = true; - iwl_stop_queue(priv, &priv->txq[txq_id]); + iwl_trans_stop_queue(trans(priv), txq_id); IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) " diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5fdf9b10b470..a0cf486f7625 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1519,7 +1519,7 @@ static void __iwl_down(struct iwl_priv *priv) if (!exit_pending) clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); - if (priv->mac80211_registered) + if (priv->shrd->mac80211_registered) ieee80211_stop_queues(priv->hw); /* Clear out all status bits but a few that are stable across reset */ @@ -1863,7 +1863,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); return ret; } - priv->mac80211_registered = 1; + priv->shrd->mac80211_registered = 1; return 0; } @@ -3243,6 +3243,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, priv->shrd = &priv->_shrd; priv->shrd->bus = bus; priv->shrd->priv = priv; + priv->shrd->hw = hw; bus_set_drv_data(priv->bus, priv->shrd); priv->shrd->trans = trans_ops->alloc(priv->shrd); @@ -3418,9 +3419,9 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_testmode_cleanup(priv); iwl_leds_exit(priv); - if (priv->mac80211_registered) { + if (priv->shrd->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - priv->mac80211_registered = 0; + priv->shrd->mac80211_registered = 0; } iwl_tt_exit(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2e75429f5ac6..08e8e1bf4830 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1181,8 +1181,6 @@ struct iwl_priv { /* Indication if ieee80211_ops->open has been called */ u8 is_open; - u8 mac80211_registered; - /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 7f92d14083ca..d3feac9e45b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -64,67 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) return --index & (n_bd - 1); } -/* - * we have 8 bits used like this: - * - * 7 6 5 4 3 2 1 0 - * | | | | | | | | - * | | | | | | +-+-------- AC queue (0-3) - * | | | | | | - * | +-+-+-+-+------------ HW queue ID - * | - * +---------------------- unused - */ -static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) -{ - BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only use 5 bits */ - - txq->swq_id = (hwq << 2) | ac; -} - -static inline void iwl_wake_queue(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - - if (unlikely(!priv->mac80211_registered)) - return; - - if (test_and_clear_bit(hwq, priv->queue_stopped)) - if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) - ieee80211_wake_queue(priv->hw, ac); -} - -static inline void iwl_stop_queue(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - - if (unlikely(!priv->mac80211_registered)) - return; - - if (!test_and_set_bit(hwq, priv->queue_stopped)) - if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) - ieee80211_stop_queue(priv->hw, ac); -} - -#ifdef ieee80211_stop_queue -#undef ieee80211_stop_queue -#endif - -#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue - -#ifdef ieee80211_wake_queue -#undef ieee80211_wake_queue -#endif - -#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue - static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 17a02a76f8b2..8b8cd54a32e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -243,6 +243,12 @@ struct iwl_shared { spinlock_t sta_lock; struct mutex mutex; + /*these 2 shouldn't really be here, but they are needed for + * iwl_queue_stop, which is called from the upper layer too + */ + u8 mac80211_registered; + struct ieee80211_hw *hw; + struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index abb2ce68deec..255b326bf0e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -240,4 +240,65 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); } +/* + * we have 8 bits used like this: + * + * 7 6 5 4 3 2 1 0 + * | | | | | | | | + * | | | | | | +-+-------- AC queue (0-3) + * | | | | | | + * | +-+-+-+-+------------ HW queue ID + * | + * +---------------------- unused + */ +static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) +{ + BUG_ON(ac > 3); /* only have 2 bits */ + BUG_ON(hwq > 31); /* only use 5 bits */ + + txq->swq_id = (hwq << 2) | ac; +} + +static inline void iwl_wake_queue(struct iwl_trans *trans, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (unlikely(!trans->shrd->mac80211_registered)) + return; + + if (test_and_clear_bit(hwq, priv(trans)->queue_stopped)) + if (atomic_dec_return(&priv(trans)->queue_stop_count[ac]) <= 0) + ieee80211_wake_queue(trans->shrd->hw, ac); +} + +static inline void iwl_stop_queue(struct iwl_trans *trans, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (unlikely(!trans->shrd->mac80211_registered)) + return; + + if (!test_and_set_bit(hwq, priv(trans)->queue_stopped)) + if (atomic_inc_return(&priv(trans)->queue_stop_count[ac]) > 0) + ieee80211_stop_queue(trans->shrd->hw, ac); +} + +#ifdef ieee80211_stop_queue +#undef ieee80211_stop_queue +#endif + +#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue + +#ifdef ieee80211_wake_queue +#undef ieee80211_wake_queue +#endif + +#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 646170400e16..cce57d53f618 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -1228,7 +1228,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, txq->need_update = 1; iwl_txq_update_write_ptr(trans, txq); } else { - iwl_stop_queue(priv(trans), txq); + iwl_stop_queue(trans, txq); } } return 0; @@ -1286,7 +1286,7 @@ static int iwlagn_txq_check_empty(struct iwl_trans *trans, iwl_stop_tx_ba_trans_ready(priv(trans), NUM_IWL_RXON_CTX, sta_id, tid); - iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); + iwl_wake_queue(trans, &priv(trans)->txq[txq_id]); } break; case IWL_EMPTYING_HW_QUEUE_ADDBA: @@ -1345,7 +1345,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, ssn , tfd_num, txq_id, txq->swq_id); freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) - iwl_wake_queue(priv(trans), txq); + iwl_wake_queue(trans, txq); } iwl_free_tfds_in_queue(trans, sta_id, tid, freed); @@ -1423,7 +1423,7 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, ac, (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0) ? "stopped" : "awake"); - iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); + iwl_wake_queue(trans, &priv(trans)->txq[txq_id]); } } @@ -1446,6 +1446,11 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) return iwl_trans; } +static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) +{ + iwl_stop_queue(trans, &priv(trans)->txq[txq_id]); +} + #define IWL_FLUSH_WAIT_MS 2000 static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) @@ -2078,6 +2083,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .kick_nic = iwl_trans_pcie_kick_nic, .free = iwl_trans_pcie_free, + .stop_queue = iwl_trans_pcie_stop_queue, .dbgfs_register = iwl_trans_pcie_dbgfs_register, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 6edf2e0dadab..7a2daa886dfd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -101,6 +101,7 @@ struct iwl_device_cmd; * @kick_nic: remove the RESET from the embedded CPU and let it run * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... + * @stop_queue: stop a specific queue * @check_stuck_queue: check if a specific queue is stuck * @wait_tx_queue_empty: wait until all tx queues are empty * @dbgfs_register: add the dbgfs files under this directory. Files will be @@ -143,6 +144,8 @@ struct iwl_trans_ops { void (*free)(struct iwl_trans *trans); + void (*stop_queue)(struct iwl_trans *trans, int q); + int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); int (*check_stuck_queue)(struct iwl_trans *trans, int q); int (*wait_tx_queue_empty)(struct iwl_trans *trans); @@ -256,6 +259,11 @@ static inline void iwl_trans_free(struct iwl_trans *trans) trans->ops->free(trans); } +static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q) +{ + trans->ops->stop_queue(trans, q); +} + static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) { return trans->ops->wait_tx_queue_empty(trans); From 8ad71bef4a9d8173cbcfbb2f796b08d33d4ca01b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 25 Aug 2011 23:11:32 -0700 Subject: [PATCH 109/129] iwlagn: move tx queues to transport layer This finalizes the move of the data path to the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 23 +--- drivers/net/wireless/iwlwifi/iwl-dev.h | 42 ------- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 50 ++++++++- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 2 +- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 53 +++++---- drivers/net/wireless/iwlwifi/iwl-trans.c | 105 +++++++++--------- 6 files changed, 136 insertions(+), 139 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 009c35a8d20b..f8a4bcf0a34b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -742,7 +742,6 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int cmd_index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; struct ieee80211_hdr *hdr; u32 status = le16_to_cpu(tx_resp->status.status); @@ -755,17 +754,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct sk_buff_head skbs; struct sk_buff *skb; struct iwl_rxon_context *ctx; - - if ((cmd_index >= txq->q.n_bd) || - (iwl_queue_used(&txq->q, cmd_index) == 0)) { - IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) " - "cmd_index %d is out of range [0-%d] %d %d\n", - __func__, txq_id, cmd_index, txq->q.n_bd, - txq->q.write_ptr, txq->q.read_ptr); - return; - } - - txq->time_stamp = jiffies; + bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> IWLAGN_TX_RES_TID_POS; @@ -774,12 +763,10 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) spin_lock_irqsave(&priv->shrd->sta_lock, flags); - if (txq->sched_retry) + if (is_agg) iwl_rx_reply_tx_agg(priv, tx_resp); if (tx_resp->frame_count == 1) { - bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); - __skb_queue_head_init(&skbs); /*we can free until ssn % q.n_bd not inclusive */ iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, @@ -850,14 +837,12 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; - struct iwl_tx_queue *txq = NULL; struct iwl_ht_agg *agg; struct sk_buff_head reclaimed_skbs; struct ieee80211_tx_info *info; struct ieee80211_hdr *hdr; struct sk_buff *skb; unsigned long flags; - int index; int sta_id; int tid; int freed; @@ -875,14 +860,10 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, return; } - txq = &priv->txq[scd_flow]; sta_id = ba_resp->sta_id; tid = ba_resp->tid; agg = &priv->shrd->tid_data[sta_id][tid].agg; - /* Find index of block-ack window */ - index = ba_resp_scd_ssn & (txq->q.n_bd - 1); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); if (unlikely(agg->txq_id != scd_flow)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 08e8e1bf4830..33a829ad7e2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -574,19 +574,6 @@ struct iwl_sensitivity_ranges { ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); extern const u8 iwl_bcast_addr[ETH_ALEN]; -extern int iwl_queue_space(const struct iwl_queue *q); -static inline int iwl_queue_used(const struct iwl_queue *q, int i) -{ - return q->write_ptr >= q->read_ptr ? - (i >= q->read_ptr && i < q->write_ptr) : - !(i < q->read_ptr && i >= q->write_ptr); -} - - -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) -{ - return index & (q->n_window - 1); -} #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 @@ -1156,10 +1143,6 @@ struct iwl_priv { int activity_timer_active; - /* Tx DMA processing queues */ - struct iwl_tx_queue *txq; - unsigned long txq_ctx_active_msk; - /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; struct traffic_stats rx_stats; @@ -1172,12 +1155,6 @@ struct iwl_priv { struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; unsigned long ucode_key_table; - /* queue refcounts */ -#define IWL_MAX_HW_QUEUES 32 - unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; - /* for each AC */ - atomic_t queue_stop_count[4]; - /* Indication if ieee80211_ops->open has been called */ u8 is_open; @@ -1334,27 +1311,8 @@ struct iwl_priv { bool have_rekey_data; }; /*iwl_priv */ -static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) -{ - set_bit(txq_id, &priv->txq_ctx_active_msk); -} - -static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) -{ - clear_bit(txq_id, &priv->txq_ctx_active_msk); -} - extern struct iwl_mod_params iwlagn_mod_params; -static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, - int txq_id, int idx) -{ - if (priv->txq[txq_id].skbs[idx]) - return (struct ieee80211_hdr *)priv->txq[txq_id]. - skbs[idx]->data; - return NULL; -} - static inline struct iwl_rxon_context * iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 255b326bf0e9..ec4e73737681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -125,6 +125,10 @@ struct iwl_dma_ptr { * @ac_to_fifo: to what fifo is a specifc AC mapped ? * @ac_to_queue: to what tx queue is a specifc AC mapped ? * @mcast_queue: + * @txq: Tx DMA processing queues + * @txq_ctx_active_msk: what queue is active + * queue_stopped: tracks what queue is stopped + * queue_stop_count: tracks what SW queue is stopped */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -150,6 +154,12 @@ struct iwl_trans_pcie { const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; u8 mcast_queue[NUM_IWL_RXON_CTX]; + + struct iwl_tx_queue *txq; + unsigned long txq_ctx_active_msk; +#define IWL_MAX_HW_QUEUES 32 + unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; + atomic_t queue_stop_count[4]; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ @@ -207,6 +217,7 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, int index); int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, struct sk_buff_head *skbs); +int iwl_queue_space(const struct iwl_queue *q); /***************************************************** * Error handling @@ -216,6 +227,9 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); void iwl_dump_csr(struct iwl_trans *trans); +/***************************************************** +* Helpers +******************************************************/ static inline void iwl_disable_interrupts(struct iwl_trans *trans) { clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); @@ -265,12 +279,14 @@ static inline void iwl_wake_queue(struct iwl_trans *trans, u8 queue = txq->swq_id; u8 ac = queue & 3; u8 hwq = (queue >> 2) & 0x1f; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); if (unlikely(!trans->shrd->mac80211_registered)) return; - if (test_and_clear_bit(hwq, priv(trans)->queue_stopped)) - if (atomic_dec_return(&priv(trans)->queue_stop_count[ac]) <= 0) + if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) + if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) ieee80211_wake_queue(trans->shrd->hw, ac); } @@ -280,12 +296,14 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, u8 queue = txq->swq_id; u8 ac = queue & 3; u8 hwq = (queue >> 2) & 0x1f; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); if (unlikely(!trans->shrd->mac80211_registered)) return; - if (!test_and_set_bit(hwq, priv(trans)->queue_stopped)) - if (atomic_inc_return(&priv(trans)->queue_stop_count[ac]) > 0) + if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) + if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) ieee80211_stop_queue(trans->shrd->hw, ac); } @@ -301,4 +319,28 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue +static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, + int txq_id) +{ + set_bit(txq_id, &trans_pcie->txq_ctx_active_msk); +} + +static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie, + int txq_id) +{ + clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk); +} + +static inline int iwl_queue_used(const struct iwl_queue *q, int i) +{ + return q->write_ptr >= q->read_ptr ? + (i >= q->read_ptr && i < q->write_ptr) : + !(i < q->read_ptr && i >= q->write_ptr); +} + +static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) +{ + return index & (q->n_window - 1); +} + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index a0699c0ef4f8..2d0ddb8d422d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -1032,7 +1032,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); for (i = 0; i < hw_params(trans).max_txq_num; i++) iwl_txq_update_write_ptr(trans, - &priv(trans)->txq[i]); + &trans_pcie->txq[i]); isr_stats->wakeup++; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 28c606cade3c..5dd6a6d1dfd7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -407,9 +407,10 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id = txq->q.id; int active = - test_bit(txq_id, &priv(trans)->txq_ctx_active_msk) ? 1 : 0; + test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | @@ -482,8 +483,8 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, /* Place first TFD at index corresponding to start sequence number. * Assumes that ssn_idx is valid (!= 0xFFF) */ - priv(trans)->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv(trans)->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ @@ -500,11 +501,11 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl_trans_tx_queue_set_status(trans, &priv(trans)->txq[txq_id], + iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], tx_fifo, 1); - priv(trans)->txq[txq_id].sta_id = sta_id; - priv(trans)->txq[txq_id].tid = tid; + trans_pcie->txq[txq_id].sta_id = sta_id; + trans_pcie->txq[txq_id].tid = tid; spin_unlock_irqrestore(&trans->shrd->lock, flags); } @@ -517,11 +518,12 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, */ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id; for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, - &priv(trans)->txq_ctx_active_msk)) + &trans_pcie->txq_ctx_active_msk)) return txq_id; return -1; } @@ -530,6 +532,7 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, u16 *ssn) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tid_data *tid_data; unsigned long flags; u16 txq_id; @@ -545,7 +548,7 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, tid_data = &trans->shrd->tid_data[sta_id][tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); + iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id); tid_data = &trans->shrd->tid_data[sta_id][tid]; if (tid_data->tfds_in_queue == 0) { @@ -564,24 +567,26 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); iwlagn_tx_queue_stop_scheduler(trans, txq_id); iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); - priv(trans)->txq[txq_id].q.read_ptr = 0; - priv(trans)->txq[txq_id].q.write_ptr = 0; + trans_pcie->txq[txq_id].q.read_ptr = 0; + trans_pcie->txq[txq_id].q.write_ptr = 0; /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl_trans_set_wr_ptrs(trans, txq_id, 0); iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv(trans), txq_id); - iwl_trans_tx_queue_set_status(trans, &priv(trans)->txq[txq_id], 0, 0); + iwl_txq_ctx_deactivate(trans_pcie, txq_id); + iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); } int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; int read_ptr, write_ptr; struct iwl_tid_data *tid_data; @@ -621,8 +626,8 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, "or starting\n"); } - write_ptr = priv(trans)->txq[txq_id].q.write_ptr; - read_ptr = priv(trans)->txq[txq_id].q.read_ptr; + write_ptr = trans_pcie->txq[txq_id].q.write_ptr; + read_ptr = trans_pcie->txq[txq_id].q.read_ptr; /* The queue is not empty */ if (write_ptr != read_ptr) { @@ -663,7 +668,8 @@ turn_off: */ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - struct iwl_tx_queue *txq = &priv(trans)->txq[trans->shrd->cmd_queue]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -852,7 +858,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) */ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) { - struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans(priv)); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct iwl_queue *q = &txq->q; int nfreed = 0; @@ -893,7 +901,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_trans *trans = trans(priv); - struct iwl_tx_queue *txq = &priv->txq[trans->shrd->cmd_queue]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; unsigned long flags; /* If a Tx command is being handled and it isn't in the actual @@ -902,8 +911,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) if (WARN(txq_id != trans->shrd->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", txq_id, trans->shrd->cmd_queue, sequence, - priv->txq[trans->shrd->cmd_queue].q.read_ptr, - priv->txq[trans->shrd->cmd_queue].q.write_ptr)) { + trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr, + trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) { iwl_print_hex_error(priv, pkt, 32); return; } @@ -1072,6 +1081,7 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int cmd_idx; int ret; @@ -1144,7 +1154,7 @@ cancel: * in later, it will possibly set an invalid * address (cmd->meta.source). */ - priv(trans)->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= + trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: @@ -1181,7 +1191,8 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, struct sk_buff_head *skbs) { - struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct iwl_queue *q = &txq->q; int last_to_free; int freed = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index cce57d53f618..cec13adb018e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -409,8 +409,8 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, */ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) { - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct iwl_queue *q = &txq->q; if (!q->n_bd) @@ -433,8 +433,8 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) */ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) { - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct device *dev = bus(trans)->dev; int i; if (WARN_ON(!txq)) @@ -477,19 +477,17 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) { int txq_id; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_priv *priv = priv(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Tx queues */ - if (priv->txq) { + if (trans_pcie->txq) { for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) iwl_tx_queue_free(trans, txq_id); } - kfree(priv->txq); - priv->txq = NULL; + kfree(trans_pcie->txq); + trans_pcie->txq = NULL; iwlagn_free_dma_ptr(trans, &trans_pcie->kw); @@ -507,16 +505,14 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) { int ret; int txq_id, slots_num; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ - if (WARN_ON(priv->txq)) { + if (WARN_ON(trans_pcie->txq)) { ret = -EINVAL; goto error; } @@ -535,9 +531,9 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) goto error; } - priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * + trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) * hw_params(trans).max_txq_num, GFP_KERNEL); - if (!priv->txq) { + if (!trans_pcie->txq) { IWL_ERR(trans, "Not enough memory for txq\n"); ret = ENOMEM; goto error; @@ -547,8 +543,8 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { slots_num = (txq_id == trans->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_alloc(trans, &priv->txq[txq_id], slots_num, - txq_id); + ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], + slots_num, txq_id); if (ret) { IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); goto error; @@ -568,11 +564,9 @@ static int iwl_tx_init(struct iwl_trans *trans) int txq_id, slots_num; unsigned long flags; bool alloc = false; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!priv->txq) { + if (!trans_pcie->txq) { ret = iwl_trans_tx_alloc(trans); if (ret) goto error; @@ -594,8 +588,8 @@ static int iwl_tx_init(struct iwl_trans *trans) for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { slots_num = (txq_id == trans->shrd->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_init(trans, &priv->txq[txq_id], slots_num, - txq_id); + ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], + slots_num, txq_id); if (ret) { IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); goto error; @@ -916,14 +910,15 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + memset(&trans_pcie->queue_stopped[0], 0, + sizeof(trans_pcie->queue_stopped)); for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); + atomic_set(&trans_pcie->queue_stop_count[i], 0); for_each_context(priv, ctx) ctx->last_tx_rejected = false; /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; + trans_pcie->txq_ctx_active_msk = 0; BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < IWLAGN_FIRST_AMPDU_QUEUE); @@ -934,14 +929,15 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) int fifo = queue_to_fifo[i].fifo; int ac = queue_to_fifo[i].ac; - iwl_txq_ctx_activate(priv, i); + iwl_txq_ctx_activate(trans_pcie, i); if (fifo == IWL_TX_FIFO_UNUSED) continue; if (ac != IWL_AC_UNSET) - iwl_set_swq_id(&priv->txq[i], ac, i); - iwl_trans_tx_queue_set_status(trans, &priv->txq[i], fifo, 0); + iwl_set_swq_id(&trans_pcie->txq[i], ac, i); + iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], + fifo, 0); } spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -958,7 +954,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) { int ch, txq_id; unsigned long flags; - struct iwl_priv *priv = priv(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&trans->shrd->lock, flags); @@ -979,7 +975,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) } spin_unlock_irqrestore(&trans->shrd->lock, flags); - if (!priv->txq) { + if (!trans_pcie->txq) { IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); return 0; } @@ -1108,7 +1104,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, } } - txq = &priv(trans)->txq[txq_id]; + txq = &trans_pcie->txq[txq_id]; q = &txq->q; /* Set up driver data for this TFD */ @@ -1268,7 +1264,8 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) static int iwlagn_txq_check_empty(struct iwl_trans *trans, int sta_id, u8 tid, int txq_id) { - struct iwl_queue *q = &priv(trans)->txq[txq_id].q; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_queue *q = &trans_pcie->txq[txq_id].q; struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; lockdep_assert_held(&trans->shrd->sta_lock); @@ -1286,7 +1283,7 @@ static int iwlagn_txq_check_empty(struct iwl_trans *trans, iwl_stop_tx_ba_trans_ready(priv(trans), NUM_IWL_RXON_CTX, sta_id, tid); - iwl_wake_queue(trans, &priv(trans)->txq[txq_id]); + iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); } break; case IWL_EMPTYING_HW_QUEUE_ADDBA: @@ -1324,13 +1321,16 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs) { - struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; /* n_bd is usually 256 => n_bd - 1 = 0xff */ int tfd_num = ssn & (txq->q.n_bd - 1); int freed = 0; u8 agg_state; bool cond; + txq->time_stamp = jiffies; + if (txq->sched_retry) { agg_state = trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; @@ -1421,9 +1421,9 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, txq_id = trans_pcie->ac_to_queue[ctx][ac]; IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", ac, - (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0) + (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) ? "stopped" : "awake"); - iwl_wake_queue(trans, &priv(trans)->txq[txq_id]); + iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); } } @@ -1448,13 +1448,16 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) { - iwl_stop_queue(trans, &priv(trans)->txq[txq_id]); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + iwl_stop_queue(trans, &trans_pcie->txq[txq_id]); } #define IWL_FLUSH_WAIT_MS 2000 static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq; struct iwl_queue *q; int cnt; @@ -1465,7 +1468,7 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { if (cnt == trans->shrd->cmd_queue) continue; - txq = &priv(trans)->txq[cnt]; + txq = &trans_pcie->txq[cnt]; q = &txq->q; while (q->read_ptr != q->write_ptr && !time_after(jiffies, now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) @@ -1486,7 +1489,8 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) */ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) { - struct iwl_tx_queue *txq = &priv(trans)->txq[cnt]; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; struct iwl_queue *q = &txq->q; unsigned long timeout; @@ -1578,7 +1582,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, const u8 *ptr; ssize_t ret; - if (!priv->txq) { + if (!trans_pcie->txq) { IWL_ERR(trans, "txq not ready\n"); return -EAGAIN; } @@ -1589,7 +1593,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, } pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - txq = &priv->txq[cnt]; + txq = &trans_pcie->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, "q[%d]: read_ptr: %u, write_ptr: %u\n", @@ -1666,9 +1670,10 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) { - + size_t count, loff_t *ppos) +{ struct iwl_trans *trans = file->private_data; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_priv *priv = priv(trans); struct iwl_tx_queue *txq; struct iwl_queue *q; @@ -1678,7 +1683,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, int ret; const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; - if (!priv->txq) { + if (!trans_pcie->txq) { IWL_ERR(priv, "txq not ready\n"); return -EAGAIN; } @@ -1687,21 +1692,21 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, return -ENOMEM; for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - txq = &priv->txq[cnt]; + txq = &trans_pcie->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, "hwq %.2d: read=%u write=%u stop=%d" " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, q->read_ptr, q->write_ptr, - !!test_bit(cnt, priv->queue_stopped), + !!test_bit(cnt, trans_pcie->queue_stopped), txq->swq_id, txq->swq_id & 3, (txq->swq_id >> 2) & 0x1f); if (cnt >= 4) continue; /* for the ACs, display the stop count too */ pos += scnprintf(buf + pos, bufsz - pos, - " stop-count: %d\n", - atomic_read(&priv->queue_stop_count[cnt])); + " stop-count: %d\n", + atomic_read(&trans_pcie->queue_stop_count[cnt])); } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); From debcf734287a4e15710e6da7add0febca349d5b4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 25 Aug 2011 23:13:56 -0700 Subject: [PATCH 110/129] iwlagn: handle GO powersave In order to implement support for GO powersave on the P2P client side, the ucode needs to know what GO we're trying to authenticate/associate with, it needs to have a station entry and the BSSID in the RXON set. Implement the new mac80211 callbacks to give this data to the device. Since this is also useful for the device when a normal connection is established, also program it with the information in that case. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 ++ drivers/net/wireless/iwlwifi/iwl-agn.c | 68 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 3 + 3 files changed, 76 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index b4d7460f05ca..1af276739d87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -435,6 +435,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (!ctx->is_active) return 0; + /* override BSSID if necessary due to preauth */ + if (ctx->preauth_bssid) + memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN); + /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; @@ -897,6 +901,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, if (!priv->disable_chain_noise_cal) iwlagn_chain_noise_reset(priv); priv->start_calib = 1; + WARN_ON(ctx->preauth_bssid); } if (changes & BSS_CHANGED_IBSS) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a0cf486f7625..8113fbe770a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2956,6 +2956,72 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) return 0; } +static int iwl_mac_tx_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + const u8 *bssid, enum ieee80211_tx_sync_type type) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + struct iwl_rxon_context *ctx = vif_priv->ctx; + int ret; + u8 sta_id; + + mutex_lock(&priv->shrd->mutex); + + if (iwl_is_associated_ctx(ctx)) { + ret = 0; + goto out; + } + + if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + ret = -EBUSY; + goto out; + } + + ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); + if (ret) + goto out; + + if (WARN_ON(sta_id != ctx->ap_sta_id)) { + ret = -EIO; + goto out_remove_sta; + } + + memcpy(ctx->bssid, bssid, ETH_ALEN); + ctx->preauth_bssid = true; + + ret = iwlagn_commit_rxon(priv, ctx); + + if (ret == 0) + goto out; + + out_remove_sta: + iwl_remove_station(priv, sta_id, bssid); + out: + mutex_unlock(&priv->shrd->mutex); + return ret; +} + +static void iwl_mac_finish_tx_sync(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *bssid, + enum ieee80211_tx_sync_type type) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + struct iwl_rxon_context *ctx = vif_priv->ctx; + + mutex_lock(&priv->shrd->mutex); + + if (iwl_is_associated_ctx(ctx)) + goto out; + + iwl_remove_station(priv, ctx->ap_sta_id, bssid); + ctx->preauth_bssid = false; + /* no need to commit */ + out: + mutex_unlock(&priv->shrd->mutex); +} + /***************************************************************************** * * driver setup and teardown @@ -3164,6 +3230,8 @@ struct ieee80211_ops iwlagn_hw_ops = { .rssi_callback = iwl_mac_rssi_callback, CFG80211_TESTMODE_CMD(iwl_testmode_cmd) CFG80211_TESTMODE_DUMP(iwl_testmode_dump) + .tx_sync = iwl_mac_tx_sync, + .finish_tx_sync = iwl_mac_finish_tx_sync, }; static u32 iwl_hw_detect(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 33a829ad7e2a..1e54293532b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -992,6 +992,9 @@ struct iwl_rxon_context { u8 extension_chan_offset; } ht; + u8 bssid[ETH_ALEN]; + bool preauth_bssid; + bool last_tx_rejected; }; From 1eb85d63c73d924c172bde059ad8b0192abd74a4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 26 Aug 2011 14:34:59 +0800 Subject: [PATCH 111/129] p54spi: add "spi:" prefix for stlc45xx modalias Since commit e0626e38 (spi: prefix modalias with "spi:"), the spi modalias is prefixed with "spi:". This patch adds "spi:" prefix for modalias of stlc45xx. Also move it to be group with other modalias. Signed-off-by: Axel Lin Acked-By: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 6d9204fef90b..f18df82eeb92 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -41,7 +41,6 @@ #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ MODULE_FIRMWARE("3826.arm"); -MODULE_ALIAS("stlc45xx"); /* * gpios should be handled in board files and provided via platform data, @@ -738,3 +737,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter "); MODULE_ALIAS("spi:cx3110x"); MODULE_ALIAS("spi:p54spi"); +MODULE_ALIAS("spi:stlc45xx"); From 996bc370fa5f28f0a07d6c8dee26591db2f3dea9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 26 Aug 2011 20:41:38 +0200 Subject: [PATCH 112/129] b43: Relax requirement for descriptors to be in the DMA zone When 64-bit DMA was first used, there were problems with the BCM4311 (14e4:4311). The problem was "fixed" by using the GFP_DMA flag in the allocation of coherent ring descriptor memory. The original problem is now believed to have been due to bugs in the 64-bit DMA implementation in the rest of the kernel, and that those bugs have been fixed. Accordingly, the requirement for the descriptors to be in the DMA zone is relaxed. Bounce buffers are left in the DMA zone. Signed-off-by: Larry Finger Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index e76b40ddbc48..c83c4b64c60e 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -423,14 +423,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) * has shown that 4K is sufficient for the latter as long as the buffer * does not cross an 8K boundary. * - * For unknown reasons - possibly a hardware error - the BCM4311 rev - * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, - * which accounts for the GFP_DMA flag below. - * - * The flags here must match the flags in free_ringmemory below! */ - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, &(ring->dmabase), flags); From 14a8083e67653a963bb53f905044c23593026737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 26 Aug 2011 20:41:39 +0200 Subject: [PATCH 113/129] b43: use 8K buffers for 64-bit DMA to workaround hardware bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 24 ++++++++++++++++-------- drivers/net/wireless/b43/dma.h | 3 ++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index c83c4b64c60e..975d96040548 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -419,26 +419,34 @@ static int alloc_ringmemory(struct b43_dmaring *ring) gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K - * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing - * has shown that 4K is sufficient for the latter as long as the buffer - * does not cross an 8K boundary. - * + * alignment and 8K buffers for 64-bit DMA with 8K alignment. + * In practice we could use smaller buffers for the latter, but the + * alignment is really important because of the hardware bug. If bit + * 0x00001000 is used in DMA address, some hardware (like BCM4331) + * copies that bit into B43_DMA64_RXSTATUS and we get false values from + * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use + * more than 256 slots for ring. */ + u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? + B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, - B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); + ring_mem_size, &(ring->dmabase), + flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; } - memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); + memset(ring->descbase, 0, ring_mem_size); return 0; } static void free_ringmemory(struct b43_dmaring *ring) { - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, + u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? + B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; + dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size, ring->descbase, ring->dmabase); } diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 7e20b04fa51a..315b96ed1d90 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -161,7 +161,8 @@ struct b43_dmadesc_generic { } __packed; /* Misc DMA constants */ -#define B43_DMA_RINGMEMSIZE PAGE_SIZE +#define B43_DMA32_RINGMEMSIZE 4096 +#define B43_DMA64_RINGMEMSIZE 8192 /* Offset of frame with actual data */ #define B43_DMA0_RX_FW598_FO 38 #define B43_DMA0_RX_FW351_FO 30 From 547589668336d6cf25c2023173d5d2c25fb7bc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 26 Aug 2011 20:41:40 +0200 Subject: [PATCH 114/129] b43: make HT-PHY support experimental MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was tested on three BCM4331 devices, code has been written from MMIO dumps only, but seems to be quite stable. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index df2b7c0856ed..b97a40ed5fff 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -124,12 +124,12 @@ config B43_PHY_LP (802.11a support is optional, and currently disabled). config B43_PHY_HT - bool "Support for HT-PHY devices (BROKEN)" - depends on B43 && BROKEN + bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)" + depends on B43 && EXPERIMENTAL ---help--- Support for the HT-PHY. - Say N, this is BROKEN and crashes driver. + Enables support for BCM4331 and possibly other chipsets with that PHY. config B43_PHY_LCN bool "Support for LCN-PHY devices (BROKEN)" From e3f2acc76dbae64d1b08455bbbaa855141d0238d Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 27 Aug 2011 11:22:59 +0530 Subject: [PATCH 115/129] ath9k_hw: Set default slottime as 9us Initialize 9us slot time as that is what is used mostly (for non-ERP cases) and also to be in sync with initvals. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7bfc8f65a67d..4ba0ee91d43a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -440,7 +440,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) if (AR_SREV_9100(ah)) ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = 20; + ah->slottime = ATH9K_SLOT_TIME_9; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; } From a7be039d347743c289b7280d5de82abf7bbdf1d8 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 27 Aug 2011 12:13:21 +0530 Subject: [PATCH 116/129] ath9k: Fix eifs/usec timeout for AR9287 v1.3+ For AR9287 v1.3+ chips, MAC runs at 117MHz. But the initvals IFS parameters are loaded based on 44/88MHz clockrate. So eifs/usec from ini should not be used for AR9287 v1.3+. The mentioned values are tested on 2 chain HT40 mode. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++-- drivers/net/wireless/ath/ath9k/reg.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4ba0ee91d43a..3a16ba256ef9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -997,8 +997,14 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) slottime = 21; sifstime = 64; } else { - eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate; - reg = REG_READ(ah, AR_USEC); + if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { + eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO; + reg = AR_USEC_ASYNC_FIFO; + } else { + eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/ + common->clockrate; + reg = REG_READ(ah, AR_USEC); + } rx_lat = MS(reg, AR_USEC_RX_LAT); tx_lat = MS(reg, AR_USEC_TX_LAT); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index a3b8bbc6c063..17a272f4d8d6 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -619,6 +619,7 @@ #define AR_D_GBL_IFS_EIFS 0x10b0 #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 +#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363 #define AR_D_GBL_IFS_MISC 0x10f0 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 @@ -1503,6 +1504,7 @@ enum { #define AR_USEC_TX_LAT_S 14 #define AR_USEC_RX_LAT 0x1F800000 #define AR_USEC_RX_LAT_S 23 +#define AR_USEC_ASYNC_FIFO 0x12E00074 #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 From 059ee09b99942bf64f4075196a7a2a992e64193d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 27 Aug 2011 10:25:27 +0200 Subject: [PATCH 117/129] ath9k: fix regression in sending aggregated packets The recent commit "ath9k: Send legacy rated frames as unaggregated" introduced a check to ensure that packets with non-MCS rates set in the rate series will not be aggregated. However, it failed to check if the rate series is valid before testing the flags, thus breaking aggregation for normal MCS-only packets if the last series is unset. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5e2982938ffc..ac393a6dbe77 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -582,7 +582,10 @@ static bool ath_lookup_legacy(struct ath_buf *bf) tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { + if (!rates[i].count || rates[i].idx < 0) + break; + if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) return true; } From cf3af74824b1bf2bd60eb6a0dd82b27f9e9236ac Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 27 Aug 2011 16:17:47 +0530 Subject: [PATCH 118/129] ath9k: Add debugfs support for mac/baseband samples This patch keep track of number of samples that includes DMA debugs registers, PCU observe, CR, channel noise, cycle conters, noisefloor history buffer and last N number of tx and rx descriptor status. These samples are grouped in table manner which dumping in debgufs. Debugfs file location: /ieee80211/phy#/ath9k/samples Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 310 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/debug.h | 47 ++++ drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 2 + drivers/net/wireless/ath/ath9k/recv.c | 22 +- 6 files changed, 369 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index da45f325be7d..fbec5f7eca6e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -828,6 +828,8 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq) { +#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ + [sc->debug.tsidx].c) int qnum = txq->axq_qnum; TX_STAT_INC(qnum, tx_pkts_all); @@ -857,6 +859,26 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); + + spin_lock(&sc->debug.samp_lock); + TX_SAMP_DBG(jiffies) = jiffies; + TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; + TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1; + TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2; + TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0; + TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1; + TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2; + TX_SAMP_DBG(rateindex) = ts->ts_rateindex; + TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK); + TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry; + TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry; + TX_SAMP_DBG(rssi) = ts->ts_rssi; + TX_SAMP_DBG(tid) = ts->tid; + TX_SAMP_DBG(qid) = ts->qid; + sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; + spin_unlock(&sc->debug.samp_lock); + +#undef TX_SAMP_DBG } static const struct file_operations fops_xmit = { @@ -995,6 +1017,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ +#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ + [sc->debug.rsidx].c) u32 phyerr; @@ -1030,8 +1054,25 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; + spin_lock(&sc->debug.samp_lock); + RX_SAMP_DBG(jiffies) = jiffies; + RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; + RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1; + RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2; + RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0; + RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1; + RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2; + RX_SAMP_DBG(antenna) = rs->rs_antenna; + RX_SAMP_DBG(rssi) = rs->rs_rssi; + RX_SAMP_DBG(rate) = rs->rs_rate; + RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon; + + sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES; + spin_unlock(&sc->debug.samp_lock); + #undef RX_STAT_INC #undef RX_PHY_ERR_INC +#undef RX_SAMP_DBG } static const struct file_operations fops_recv = { @@ -1272,6 +1313,269 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; +void ath9k_debug_samp_bb_mac(struct ath_softc *sc) +{ +#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + unsigned long flags; + int i; + + ath9k_ps_wakeup(sc); + + spin_lock_irqsave(&common->cc_lock, flags); + ath_hw_cycle_counters_update(common); + spin_unlock_irqrestore(&common->cc_lock, flags); + + spin_lock_bh(&sc->debug.samp_lock); + + ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles; + ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy; + ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame; + ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame; + ATH_SAMP_DBG(noise) = ah->noise; + + REG_WRITE_D(ah, AR_MACMISC, + ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | + (AR_MACMISC_MISC_OBS_BUS_1 << + AR_MACMISC_MISC_OBS_BUS_MSB_S))); + + for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) + ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah, + AR_DMADBG_0 + (i * sizeof(u32))); + + ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1); + ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR); + + memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist, + sizeof(ATH_SAMP_DBG(nfCalHist))); + + sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES; + spin_unlock_bh(&sc->debug.samp_lock); + ath9k_ps_restore(sc); + +#undef ATH_SAMP_DBG +} + +static int open_file_bb_mac_samps(struct inode *inode, struct file *file) +{ +#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c + struct ath_softc *sc = inode->i_private; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; + struct ath_dbg_bb_mac_samp *bb_mac_samp; + struct ath9k_nfcal_hist *h; + int i, j, qcuOffset = 0, dcuOffset = 0; + u32 *qcuBase, *dcuBase, size = 30000, len = 0; + u32 sampidx = 0; + u8 *buf; + u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; + u8 nread; + + buf = vmalloc(size); + if (!buf) + return -ENOMEM; + bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); + if (!bb_mac_samp) { + vfree(buf); + return -ENOMEM; + } + + spin_lock_bh(&sc->debug.samp_lock); + memcpy(bb_mac_samp, sc->debug.bb_mac_samp, + sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); + spin_unlock_bh(&sc->debug.samp_lock); + + len += snprintf(buf + len, size - len, + "Raw DMA Debug Dump:\n"); + len += snprintf(buf + len, size - len, "Sample |\t"); + for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) + len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i); + len += snprintf(buf + len, size - len, "\n"); + + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + len += snprintf(buf + len, size - len, "%d\t", sampidx); + + for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) + len += snprintf(buf + len, size - len, " %08x\t", + ATH_SAMP_DBG(dma_dbg_reg_vals[i])); + len += snprintf(buf + len, size - len, "\n"); + } + len += snprintf(buf + len, size - len, "\n"); + + len += snprintf(buf + len, size - len, + "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); + dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); + + for (i = 0; i < ATH9K_NUM_QUEUES; i++, + qcuOffset += 4, dcuOffset += 5) { + if (i == 8) { + qcuOffset = 0; + qcuBase++; + } + + if (i == 6) { + dcuOffset = 0; + dcuBase++; + } + if (!sc->debug.stats.txstats[i].queued) + continue; + + len += snprintf(buf + len, size - len, + "%4d %7d %2x %1x %2x %2x\n", + sampidx, i, + (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, + (*qcuBase & (0x8 << qcuOffset)) >> + (qcuOffset + 3), + ATH_SAMP_DBG(dma_dbg_reg_vals[2]) & + (0x7 << (i * 3)) >> (i * 3), + (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); + } + len += snprintf(buf + len, size - len, "\n"); + } + len += snprintf(buf + len, size - len, + "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp " + "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 " + "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n"); + + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); + dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); + + len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx, + (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18, + (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22); + len += snprintf(buf + len, size - len, "%7x %8x ", + (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26, + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3)); + len += snprintf(buf + len, size - len, "%7x %7x ", + (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25, + (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27); + len += snprintf(buf + len, size - len, "%7d %12d ", + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2, + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10); + len += snprintf(buf + len, size - len, "%12d %12d ", + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11, + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12); + len += snprintf(buf + len, size - len, "%12d %12d ", + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13, + (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17); + len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n", + ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr)); + } + + len += snprintf(buf + len, size - len, + "Sample ChNoise Chain privNF #Reading Readings\n"); + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + h = ATH_SAMP_DBG(nfCalHist); + if (!ATH_SAMP_DBG(noise)) + continue; + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (!(chainmask & (1 << i)) || + ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) + continue; + + nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - + h[i].invalidNFcount; + len += snprintf(buf + len, size - len, + "%4d %5d %4d\t %d\t %d\t", + sampidx, ATH_SAMP_DBG(noise), + i, h[i].privNF, nread); + for (j = 0; j < nread; j++) + len += snprintf(buf + len, size - len, + " %d", h[i].nfCalBuffer[j]); + len += snprintf(buf + len, size - len, "\n"); + } + } + len += snprintf(buf + len, size - len, "\nCycle counters:\n" + "Sample Total Rxbusy Rxframes Txframes\n"); + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + if (!ATH_SAMP_DBG(cc.cycles)) + continue; + len += snprintf(buf + len, size - len, + "%4d %08x %08x %08x %08x\n", + sampidx, ATH_SAMP_DBG(cc.cycles), + ATH_SAMP_DBG(cc.rx_busy), + ATH_SAMP_DBG(cc.rx_frame), + ATH_SAMP_DBG(cc.tx_frame)); + } + + len += snprintf(buf + len, size - len, "Tx status Dump :\n"); + len += snprintf(buf + len, size - len, + "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " + "isok rts_fail data_fail rate tid qid tx_before(ms)\n"); + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { + if (!ATH_SAMP_DBG(ts[i].jiffies)) + continue; + len += snprintf(buf + len, size - len, "%4d \t" + "%8d %4d %4d %4d %4d %4d %4d %4d %4d " + "%4d %4d %2d %2d %d\n", + sampidx, + ATH_SAMP_DBG(ts[i].rssi_ctl0), + ATH_SAMP_DBG(ts[i].rssi_ctl1), + ATH_SAMP_DBG(ts[i].rssi_ctl2), + ATH_SAMP_DBG(ts[i].rssi_ext0), + ATH_SAMP_DBG(ts[i].rssi_ext1), + ATH_SAMP_DBG(ts[i].rssi_ext2), + ATH_SAMP_DBG(ts[i].rssi), + ATH_SAMP_DBG(ts[i].isok), + ATH_SAMP_DBG(ts[i].rts_fail_cnt), + ATH_SAMP_DBG(ts[i].data_fail_cnt), + ATH_SAMP_DBG(ts[i].rateindex), + ATH_SAMP_DBG(ts[i].tid), + ATH_SAMP_DBG(ts[i].qid), + jiffies_to_msecs(jiffies - + ATH_SAMP_DBG(ts[i].jiffies))); + } + } + + len += snprintf(buf + len, size - len, "Rx status Dump :\n"); + len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 " + "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n"); + for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { + for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { + if (!ATH_SAMP_DBG(rs[i].jiffies)) + continue; + len += snprintf(buf + len, size - len, "%4d \t" + "%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n", + sampidx, + ATH_SAMP_DBG(rs[i].rssi_ctl0), + ATH_SAMP_DBG(rs[i].rssi_ctl1), + ATH_SAMP_DBG(rs[i].rssi_ctl2), + ATH_SAMP_DBG(rs[i].rssi_ext0), + ATH_SAMP_DBG(rs[i].rssi_ext1), + ATH_SAMP_DBG(rs[i].rssi_ext2), + ATH_SAMP_DBG(rs[i].rssi), + ATH_SAMP_DBG(rs[i].is_mybeacon) ? + "True" : "False", + ATH_SAMP_DBG(rs[i].antenna), + ATH_SAMP_DBG(rs[i].rate), + jiffies_to_msecs(jiffies - + ATH_SAMP_DBG(rs[i].jiffies))); + } + } + + vfree(bb_mac_samp); + file->private_data = buf; + + return 0; +#undef ATH_SAMP_DBG +} + +static const struct file_operations fops_samps = { + .open = open_file_bb_mac_samps, + .read = ath9k_debugfs_read_buf, + .release = ath9k_debugfs_release_buf, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + + int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1321,6 +1625,8 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_base_eeprom); debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_modal_eeprom); + debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_samps); debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); @@ -1329,5 +1635,9 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); sc->debug.regidx = 0; + memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp)); + sc->debug.sampidx = 0; + sc->debug.tsidx = 0; + sc->debug.rsidx = 0; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 4a04510e1111..95f85bdc8db7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -177,14 +177,57 @@ struct ath_stats { struct ath_rx_stats rxstats; }; +#define ATH_DBG_MAX_SAMPLES 10 +struct ath_dbg_bb_mac_samp { + u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS]; + u32 pcu_obs, pcu_cr, noise; + struct { + u64 jiffies; + int8_t rssi_ctl0; + int8_t rssi_ctl1; + int8_t rssi_ctl2; + int8_t rssi_ext0; + int8_t rssi_ext1; + int8_t rssi_ext2; + int8_t rssi; + bool isok; + u8 rts_fail_cnt; + u8 data_fail_cnt; + u8 rateindex; + u8 qid; + u8 tid; + } ts[ATH_DBG_MAX_SAMPLES]; + struct { + u64 jiffies; + int8_t rssi_ctl0; + int8_t rssi_ctl1; + int8_t rssi_ctl2; + int8_t rssi_ext0; + int8_t rssi_ext1; + int8_t rssi_ext2; + int8_t rssi; + bool is_mybeacon; + u8 antenna; + u8 rate; + } rs[ATH_DBG_MAX_SAMPLES]; + struct ath_cycle_counters cc; + struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; +}; + struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; struct ath_stats stats; + spinlock_t samp_lock; + struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; + u8 sampidx; + u8 tsidx; + u8 rsidx; }; int ath9k_init_debug(struct ath_hw *ah); +void ath9k_debug_samp_bb_mac(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq); @@ -197,6 +240,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } +static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) +{ +} + static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d7761d1fc5ba..dd71a5f77516 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -572,6 +572,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); + spin_lock_init(&sc->debug.samp_lock); INIT_LIST_HEAD(&sc->nodes); #endif tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 153859ccc2a1..2c43e13da002 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -146,6 +146,7 @@ struct ath_rx_status { u8 rs_moreaggr; u8 rs_num_delims; u8 rs_flags; + bool is_mybeacon; u32 evm0; u32 evm1; u32 evm2; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 5ac4f3f2ad60..7b7864dfab75 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -546,6 +546,7 @@ set_timer: * The interval must be the shortest necessary to satisfy ANI, * short calibration and long calibration. */ + ath9k_debug_samp_bb_mac(sc); cal_interval = ATH_LONG_CALINTERVAL; if (sc->sc_ah->config.enable_ani) cal_interval = min(cal_interval, @@ -978,6 +979,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) sc->hw_busy_count = 0; + ath9k_debug_samp_bb_mac(sc); /* Stop ANI */ del_timer_sync(&common->ani.timer); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 800e9ee7e035..9c7f905f3871 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -952,23 +952,12 @@ static void ath9k_process_rssi(struct ath_common *common, struct ath_softc *sc = hw->priv; struct ath_hw *ah = common->ah; int last_rssi; - __le16 fc; - if ((ah->opmode != NL80211_IFTYPE_STATION) && - (ah->opmode != NL80211_IFTYPE_ADHOC)) + if (!rx_stats->is_mybeacon || + ((ah->opmode != NL80211_IFTYPE_STATION) && + (ah->opmode != NL80211_IFTYPE_ADHOC))) return; - fc = hdr->frame_control; - if (!ieee80211_is_beacon(fc) || - compare_ether_addr(hdr->addr3, common->curbssid)) { - /* TODO: This doesn't work well if you have stations - * associated to two different APs because curbssid - * is just the last AP that any of the stations associated - * with. - */ - return; - } - if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); @@ -1838,6 +1827,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); rxs = IEEE80211_SKB_RXCB(hdr_skb); + if (ieee80211_is_beacon(hdr->frame_control) && + !compare_ether_addr(hdr->addr3, common->curbssid)) + rs.is_mybeacon = true; + else + rs.is_mybeacon = false; ath_debug_stat_rx(sc, &rs); From 1ba45b9e3a366fee0603cda51e61935b7dc9db7d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 27 Aug 2011 13:56:00 -0500 Subject: [PATCH 119/129] ath9k: Fix a smatch warnings Smatch shows the following warnings: CHECK drivers/net/wireless/ath/ath9k/htc_drv_main.c drivers/net/wireless/ath/ath9k/htc_drv_main.c +1315 ath9k_htc_configure_filter(27) warn: inconsistent returns mutex:&priv->mutex: locked (1303) unlocked (1315) CHECK drivers/net/wireless/ath/ath9k/ar9003_eeprom.c drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +3321 ar9300_eeprom_restore_internal(20) warn: returning -1 instead of -ENOMEM is sloppy Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 908463915b99..cb4c32eaef61 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3318,7 +3318,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, word = kzalloc(2048, GFP_KERNEL); if (!word) - return -1; + return -ENOMEM; memcpy(mptr, &ar9300_default, mdata_size); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0248024da56a..b9de1511add9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1300,6 +1300,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, if (priv->op_flags & OP_INVALID) { ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, "Unable to configure filter on invalid state\n"); + mutex_unlock(&priv->mutex); return; } ath9k_htc_ps_wakeup(priv); From 9a53bf54b8149bc1372f50a83b769f42772083ea Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 27 Aug 2011 15:53:42 -0500 Subject: [PATCH 120/129] b43: Fix swatch warning Swatch reports the following warning for main.c: CHECK drivers/net/wireless/b43/main.c drivers/net/wireless/b43/main.c +4115 b43_wireless_core_stop(7) warn: variable dereferenced before check 'dev' After analysis, this is not a bug, but a false warning. Nonetheless, a cleanup is in order to prevent some future janitor proposing the wrong fix, as I did in my original patch. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d2b1d1fe202b..172294170df8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4131,10 +4131,13 @@ out_unlock: * because the core might be gone away while we unlocked the mutex. */ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) { - struct b43_wl *wl = dev->wl; + struct b43_wl *wl; struct b43_wldev *orig_dev; u32 mask; + if (!dev) + return NULL; + wl = dev->wl; redo: if (!dev || b43_status(dev) < B43_STAT_STARTED) return dev; From 78b8e51dd93a36df55a1c9aacbf6c16361a98cbd Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 29 Aug 2011 15:47:58 -0400 Subject: [PATCH 121/129] wl12xx/sdio_test.c: fix build breakage from WL127X_FW_NAME change Commit c302b2c959164622558474871ae942da0e484a38 ("wl12xx: Use a single fw for both STA and AP roles") changed the name of the firmware name definition, breaking the build of wl12xx/sdio_test.c. Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/sdio_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index f28915392877..c3610492852e 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -193,7 +193,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ret = request_firmware(&fw, WL128X_FW_NAME, wl1271_wl_to_dev(wl)); else - ret = request_firmware(&fw, WL1271_FW_NAME, + ret = request_firmware(&fw, WL127X_FW_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { From 7b8112d6db0cc67dd2a722ca5bf707768890ac9d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 26 Aug 2011 01:56:38 -0700 Subject: [PATCH 122/129] ath: Make ath_dbg void not int The return value is never used so make it void. Reduces object size a tiny bit. $ size drivers/net/wireless/ath/built-in.o* text data bss dec hex filename 1164175 16235 212032 1392442 153f3a drivers/net/wireless/ath/built-in.o.new 1164819 16235 212032 1393086 1541be drivers/net/wireless/ath/built-in.o.old Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 17c4b56c3874..a3f8505c712b 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -178,8 +178,9 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); -extern __attribute__ ((format (printf, 3, 4))) int -ath_printk(const char *level, struct ath_common *common, const char *fmt, ...); +extern __attribute__((format (printf, 3, 4))) +int ath_printk(const char *level, struct ath_common *common, + const char *fmt, ...); #define ath_emerg(common, fmt, ...) \ ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) @@ -246,27 +247,21 @@ enum ATH_DEBUG { #ifdef CONFIG_ATH_DEBUG -#define ath_dbg(common, dbg_mask, fmt, ...) \ -({ \ - int rtn; \ - if ((common)->debug_mask & dbg_mask) \ - rtn = ath_printk(KERN_DEBUG, common, fmt, \ - ##__VA_ARGS__); \ - else \ - rtn = 0; \ - \ - rtn; \ -}) +#define ath_dbg(common, dbg_mask, fmt, ...) \ +do { \ + if ((common)->debug_mask & dbg_mask) \ + ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ +} while (0) + #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) #else -static inline __attribute__ ((format (printf, 3, 4))) int -ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, - const char *fmt, ...) +static inline __attribute__((format (printf, 3, 4))) +void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, + const char *fmt, ...) { - return 0; } #define ATH_DBG_WARN(foo, arg...) do {} while (0) #define ATH_DBG_WARN_ON_ONCE(foo) ({ \ From 29e76245d46ff530bb2b0311e9fc823fc07b1147 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 26 Aug 2011 01:56:39 -0700 Subject: [PATCH 123/129] ath: Make ath_printk void not int and remove unused struct ath_common * Changing the return type and removing the unused argument from ath_printk reduces code size. Add an __always_unused struct ath_common * to the macros that call ath_printk to avoid unused variable warnings. $ size drivers/net/wireless/ath/built-in.o* text data bss dec hex filename 1159859 16235 212000 1388094 152e3e drivers/net/wireless/ath/built-in.o.new 1164175 16235 212032 1392442 153f3a drivers/net/wireless/ath/built-in.o.old Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 27 ++++++++++++++++----------- drivers/net/wireless/ath/main.c | 8 ++------ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index a3f8505c712b..9891fb605a01 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -178,24 +178,29 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); -extern __attribute__((format (printf, 3, 4))) -int ath_printk(const char *level, struct ath_common *common, - const char *fmt, ...); +extern __attribute__((format (printf, 2, 3))) +void ath_printk(const char *level, const char *fmt, ...); + +#define _ath_printk(level, common, fmt, ...) \ +do { \ + __always_unused struct ath_common *unused = common; \ + ath_printk(level, fmt, ##__VA_ARGS__); \ +} while (0) #define ath_emerg(common, fmt, ...) \ - ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) #define ath_alert(common, fmt, ...) \ - ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) #define ath_crit(common, fmt, ...) \ - ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) #define ath_err(common, fmt, ...) \ - ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) #define ath_warn(common, fmt, ...) \ - ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) #define ath_notice(common, fmt, ...) \ - ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) #define ath_info(common, fmt, ...) \ - ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) + _ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) /** * enum ath_debug_level - atheros wireless debug level @@ -250,7 +255,7 @@ enum ATH_DEBUG { #define ath_dbg(common, dbg_mask, fmt, ...) \ do { \ if ((common)->debug_mask & dbg_mask) \ - ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ + _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ } while (0) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index c325202fdc5f..d9218fe02036 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c @@ -57,22 +57,18 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, } EXPORT_SYMBOL(ath_rxbuf_alloc); -int ath_printk(const char *level, struct ath_common *common, - const char *fmt, ...) +void ath_printk(const char *level, const char *fmt, ...) { struct va_format vaf; va_list args; - int rtn; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - rtn = printk("%sath: %pV", level, &vaf); + printk("%sath: %pV", level, &vaf); va_end(args); - - return rtn; } EXPORT_SYMBOL(ath_printk); From a75c0629716ea19ff934ef4ff1c31a4610bcb408 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 28 Aug 2011 00:32:21 +0200 Subject: [PATCH 124/129] ath9k: use u8 for the tx key index This saves some space in struct ath_frame_info Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 2 +- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 2 +- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 2 +- drivers/net/wireless/ath/ath9k/mac.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 45b262fe2c25..33deb0d574b0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u32 keyIx, + u32 txPower, u8 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar5416_desc *ads = AR5416DESC(ds); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 8ace36e77399..d08ab930e430 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktlen, enum ath9k_pkt_type type, u32 txpower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags) + u8 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar9003_txc *ads = (struct ar9003_txc *) ds; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3a893e19d6c3..d961f11201e9 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -207,8 +207,8 @@ struct ath_atx_ac { struct ath_frame_info { int framelen; - u32 keyix; enum ath9k_key_type keytype; + u8 keyix; u8 retries; u16 seqno; }; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 3aa3fb191775..c8af86c795e5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -623,7 +623,7 @@ struct ath_hw_ops { struct ath_tx_status *ts); void (*set11n_txdesc)(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u32 keyIx, + u32 txPower, u8 keyIx, enum ath9k_key_type keyType, u32 flags); void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 2c43e13da002..acb83bfd05a0 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -195,7 +195,7 @@ struct ath_htc_rx_status { #define ATH9K_RX_DECRYPT_BUSY 0x40 #define ATH9K_RXKEYIX_INVALID ((u8)-1) -#define ATH9K_TXKEYIX_INVALID ((u32)-1) +#define ATH9K_TXKEYIX_INVALID ((u8)-1) enum ath9k_phyerr { ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ From 56dc63369270b60e59637d153caf2e6b424ca30e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 28 Aug 2011 00:32:22 +0200 Subject: [PATCH 125/129] ath9k: clean up the aggregation tid queue Use a sk_buff_head instead containing skbs instead of a list_head containing ath_bufs. This makes it easier to decouple the aggregation code from the ath_buf struct Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 +- drivers/net/wireless/ath/ath9k/debug.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 77 ++++++++++++++------------ 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d961f11201e9..eb4cdefda629 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -206,6 +206,7 @@ struct ath_atx_ac { }; struct ath_frame_info { + struct ath_buf *bf; int framelen; enum ath9k_key_type keytype; u8 keyix; @@ -235,7 +236,7 @@ struct ath_buf { struct ath_atx_tid { struct list_head list; - struct list_head buf_q; + struct sk_buff_head buf_q; struct ath_node *an; struct ath_atx_ac *ac; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index fbec5f7eca6e..727e8de22fda 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf, " tid: %p %s %s %i %p %p\n", tid, tid->sched ? "sched" : "idle", tid->paused ? "paused" : "running", - list_empty(&tid->buf_q), + skb_queue_empty(&tid->buf_q), tid->an, tid->ac); if (len >= size) goto done; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index ac393a6dbe77..34005e11502c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) spin_lock_bh(&txq->axq_lock); tid->paused = false; - if (list_empty(&tid->buf_q)) + if (skb_queue_empty(&tid->buf_q)) goto unlock; ath_tx_queue_tid(txq, tid); @@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { struct ath_txq *txq = tid->ac->txq; + struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) memset(&ts, 0, sizeof(ts)); spin_lock_bh(&txq->axq_lock); - while (!list_empty(&tid->buf_q)) { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_move_tail(&bf->list, &bf_head); + while ((skb = __skb_dequeue(&tid->buf_q))) { + fi = get_frame_info(skb); + bf = fi->bf; + + list_add_tail(&bf->list, &bf_head); spin_unlock_bh(&txq->axq_lock); - fi = get_frame_info(bf->bf_mpdu); if (fi->retries) { ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); @@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid) { + struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); - for (;;) { - if (list_empty(&tid->buf_q)) - break; + while ((skb = __skb_dequeue(&tid->buf_q))) { + fi = get_frame_info(skb); + bf = fi->bf; - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_move_tail(&bf->list, &bf_head); + list_add_tail(&bf->list, &bf_head); - fi = get_frame_info(bf->bf_mpdu); if (fi->retries) ath_tx_update_baw(sc, tid, fi->seqno); @@ -349,7 +350,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ieee80211_tx_info *tx_info; struct ath_atx_tid *tid = NULL; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct list_head bf_head, bf_pending; + struct list_head bf_head; + struct sk_buff_head bf_pending; u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; @@ -422,8 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } } - INIT_LIST_HEAD(&bf_pending); - INIT_LIST_HEAD(&bf_head); + __skb_queue_head_init(&bf_pending); ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { @@ -467,10 +468,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Make sure the last desc is reclaimed if it * not a holding desc. */ - if (!bf_last->bf_stale || bf_next != NULL) + INIT_LIST_HEAD(&bf_head); + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || + bf_next != NULL || !bf_last->bf_stale) list_move_tail(&bf->list, &bf_head); - else - INIT_LIST_HEAD(&bf_head); if (!txpending || (tid->state & AGGR_CLEANUP)) { /* @@ -521,7 +522,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - list_add_tail(&tbf->list, &bf_head); + fi->bf = tbf; } else { /* * Clear descriptor status words for @@ -536,21 +537,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Put this buffer to the temporary pending * queue to retain ordering */ - list_splice_tail_init(&bf_head, &bf_pending); + __skb_queue_tail(&bf_pending, skb); } bf = bf_next; } /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!list_empty(&bf_pending)) { + if (!skb_queue_empty(&bf_pending)) { if (an->sleeping) ieee80211_sta_set_tim(sta); spin_lock_bh(&txq->axq_lock); if (clear_filter) tid->ac->clear_ps_filter = true; - list_splice(&bf_pending, &tid->buf_q); + skb_queue_splice(&bf_pending, &tid->buf_q); if (!an->sleeping) ath_tx_queue_tid(txq, tid); spin_unlock_bh(&txq->axq_lock); @@ -743,19 +744,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first, *bf_prev = NULL; + struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; int rl = 0, nframes = 0, ndelim, prev_al = 0; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; - - bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); + struct sk_buff *skb; do { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - fi = get_frame_info(bf->bf_mpdu); + skb = skb_peek(&tid->buf_q); + fi = get_frame_info(skb); + bf = fi->bf; + + if (!bf_first) + bf_first = bf; /* do not step over block-ack window */ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { @@ -808,7 +812,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, if (!fi->retries) ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); - list_move_tail(&bf->list, bf_q); + + __skb_unlink(skb, &tid->buf_q); + list_add_tail(&bf->list, bf_q); if (bf_prev) { bf_prev->bf_next = bf; ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, @@ -816,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } bf_prev = bf; - } while (!list_empty(&tid->buf_q)); + } while (!skb_queue_empty(&tid->buf_q)); *aggr_len = al; @@ -834,7 +840,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, int aggr_len; do { - if (list_empty(&tid->buf_q)) + if (skb_queue_empty(&tid->buf_q)) return; INIT_LIST_HEAD(&bf_q); @@ -955,7 +961,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); - if (!list_empty(&tid->buf_q)) + if (!skb_queue_empty(&tid->buf_q)) buffered = true; tid->sched = false; @@ -988,7 +994,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); ac->clear_ps_filter = true; - if (!list_empty(&tid->buf_q) && !tid->paused) { + if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { ath_tx_queue_tid(txq, tid); ath_txq_schedule(sc, txq); } @@ -1332,7 +1338,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) * add tid to round-robin queue if more frames * are pending for the tid */ - if (!list_empty(&tid->buf_q)) + if (!skb_queue_empty(&tid->buf_q)) ath_tx_queue_tid(txq, tid); if (tid == last_tid || @@ -1438,7 +1444,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - seqno is not within block-ack window * - h/w queue depth exceeds low water mark */ - if (!list_empty(&tid->buf_q) || tid->paused || + if (!skb_queue_empty(&tid->buf_q) || tid->paused || !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* @@ -1446,7 +1452,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * for aggregation. */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); - list_add_tail(&bf->list, &tid->buf_q); + __skb_queue_tail(&tid->buf_q, bf->bf_mpdu); if (!txctl->an || !txctl->an->sleeping) ath_tx_queue_tid(txctl->txq, tid); return; @@ -1777,6 +1783,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, bf->bf_buf_addr, txq->axq_qnum); + fi->bf = bf; return bf; } @@ -2394,7 +2401,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->sched = false; tid->paused = false; tid->state &= ~AGGR_CLEANUP; - INIT_LIST_HEAD(&tid->buf_q); + __skb_queue_head_init(&tid->buf_q); acno = TID_TO_WME_AC(tidno); tid->ac = &an->ac[acno]; tid->state &= ~AGGR_ADDBA_COMPLETE; From 6a0ddaef7c2f50f2d3ee8dfbf37f66dda11f061a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 28 Aug 2011 00:32:23 +0200 Subject: [PATCH 126/129] ath9k: move the sequence number from ath_frame_info to ath_buf It is only necessary for BAW tracking and moving it to the ath_buf makes it easier to add further improvements, such as deferring seqno allocation in the aggregation path. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 55 +++++++++++--------------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index eb4cdefda629..5d9a9aabe476 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -211,12 +211,12 @@ struct ath_frame_info { enum ath9k_key_type keytype; u8 keyix; u8 retries; - u16 seqno; }; struct ath_buf_state { u8 bf_type; u8 bfs_paprd; + u16 seqno; unsigned long bfs_paprd_timestamp; }; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 34005e11502c..e3eeca98fbba 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -168,7 +168,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) spin_unlock_bh(&txq->axq_lock); if (fi->retries) { - ath_tx_update_baw(sc, tid, fi->seqno); + ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); } else { ath_tx_send_normal(sc, txq, NULL, &bf_head); @@ -237,7 +237,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); if (fi->retries) - ath_tx_update_baw(sc, tid, fi->seqno); + ath_tx_update_baw(sc, tid, bf->bf_state.seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -327,7 +327,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, while (bf) { fi = get_frame_info(bf->bf_mpdu); - ba_index = ATH_BA_INDEX(seq_st, fi->seqno); + ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno); (*nframes)++; if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) @@ -428,6 +428,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { + u16 seqno = bf->bf_state.seqno; + txfail = txpending = sendbar = 0; bf_next = bf->bf_next; @@ -435,7 +437,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@ -479,7 +481,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, fi->seqno); + ath_tx_update_baw(sc, tid, seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { @@ -507,7 +509,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, fi->seqno); + ath_tx_update_baw(sc, tid, seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= @@ -752,17 +754,19 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; struct sk_buff *skb; + u16 seqno; do { skb = skb_peek(&tid->buf_q); fi = get_frame_info(skb); bf = fi->bf; + seqno = bf->bf_state.seqno; if (!bf_first) bf_first = bf; /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@ -810,7 +814,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, /* link buffers of this frame to the aggregate */ if (!fi->retries) - ath_tx_addto_baw(sc, tid, fi->seqno); + ath_tx_addto_baw(sc, tid, seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); __skb_unlink(skb, &tid->buf_q); @@ -1434,6 +1438,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, { struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); struct list_head bf_head; + u16 seqno = bf->bf_state.seqno; bf->bf_state.bf_type |= BUF_AMPDU; @@ -1445,7 +1450,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - h/w queue depth exceeds low water mark */ if (!skb_queue_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || + !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) || txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later @@ -1463,7 +1468,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, /* Add sub-frame to BAW */ if (!fi->retries) - ath_tx_addto_baw(sc, tid, fi->seqno); + ath_tx_addto_baw(sc, tid, seqno); /* Queue to h/w without aggregation */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); @@ -1519,39 +1524,19 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, int framelen) { - struct ath_softc *sc = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - struct ieee80211_hdr *hdr; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an = NULL; - struct ath_atx_tid *tid; enum ath9k_key_type keytype; - u16 seqno = 0; - u8 tidno; keytype = ath9k_cmn_get_hw_crypto_keytype(skb); if (sta) an = (struct ath_node *) sta->drv_priv; - hdr = (struct ieee80211_hdr *)skb->data; - if (an && ieee80211_is_data_qos(hdr->frame_control) && - conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { - - tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; - - /* - * Override seqno set by upper layer with the one - * in tx aggregation state. - */ - tid = ATH_AN_2_TID(an, tidno); - seqno = tid->seq_next; - hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - } - memset(fi, 0, sizeof(*fi)); if (hw_key) fi->keyix = hw_key->hw_key_idx; @@ -1561,7 +1546,6 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; fi->framelen = framelen; - fi->seqno = seqno; } static int setup_tx_flags(struct sk_buff *skb) @@ -1797,6 +1781,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct list_head bf_head; struct ath_atx_tid *tid = NULL; + u16 seqno; u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); @@ -1806,6 +1791,12 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(txctl->an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); + + bf->bf_state.seqno = seqno; + WARN_ON(tid->ac->txq != txctl->txq); } From fa05f87ad4213a3e99bea6f5e73611dc27b4304a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 28 Aug 2011 00:32:24 +0200 Subject: [PATCH 127/129] ath9k: move seqno allocation in the tx path to ath_tx_setup_buffer Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 42 +++++++++++++++------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e3eeca98fbba..bd523619e7b7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1717,17 +1717,19 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) } -static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, +static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, struct sk_buff *skb) { - struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_buf *bf; struct ath_desc *ds; int frm_type; + u16 seqno; bf = ath_tx_get_buffer(sc); if (!bf) { @@ -1737,6 +1739,13 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, ATH_TXBUF_RESET(bf); + if (tid) { + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); + bf->bf_state.seqno = seqno; + } + bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; @@ -1773,15 +1782,15 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, } /* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, +static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, struct ath_tx_control *txctl) { - struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct list_head bf_head; struct ath_atx_tid *tid = NULL; - u16 seqno; + struct ath_buf *bf; + int ret = 0; u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); @@ -1791,15 +1800,15 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(txctl->an, tidno); - seqno = tid->seq_next; - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - - bf->bf_state.seqno = seqno; - WARN_ON(tid->ac->txq != txctl->txq); } + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (unlikely(!bf)) { + ret = -ENOMEM; + goto out; + } + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { /* * Try aggregation if it's a unicast data frame @@ -1825,7 +1834,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } +out: spin_unlock_bh(&txctl->txq->axq_lock); + return ret; } /* Upon failure caller should free skb */ @@ -1838,7 +1849,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; struct ath_txq *txq = txctl->txq; - struct ath_buf *bf; int padpos, padsize; int frmlen = skb->len + FCS_LEN; int q; @@ -1885,10 +1895,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, * info are no longer valid (overwritten by the ath_frame_info data. */ - bf = ath_tx_setup_buffer(hw, txctl->txq, skb); - if (unlikely(!bf)) - return -ENOMEM; - q = skb_get_queue_mapping(skb); spin_lock_bh(&txq->axq_lock); if (txq == sc->tx.txq_map[q] && @@ -1898,9 +1904,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, } spin_unlock_bh(&txq->axq_lock); - ath_tx_start_dma(sc, bf, txctl); - - return 0; + return ath_tx_start_dma(sc, skb, txctl); } /*****************/ From 44f1d26c16d5806f23f8d7ce5b85362a1897fbef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 28 Aug 2011 00:32:25 +0200 Subject: [PATCH 128/129] ath9k: defer ath_tx_setup_buffer setup to the first tx attempt during aggr With sequence number and buffer allocation deferred to when they're needed for the first time, it becomes much easier to start dropping packets from the tid queue if necessary, e.g. when latency suddenly increases. This can lead to some future improvements in buffer management for better latency. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 105 ++++++++++++++++---------- 1 file changed, 66 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index bd523619e7b7..68066c56e4e5 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -48,8 +48,9 @@ static u16 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); + struct ath_atx_tid *tid, struct sk_buff *skb); +static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, + int tx_flags, struct ath_txq *txq); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); @@ -61,6 +62,10 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); +static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, + struct sk_buff *skb); enum { MCS_HT20, @@ -164,14 +169,13 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) fi = get_frame_info(skb); bf = fi->bf; - list_add_tail(&bf->list, &bf_head); - spin_unlock_bh(&txq->axq_lock); - if (fi->retries) { + if (bf && fi->retries) { + list_add_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); } else { - ath_tx_send_normal(sc, txq, NULL, &bf_head); + ath_tx_send_normal(sc, txq, NULL, skb); } spin_lock_bh(&txq->axq_lock); } @@ -234,6 +238,13 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, fi = get_frame_info(skb); bf = fi->bf; + if (!bf) { + spin_unlock(&txq->axq_lock); + ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); + spin_lock(&txq->axq_lock); + continue; + } + list_add_tail(&bf->list, &bf_head); if (fi->retries) @@ -760,8 +771,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, skb = skb_peek(&tid->buf_q); fi = get_frame_info(skb); bf = fi->bf; - seqno = bf->bf_state.seqno; + if (!fi->bf) + bf = ath_tx_setup_buffer(sc, txq, tid, skb); + if (!bf) + continue; + + bf->bf_state.bf_type |= BUF_AMPDU; + seqno = bf->bf_state.seqno; if (!bf_first) bf_first = bf; @@ -1434,13 +1451,11 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, struct ath_tx_control *txctl) + struct sk_buff *skb, struct ath_tx_control *txctl) { - struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); + struct ath_frame_info *fi = get_frame_info(skb); struct list_head bf_head; - u16 seqno = bf->bf_state.seqno; - - bf->bf_state.bf_type |= BUF_AMPDU; + struct ath_buf *bf; /* * Do not queue to h/w when any of the following conditions is true: @@ -1450,25 +1465,29 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - h/w queue depth exceeds low water mark */ if (!skb_queue_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) || + !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); - __skb_queue_tail(&tid->buf_q, bf->bf_mpdu); + __skb_queue_tail(&tid->buf_q, skb); if (!txctl->an || !txctl->an->sleeping) ath_tx_queue_tid(txctl->txq, tid); return; } + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) + return; + + bf->bf_state.bf_type |= BUF_AMPDU; INIT_LIST_HEAD(&bf_head); list_add(&bf->list, &bf_head); /* Add sub-frame to BAW */ - if (!fi->retries) - ath_tx_addto_baw(sc, tid, seqno); + ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); /* Queue to h/w without aggregation */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); @@ -1478,13 +1497,21 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, } static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) + struct ath_atx_tid *tid, struct sk_buff *skb) { - struct ath_frame_info *fi; + struct ath_frame_info *fi = get_frame_info(skb); + struct list_head bf_head; struct ath_buf *bf; - bf = list_first_entry(bf_head, struct ath_buf, list); + bf = fi->bf; + if (!bf) + bf = ath_tx_setup_buffer(sc, txq, tid, skb); + + if (!bf) + return; + + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ @@ -1492,9 +1519,8 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; - fi = get_frame_info(bf->bf_mpdu); ath_buf_set_rate(sc, bf, fi->framelen); - ath_tx_txqaddbuf(sc, txq, bf_head, false); + ath_tx_txqaddbuf(sc, txq, &bf_head, false); TX_STAT_INC(txq->axq_qnum, queued); } @@ -1717,6 +1743,10 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) } +/* + * Assign a descriptor (and sequence number if necessary, + * and map buffer for DMA. Frees skb on error + */ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, @@ -1734,7 +1764,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); - return NULL; + goto error; } ATH_TXBUF_RESET(bf); @@ -1757,7 +1787,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - return NULL; + goto error; } frm_type = get_hw_packet_type(skb); @@ -1779,18 +1809,20 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, fi->bf = bf; return bf; + +error: + dev_kfree_skb_any(skb); + return NULL; } /* FIXME: tx power */ -static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, +static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, struct ath_tx_control *txctl) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct list_head bf_head; struct ath_atx_tid *tid = NULL; struct ath_buf *bf; - int ret = 0; u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); @@ -1803,21 +1835,16 @@ static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, WARN_ON(tid->ac->txq != txctl->txq); } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); - if (unlikely(!bf)) { - ret = -ENOMEM; - goto out; - } - if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { /* * Try aggregation if it's a unicast data frame * and the destination is HT capable. */ - ath_tx_send_ampdu(sc, tid, bf, txctl); + ath_tx_send_ampdu(sc, tid, skb, txctl); } else { - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) + goto out; bf->bf_state.bfs_paprd = txctl->paprd; @@ -1831,12 +1858,11 @@ static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); - ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); + ath_tx_send_normal(sc, txctl->txq, tid, skb); } out: spin_unlock_bh(&txctl->txq->axq_lock); - return ret; } /* Upon failure caller should free skb */ @@ -1904,7 +1930,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, } spin_unlock_bh(&txq->axq_lock); - return ath_tx_start_dma(sc, skb, txctl); + ath_tx_start_dma(sc, skb, txctl); + return 0; } /*****************/ From 2fa8b6a0e42570690a48a56cb65778211e3cc9cc Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Sun, 28 Aug 2011 08:22:38 -0500 Subject: [PATCH 129/129] iwlwifi: iwl-agn-rs.c: remove old comment this comment refers to some code that was removed. Signed-off-by: Greg Dietsche Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 356762f21d2f..ffee15ba06a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2214,7 +2214,6 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) /* * setup rate table in uCode - * return rate_n_flags as used in the table */ static void rs_update_rate_tbl(struct iwl_priv *priv, struct iwl_rxon_context *ctx,