Merge branch 'wl12xx-next' into for-linville

Conflicts:
	drivers/net/wireless/ti/wl12xx/main.c
	drivers/net/wireless/ti/wlcore/wlcore.h
Tento commit je obsažen v:
Luciano Coelho
2013-01-18 09:40:07 +02:00
47 změnil soubory, kde provedl 4632 přidání a 2032 odebrání

Zobrazit soubor

@@ -1,3 +1,3 @@
wl12xx-objs = main.o cmd.o acx.o debugfs.o
wl12xx-objs = main.o cmd.o acx.o debugfs.o scan.o event.o
obj-$(CONFIG_WL12XX) += wl12xx.o

Zobrazit soubor

@@ -284,3 +284,40 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
kfree(radio_parms);
return ret;
}
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch)
{
struct wl12xx_cmd_channel_switch *cmd;
int ret;
wl1271_debug(DEBUG_ACX, "cmd channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = wlvif->role_id;
cmd->channel = ch_switch->channel->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
/* FIXME: control from mac80211 in the future */
/* Enable TX on the target channel */
cmd->post_switch_tx_disable = 0;
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send channel switch command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}

Zobrazit soubor

@@ -103,10 +103,30 @@ struct wl1271_ext_radio_parms_cmd {
u8 padding[3];
} __packed;
struct wl12xx_cmd_channel_switch {
struct wl1271_cmd_header header;
u8 role_id;
/* The new serving channel */
u8 channel;
/* Relative time of the serving channel switch in TBTT units */
u8 switch_time;
/* Stop the role TX, should expect it after radar detection */
u8 stop_tx;
/* The target channel tx status 1-stopped 0-open*/
u8 post_switch_tx_disable;
u8 padding[3];
} __packed;
int wl1271_cmd_general_parms(struct wl1271 *wl);
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 wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
#endif /* __WL12XX_CMD_H__ */

Zobrazit soubor

@@ -0,0 +1,116 @@
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 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 St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "event.h"
#include "scan.h"
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
bool *timeout)
{
u32 local_event;
switch (event) {
case WLCORE_EVENT_ROLE_STOP_COMPLETE:
local_event = ROLE_STOP_COMPLETE_EVENT_ID;
break;
case WLCORE_EVENT_PEER_REMOVE_COMPLETE:
local_event = PEER_REMOVE_COMPLETE_EVENT_ID;
break;
default:
/* event not implemented */
return 0;
}
return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
}
int wl12xx_process_mailbox_events(struct wl1271 *wl)
{
struct wl12xx_event_mailbox *mbox = wl->mbox;
u32 vector;
vector = le32_to_cpu(mbox->events_vector);
vector &= ~(le32_to_cpu(mbox->events_mask));
wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector);
if (vector & SCAN_COMPLETE_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "status: 0x%x",
mbox->scheduled_scan_status);
if (wl->scan_wlvif)
wl12xx_scan_completed(wl, wl->scan_wlvif);
}
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
wl1271_debug(DEBUG_EVENT,
"PERIODIC_SCAN_REPORT_EVENT (status 0x%0x)",
mbox->scheduled_scan_status);
wlcore_scan_sched_scan_results(wl);
}
if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID)
wlcore_event_sched_scan_completed(wl,
mbox->scheduled_scan_status);
if (vector & SOFT_GEMINI_SENSE_EVENT_ID)
wlcore_event_soft_gemini_sense(wl,
mbox->soft_gemini_sense_info);
if (vector & BSS_LOSE_EVENT_ID)
wlcore_event_beacon_loss(wl, 0xff);
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID)
wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric);
if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)
wlcore_event_ba_rx_constraint(wl,
BIT(mbox->role_id),
mbox->rx_ba_allowed);
if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID)
wlcore_event_channel_switch(wl, 0xff,
mbox->channel_switch_status);
if (vector & DUMMY_PACKET_EVENT_ID)
wlcore_event_dummy_packet(wl);
/*
* "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected.
*/
if (vector & MAX_TX_RETRY_EVENT_ID)
wlcore_event_max_tx_failure(wl,
le16_to_cpu(mbox->sta_tx_retry_exceeded));
if (vector & INACTIVE_STA_EVENT_ID)
wlcore_event_inactive_sta(wl,
le16_to_cpu(mbox->sta_aging_status));
if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
wlcore_event_roc_complete(wl);
return 0;
}

Zobrazit soubor

@@ -0,0 +1,111 @@
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 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 St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_EVENT_H__
#define __WL12XX_EVENT_H__
#include "../wlcore/wlcore.h"
enum {
MEASUREMENT_START_EVENT_ID = BIT(8),
MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
SCAN_COMPLETE_EVENT_ID = BIT(10),
WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
RESERVED1 = BIT(13),
PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
ROLE_STOP_COMPLETE_EVENT_ID = BIT(15),
RADAR_DETECTED_EVENT_ID = BIT(16),
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),
DUMMY_PACKET_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
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),
};
struct wl12xx_event_mailbox {
__le32 events_vector;
__le32 events_mask;
__le32 reserved_1;
__le32 reserved_2;
u8 number_of_scan_results;
u8 scan_tag;
u8 completed_scan_status;
u8 reserved_3;
u8 soft_gemini_sense_info;
u8 soft_gemini_protective_info;
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
u8 change_auto_mode_timeout;
u8 scheduled_scan_status;
u8 reserved4;
/* tuned channel (roc) */
u8 roc_channel;
__le16 hlid_removed_bitmap;
/* bitmap of aged stations (by HLID) */
__le16 sta_aging_status;
/* bitmap of stations (by HLID) which exceeded max tx retries */
__le16 sta_tx_retry_exceeded;
/* discovery completed results */
u8 discovery_tag;
u8 number_of_preq_results;
u8 number_of_prsp_results;
u8 reserved_5;
/* rx ba constraint */
u8 role_id; /* 0xFF means any role. */
u8 rx_ba_allowed;
u8 reserved_6[2];
/* Channel switch results */
u8 channel_switch_role_id;
u8 channel_switch_status;
u8 reserved_7[2];
u8 ps_poll_delivery_failure_role_ids;
u8 stopped_role_ids;
u8 started_role_ids;
u8 reserved_8[9];
} __packed;
int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
bool *timeout);
int wl12xx_process_mailbox_events(struct wl1271 *wl);
#endif

Zobrazit soubor

@@ -38,6 +38,8 @@
#include "reg.h"
#include "cmd.h"
#include "acx.h"
#include "scan.h"
#include "event.h"
#include "debugfs.h"
static char *fref_param;
@@ -208,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = {
.tmpl_short_retry_limit = 10,
.tmpl_long_retry_limit = 10,
.tx_watchdog_timeout = 5000,
.slow_link_thold = 3,
.fast_link_thold = 10,
},
.conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
@@ -265,8 +269,10 @@ static struct wlcore_conf wl12xx_conf = {
.scan = {
.min_dwell_time_active = 7500,
.max_dwell_time_active = 30000,
.min_dwell_time_passive = 100000,
.max_dwell_time_passive = 100000,
.min_dwell_time_active_long = 25000,
.max_dwell_time_active_long = 50000,
.dwell_time_passive = 100000,
.dwell_time_dfs = 150000,
.num_probe_reqs = 2,
.split_scan_timeout = 50000,
},
@@ -368,6 +374,10 @@ static struct wlcore_conf wl12xx_conf = {
.increase_time = 1,
.window_size = 16,
},
.recovery = {
.bug_on_recovery = 0,
.no_recovery = 0,
},
};
static struct wl12xx_priv_conf wl12xx_default_priv_conf = {
@@ -601,9 +611,9 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
int ret;
if (wl->chip.id != CHIP_ID_1283_PG20) {
if (wl->chip.id != CHIP_ID_128X_PG20) {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
struct wl127x_rx_mem_pool_addr rx_mem_addr;
struct wl12xx_priv *priv = wl->priv;
/*
* Choose the block we want to read
@@ -612,13 +622,13 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
*/
u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK;
rx_mem_addr.addr = (mem_block << 8) +
priv->rx_mem_addr->addr = (mem_block << 8) +
le32_to_cpu(wl_mem_map->packet_memory_pool_start);
rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
priv->rx_mem_addr->addr_extra = priv->rx_mem_addr->addr + 4;
ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr,
sizeof(rx_mem_addr), false);
ret = wlcore_write(wl, WL1271_SLV_REG_DATA, priv->rx_mem_addr,
sizeof(*priv->rx_mem_addr), false);
if (ret < 0)
return ret;
}
@@ -631,13 +641,15 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
int ret = 0;
switch (wl->chip.id) {
case CHIP_ID_1271_PG10:
case CHIP_ID_127X_PG10:
wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
wl->chip.id);
wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
WLCORE_QUIRK_TKIP_HEADER_SPACE |
WLCORE_QUIRK_START_STA_FAILS |
WLCORE_QUIRK_AP_ZERO_SESSION_ID;
wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
wl->mr_fw_name = WL127X_FW_NAME_MULTI;
memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x,
@@ -646,18 +658,22 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl->ops->prepare_read = wl127x_prepare_read;
wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
WL127X_MINOR_VER);
wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER,
WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER,
WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER,
WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER);
break;
case CHIP_ID_1271_PG20:
case CHIP_ID_127X_PG20:
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
wl->chip.id);
wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
WLCORE_QUIRK_TKIP_HEADER_SPACE |
WLCORE_QUIRK_START_STA_FAILS |
WLCORE_QUIRK_AP_ZERO_SESSION_ID;
wl->plt_fw_name = WL127X_PLT_FW_NAME;
wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
wl->mr_fw_name = WL127X_FW_NAME_MULTI;
@@ -667,12 +683,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl->ops->prepare_read = wl127x_prepare_read;
wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
WL127X_MINOR_VER);
wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER,
WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER,
WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER,
WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER);
break;
case CHIP_ID_1283_PG20:
case CHIP_ID_128X_PG20:
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
wl->chip.id);
wl->plt_fw_name = WL128X_PLT_FW_NAME;
@@ -682,19 +700,29 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* wl128x requires TX blocksize alignment */
wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
WLCORE_QUIRK_TKIP_HEADER_SPACE |
WLCORE_QUIRK_START_STA_FAILS |
WLCORE_QUIRK_AP_ZERO_SESSION_ID;
wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER,
WL128X_MAJOR_VER, WL128X_SUBTYPE_VER,
WL128X_MINOR_VER);
wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER,
WL128X_IFTYPE_SR_VER, WL128X_MAJOR_SR_VER,
WL128X_SUBTYPE_SR_VER, WL128X_MINOR_SR_VER,
WL128X_IFTYPE_MR_VER, WL128X_MAJOR_MR_VER,
WL128X_SUBTYPE_MR_VER, WL128X_MINOR_MR_VER);
break;
case CHIP_ID_1283_PG10:
case CHIP_ID_128X_PG10:
default:
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
ret = -ENODEV;
goto out;
}
/* common settings */
wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY;
wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY;
wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ;
out:
return ret;
}
@@ -1067,7 +1095,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
u32 clk;
int selected_clock = -1;
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0)
goto out;
@@ -1098,7 +1126,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
if (wl->chip.id == CHIP_ID_1283_PG20)
if (wl->chip.id == CHIP_ID_128X_PG20)
clk |= ((selected_clock & 0x3) << 1) << 4;
else
clk |= (priv->ref_clock << 1) << 4;
@@ -1152,7 +1180,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl)
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
if (ret < 0)
goto out;
@@ -1219,6 +1247,23 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
wl->event_mask = BSS_LOSE_EVENT_ID |
REGAINED_BSS_EVENT_ID |
SCAN_COMPLETE_EVENT_ID |
ROLE_STOP_COMPLETE_EVENT_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 |
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 |
CHANNEL_SWITCH_COMPLETE_EVENT_ID;
ret = wlcore_boot_run_firmware(wl);
if (ret < 0)
goto out;
@@ -1261,7 +1306,7 @@ static void
wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
u32 blks, u32 spare_blks)
{
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
desc->wl128x_mem.total_mem_blocks = blks;
} else {
desc->wl127x_mem.extra_blocks = spare_blks;
@@ -1275,7 +1320,7 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
{
u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
desc->length = cpu_to_le16(aligned_len >> 2);
@@ -1339,7 +1384,7 @@ static int wl12xx_hw_init(struct wl1271 *wl)
{
int ret;
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
ret = wl128x_cmd_general_parms(wl);
@@ -1394,22 +1439,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
return wlvif->rate_set;
}
static int wl12xx_identify_fw(struct wl1271 *wl)
{
unsigned int *fw_ver = wl->chip.fw_ver;
/* 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))
wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED;
/* This feature is not yet supported for AP mode */
if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED;
return 0;
}
static void wl12xx_conf_init(struct wl1271 *wl)
{
struct wl12xx_priv *priv = wl->priv;
@@ -1426,7 +1455,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
bool supported = false;
u8 major, minor;
if (wl->chip.id == CHIP_ID_1283_PG20) {
if (wl->chip.id == CHIP_ID_128X_PG20) {
major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
@@ -1482,7 +1511,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
u16 die_info;
int ret;
if (wl->chip.id == CHIP_ID_1283_PG20)
if (wl->chip.id == CHIP_ID_128X_PG20)
ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1,
&die_info);
else
@@ -1589,16 +1618,46 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
return wlcore_set_key(wl, cmd, vif, sta, key_conf);
}
static int wl12xx_set_peer_cap(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap,
bool allow_ht_operation,
u32 rate_set, u8 hlid)
{
return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation,
hlid);
}
static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
struct wl1271_link *lnk)
{
u8 thold;
if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
thold = wl->conf.tx.fast_link_thold;
else
thold = wl->conf.tx.slow_link_thold;
return lnk->allocated_pkts < thold;
}
static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
struct wl1271_link *lnk)
{
/* any link is good for low priority */
return true;
}
static int wl12xx_setup(struct wl1271 *wl);
static struct wlcore_ops wl12xx_ops = {
.setup = wl12xx_setup,
.identify_chip = wl12xx_identify_chip,
.identify_fw = wl12xx_identify_fw,
.boot = wl12xx_boot,
.plt_init = wl12xx_plt_init,
.trigger_cmd = wl12xx_trigger_cmd,
.ack_event = wl12xx_ack_event,
.wait_for_event = wl12xx_wait_for_event,
.process_mailbox_events = wl12xx_process_mailbox_events,
.calc_tx_blocks = wl12xx_calc_tx_blocks,
.set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
.set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
@@ -1615,9 +1674,17 @@ static struct wlcore_ops wl12xx_ops = {
.set_rx_csum = NULL,
.ap_get_mimo_wide_rate_mask = NULL,
.debugfs_init = wl12xx_debugfs_add_files,
.scan_start = wl12xx_scan_start,
.scan_stop = wl12xx_scan_stop,
.sched_scan_start = wl12xx_sched_scan_start,
.sched_scan_stop = wl12xx_scan_sched_scan_stop,
.get_spare_blocks = wl12xx_get_spare_blocks,
.set_key = wl12xx_set_key,
.channel_switch = wl12xx_cmd_channel_switch,
.pre_pkt_send = NULL,
.set_peer_cap = wl12xx_set_peer_cap,
.lnk_high_prio = wl12xx_lnk_high_prio,
.lnk_low_prio = wl12xx_lnk_low_prio,
};
static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
@@ -1641,6 +1708,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl->rtable = wl12xx_rtable;
wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS;
wl->num_channels = 1;
wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES;
wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
@@ -1693,6 +1761,10 @@ static int wl12xx_setup(struct wl1271 *wl)
wl1271_error("Invalid tcxo parameter %s", tcxo_param);
}
priv->rx_mem_addr = kmalloc(sizeof(*priv->rx_mem_addr), GFP_KERNEL);
if (!priv->rx_mem_addr)
return -ENOMEM;
return 0;
}
@@ -1703,7 +1775,8 @@ static int wl12xx_probe(struct platform_device *pdev)
int ret;
hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv),
WL12XX_AGGR_BUFFER_SIZE);
WL12XX_AGGR_BUFFER_SIZE,
sizeof(struct wl12xx_event_mailbox));
if (IS_ERR(hw)) {
wl1271_error("can't allocate hw");
ret = PTR_ERR(hw);
@@ -1725,6 +1798,21 @@ out:
return ret;
}
static int wl12xx_remove(struct platform_device *pdev)
{
struct wl1271 *wl = platform_get_drvdata(pdev);
struct wl12xx_priv *priv;
if (!wl)
goto out;
priv = wl->priv;
kfree(priv->rx_mem_addr);
out:
return wlcore_remove(pdev);
}
static const struct platform_device_id wl12xx_id_table[] = {
{ "wl12xx", 0 },
{ } /* Terminating Entry */
@@ -1733,7 +1821,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
static struct platform_driver wl12xx_driver = {
.probe = wl12xx_probe,
.remove = wlcore_remove,
.remove = wl12xx_remove,
.id_table = wl12xx_id_table,
.driver = {
.name = "wl12xx_driver",

Zobrazit soubor

@@ -0,0 +1,501 @@
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 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 St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/ieee80211.h>
#include "scan.h"
#include "../wlcore/debug.h"
#include "../wlcore/tx.h"
static int wl1271_get_scan_channels(struct wl1271 *wl,
struct cfg80211_scan_request *req,
struct basic_scan_channel_params *channels,
enum ieee80211_band band, bool passive)
{
struct conf_scan_settings *c = &wl->conf.scan;
int i, j;
u32 flags;
for (i = 0, j = 0;
i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
i++) {
flags = req->channels[i]->flags;
if (!test_bit(i, wl->scan.scanned_ch) &&
!(flags & IEEE80211_CHAN_DISABLED) &&
(req->channels[i]->band == band) &&
/*
* In passive scans, we scan all remaining
* channels, even if not marked as such.
* In active scans, we only scan channels not
* marked as passive.
*/
(passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
req->channels[i]->band,
req->channels[i]->center_freq);
wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X",
req->channels[i]->hw_value,
req->channels[i]->flags);
wl1271_debug(DEBUG_SCAN,
"max_antenna_gain %d, max_power %d",
req->channels[i]->max_antenna_gain,
req->channels[i]->max_power);
wl1271_debug(DEBUG_SCAN, "beacon_found %d",
req->channels[i]->beacon_found);
if (!passive) {
channels[j].min_duration =
cpu_to_le32(c->min_dwell_time_active);
channels[j].max_duration =
cpu_to_le32(c->max_dwell_time_active);
} else {
channels[j].min_duration =
cpu_to_le32(c->dwell_time_passive);
channels[j].max_duration =
cpu_to_le32(c->dwell_time_passive);
}
channels[j].early_termination = 0;
channels[j].tx_power_att = req->channels[i]->max_power;
channels[j].channel = req->channels[i]->hw_value;
memset(&channels[j].bssid_lsb, 0xff, 4);
memset(&channels[j].bssid_msb, 0xff, 2);
/* Mark the channels we already used */
set_bit(i, wl->scan.scanned_ch);
j++;
}
}
return j;
}
#define WL1271_NOTHING_TO_SCAN 1
static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum ieee80211_band band,
bool passive, u32 basic_rate)
{
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct wl1271_cmd_scan *cmd;
struct wl1271_cmd_trigger_scan_to *trigger;
int ret;
u16 scan_options = 0;
/* skip active scans if we don't have SSIDs */
if (!passive && wl->scan.req->n_ssids == 0)
return WL1271_NOTHING_TO_SCAN;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
if (!cmd || !trigger) {
ret = -ENOMEM;
goto out;
}
if (wl->conf.scan.split_scan_timeout)
scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN;
if (passive)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
cmd->params.role_id = wlvif->role_id;
if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
goto out;
}
cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
cmd->channels,
band, passive);
if (cmd->params.n_ch == 0) {
ret = WL1271_NOTHING_TO_SCAN;
goto out;
}
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tid_trigger = CONF_TX_AC_ANY_TID;
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
if (band == IEEE80211_BAND_2GHZ)
cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ;
else
cmd->params.band = WL1271_SCAN_BAND_5_GHZ;
if (wl->scan.ssid_len && wl->scan.ssid) {
cmd->params.ssid_len = wl->scan.ssid_len;
memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
}
memcpy(cmd->addr, vif->addr, ETH_ALEN);
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
cmd->params.role_id, band,
wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie,
wl->scan.req->ie_len, false);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
}
trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout);
ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
sizeof(*trigger), 0);
if (ret < 0) {
wl1271_error("trigger scan to failed for hw scan");
goto out;
}
wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("SCAN failed");
goto out;
}
out:
kfree(cmd);
kfree(trigger);
return ret;
}
int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct wl1271_cmd_header *cmd = NULL;
int ret = 0;
if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE))
return -EINVAL;
wl1271_debug(DEBUG_CMD, "cmd scan stop");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd,
sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("cmd stop_scan failed");
goto out;
}
out:
kfree(cmd);
return ret;
}
void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret = 0;
enum ieee80211_band band;
u32 rate, mask;
switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE:
break;
case WL1271_SCAN_STATE_2GHZ_ACTIVE:
band = IEEE80211_BAND_2GHZ;
mask = wlvif->bitrate_masks[band];
if (wl->scan.req->no_cck) {
mask &= ~CONF_TX_CCK_RATES;
if (!mask)
mask = CONF_TX_RATE_MASK_BASIC_P2P;
}
rate = wl1271_tx_min_rate_get(wl, mask);
ret = wl1271_scan_send(wl, wlvif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
wl1271_scan_stm(wl, wlvif);
}
break;
case WL1271_SCAN_STATE_2GHZ_PASSIVE:
band = IEEE80211_BAND_2GHZ;
mask = wlvif->bitrate_masks[band];
if (wl->scan.req->no_cck) {
mask &= ~CONF_TX_CCK_RATES;
if (!mask)
mask = CONF_TX_RATE_MASK_BASIC_P2P;
}
rate = wl1271_tx_min_rate_get(wl, mask);
ret = wl1271_scan_send(wl, wlvif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
else
wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl, wlvif);
}
break;
case WL1271_SCAN_STATE_5GHZ_ACTIVE:
band = IEEE80211_BAND_5GHZ;
rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, wlvif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
wl1271_scan_stm(wl, wlvif);
}
break;
case WL1271_SCAN_STATE_5GHZ_PASSIVE:
band = IEEE80211_BAND_5GHZ;
rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, wlvif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl, wlvif);
}
break;
case WL1271_SCAN_STATE_DONE:
wl->scan.failed = false;
cancel_delayed_work(&wl->scan_complete_work);
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
msecs_to_jiffies(0));
break;
default:
wl1271_error("invalid scan state");
break;
}
if (ret < 0) {
cancel_delayed_work(&wl->scan_complete_work);
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
msecs_to_jiffies(0));
}
}
static void wl12xx_adjust_channels(struct wl1271_cmd_sched_scan_config *cmd,
struct wlcore_scan_channels *cmd_channels)
{
memcpy(cmd->passive, cmd_channels->passive, sizeof(cmd->passive));
memcpy(cmd->active, cmd_channels->active, sizeof(cmd->active));
cmd->dfs = cmd_channels->dfs;
cmd->n_pactive_ch = cmd_channels->passive_active;
memcpy(cmd->channels_2, cmd_channels->channels_2,
sizeof(cmd->channels_2));
memcpy(cmd->channels_5, cmd_channels->channels_5,
sizeof(cmd->channels_2));
/* channels_4 are not supported, so no need to copy them */
}
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies)
{
struct wl1271_cmd_sched_scan_config *cfg = NULL;
struct wlcore_scan_channels *cfg_channels = NULL;
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int i, ret;
bool force_passive = !req->n_ssids;
wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
cfg->role_id = wlvif->role_id;
cfg->rssi_threshold = c->rssi_threshold;
cfg->snr_threshold = c->snr_threshold;
cfg->n_probe_reqs = c->num_probe_reqs;
/* cycles set to 0 it means infinite (until manually stopped) */
cfg->cycles = 0;
/* report APs when at least 1 is found */
cfg->report_after = 1;
/* don't stop scanning automatically when something is found */
cfg->terminate = 0;
cfg->tag = WL1271_SCAN_DEFAULT_TAG;
/* don't filter on BSS type */
cfg->bss_type = SCAN_BSS_TYPE_ANY;
/* currently NL80211 supports only a single interval */
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
cfg->intervals[i] = cpu_to_le32(req->interval);
cfg->ssid_len = 0;
ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req);
if (ret < 0)
goto out;
cfg->filter_type = ret;
wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
cfg_channels = kzalloc(sizeof(*cfg_channels), GFP_KERNEL);
if (!cfg_channels) {
ret = -ENOMEM;
goto out;
}
if (!wlcore_set_scan_chan_params(wl, cfg_channels, req->channels,
req->n_channels, req->n_ssids,
SCAN_TYPE_PERIODIC)) {
wl1271_error("scan channel list is empty");
ret = -EINVAL;
goto out;
}
wl12xx_adjust_channels(cfg, cfg_channels);
if (!force_passive && cfg->active[0]) {
u8 band = IEEE80211_BAND_2GHZ;
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
wlvif->role_id, band,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[band],
ies->len[band], true);
if (ret < 0) {
wl1271_error("2.4GHz PROBE request template failed");
goto out;
}
}
if (!force_passive && cfg->active[1]) {
u8 band = IEEE80211_BAND_5GHZ;
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
wlvif->role_id, band,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[band],
ies->len[band], true);
if (ret < 0) {
wl1271_error("5GHz PROBE request template failed");
goto out;
}
}
wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg));
ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg,
sizeof(*cfg), 0);
if (ret < 0) {
wl1271_error("SCAN configuration failed");
goto out;
}
out:
kfree(cfg_channels);
kfree(cfg);
return ret;
}
int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct wl1271_cmd_sched_scan_start *start;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd periodic scan start");
if (wlvif->bss_type != BSS_TYPE_STA_BSS)
return -EOPNOTSUPP;
if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) &&
test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
return -EBUSY;
start = kzalloc(sizeof(*start), GFP_KERNEL);
if (!start)
return -ENOMEM;
start->role_id = wlvif->role_id;
start->tag = WL1271_SCAN_DEFAULT_TAG;
ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start,
sizeof(*start), 0);
if (ret < 0) {
wl1271_error("failed to send scan start command");
goto out_free;
}
out_free:
kfree(start);
return ret;
}
int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies)
{
int ret;
ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies);
if (ret < 0)
return ret;
return wl1271_scan_sched_scan_start(wl, wlvif);
}
void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
struct wl1271_cmd_sched_scan_stop *stop;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd periodic scan stop");
/* FIXME: what to do if alloc'ing to stop fails? */
stop = kzalloc(sizeof(*stop), GFP_KERNEL);
if (!stop) {
wl1271_error("failed to alloc memory to send sched scan stop");
return;
}
stop->role_id = wlvif->role_id;
stop->tag = WL1271_SCAN_DEFAULT_TAG;
ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop,
sizeof(*stop), 0);
if (ret < 0) {
wl1271_error("failed to send sched scan stop command");
goto out_free;
}
out_free:
kfree(stop);
}
int wl12xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_scan_request *req)
{
wl1271_scan_stm(wl, wlvif);
return 0;
}
void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
wl1271_scan_stm(wl, wlvif);
}

Zobrazit soubor

@@ -0,0 +1,140 @@
/*
* This file is part of wl12xx
*
* Copyright (C) 2012 Texas Instruments. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 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 St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __WL12XX_SCAN_H__
#define __WL12XX_SCAN_H__
#include "../wlcore/wlcore.h"
#include "../wlcore/cmd.h"
#include "../wlcore/scan.h"
#define WL12XX_MAX_CHANNELS_5GHZ 23
struct basic_scan_params {
/* 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;
u8 tid_trigger;
u8 ssid_len;
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 scan_tag;
u8 padding2[2];
} __packed;
struct basic_scan_channel_params {
/* Duration in TU to wait for frames on a channel for active scan */
__le32 min_duration;
__le32 max_duration;
__le32 bssid_lsb;
__le16 bssid_msb;
u8 early_termination;
u8 tx_power_att;
u8 channel;
/* FW internal use only! */
u8 dfs_candidate;
u8 activity_detected;
u8 pad;
} __packed;
struct wl1271_cmd_scan {
struct wl1271_cmd_header header;
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_sched_scan_config {
struct wl1271_cmd_header header;
__le32 intervals[SCAN_MAX_CYCLE_INTERVALS];
s8 rssi_threshold; /* for filtering (in dBm) */
s8 snr_threshold; /* for filtering (in dB) */
u8 cycles; /* maximum number of scan cycles */
u8 report_after; /* report when this number of results are received */
u8 terminate; /* stop scanning after reporting */
u8 tag;
u8 bss_type; /* for filtering */
u8 filter_type;
u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 n_probe_reqs; /* Number of probes requests per channel */
u8 passive[SCAN_MAX_BANDS];
u8 active[SCAN_MAX_BANDS];
u8 dfs;
u8 n_pactive_ch; /* number of pactive (passive until fw detects energy)
channels in BG band */
u8 role_id;
u8 padding[1];
struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
struct conn_scan_ch_params channels_5[WL12XX_MAX_CHANNELS_5GHZ];
struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
} __packed;
struct wl1271_cmd_sched_scan_start {
struct wl1271_cmd_header header;
u8 tag;
u8 role_id;
u8 padding[2];
} __packed;
struct wl1271_cmd_sched_scan_stop {
struct wl1271_cmd_header header;
u8 tag;
u8 role_id;
u8 padding[2];
} __packed;
int wl12xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_scan_request *req);
int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies);
void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
#endif

Zobrazit soubor

@@ -24,19 +24,37 @@
#include "conf.h"
/* minimum FW required for driver for wl127x */
#define WL127X_CHIP_VER 6
#define WL127X_IFTYPE_VER 3
#define WL127X_MAJOR_VER 10
#define WL127X_SUBTYPE_VER 2
#define WL127X_MINOR_VER 115
/* WiLink 6/7 chip IDs */
#define CHIP_ID_127X_PG10 (0x04030101)
#define CHIP_ID_127X_PG20 (0x04030111)
#define CHIP_ID_128X_PG10 (0x05030101)
#define CHIP_ID_128X_PG20 (0x05030111)
/* minimum FW required for driver for wl128x */
/* FW chip version for wl127x */
#define WL127X_CHIP_VER 6
/* minimum single-role FW version for wl127x */
#define WL127X_IFTYPE_SR_VER 3
#define WL127X_MAJOR_SR_VER 10
#define WL127X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
#define WL127X_MINOR_SR_VER 115
/* minimum multi-role FW version for wl127x */
#define WL127X_IFTYPE_MR_VER 5
#define WL127X_MAJOR_MR_VER 7
#define WL127X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE
#define WL127X_MINOR_MR_VER 115
/* FW chip version for wl128x */
#define WL128X_CHIP_VER 7
#define WL128X_IFTYPE_VER 3
#define WL128X_MAJOR_VER 10
#define WL128X_SUBTYPE_VER 2
#define WL128X_MINOR_VER 115
/* minimum single-role FW version for wl128x */
#define WL128X_IFTYPE_SR_VER 3
#define WL128X_MAJOR_SR_VER 10
#define WL128X_SUBTYPE_SR_VER WLCORE_FW_VER_IGNORE
#define WL128X_MINOR_SR_VER 115
/* minimum multi-role FW version for wl128x */
#define WL128X_IFTYPE_MR_VER 5
#define WL128X_MAJOR_MR_VER 7
#define WL128X_SUBTYPE_MR_VER WLCORE_FW_VER_IGNORE
#define WL128X_MINOR_MR_VER 42
#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@@ -55,6 +73,8 @@ struct wl12xx_priv {
int ref_clock;
int tcxo_clock;
struct wl127x_rx_mem_pool_addr *rx_mem_addr;
};
#endif /* __WL12XX_PRIV_H__ */