Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
Коммит
f5237f278f
|
@ -47,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus);
|
|||
/* driver_chipcommon.c */
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
extern struct platform_device bcma_pflash_dev;
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
/* driver_chipcommon_pmu.c */
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
struct platform_device bcma_nflash_dev = {
|
||||
.name = "bcma_nflash",
|
||||
.num_resources = 0,
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SOC_FLASH2,
|
||||
|
|
|
@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
|||
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
|
||||
}
|
||||
|
||||
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
||||
|
||||
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
return bcma_core_irq(cc->core);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct gpio_chip *chip = &cc->gpio;
|
||||
|
@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
|||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
chip->ngpio = 16;
|
||||
/* There is just one SoC in one device and its GPIO addresses should be
|
||||
* deterministic to address them more easily. The other buses could get
|
||||
|
|
|
@ -14,11 +14,33 @@
|
|||
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
static const char *part_probes[] = { "bcm47xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data bcma_pflash_data = {
|
||||
.part_probe_types = part_probes,
|
||||
};
|
||||
|
||||
static struct resource bcma_pflash_resource = {
|
||||
.name = "bcma_pflash",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device bcma_pflash_dev = {
|
||||
.name = "physmap-flash",
|
||||
.dev = {
|
||||
.platform_data = &bcma_pflash_data,
|
||||
},
|
||||
.resource = &bcma_pflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
{
|
||||
|
@ -211,6 +233,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
|||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
struct bcma_drv_cc *cc = &bus->drv_cc;
|
||||
struct bcma_pflash *pflash = &cc->pflash;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
|
@ -220,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
|||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
cc->pflash.present = true;
|
||||
cc->pflash.window = BCMA_SOC_FLASH2;
|
||||
cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
|
||||
pflash->present = true;
|
||||
pflash->window = BCMA_SOC_FLASH2;
|
||||
pflash->window_size = BCMA_SOC_FLASH2_SZ;
|
||||
|
||||
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
|
||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
cc->pflash.buswidth = 1;
|
||||
pflash->buswidth = 1;
|
||||
else
|
||||
cc->pflash.buswidth = 2;
|
||||
pflash->buswidth = 2;
|
||||
|
||||
bcma_pflash_data.width = pflash->buswidth;
|
||||
bcma_pflash_resource.start = pflash->window;
|
||||
bcma_pflash_resource.end = pflash->window + pflash->window_size;
|
||||
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Flash type not supported\n");
|
||||
|
|
|
@ -149,6 +149,14 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
|||
dev_id++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
if (bus->drv_cc.pflash.present) {
|
||||
err = platform_device_register(&bcma_pflash_dev);
|
||||
if (err)
|
||||
bcma_err(bus, "Error registering parallel flash\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
if (bus->drv_cc.sflash.present) {
|
||||
err = platform_device_register(&bcma_sflash_dev);
|
||||
|
|
|
@ -58,6 +58,7 @@ config ATH9K_DEBUGFS
|
|||
bool "Atheros ath9k debugging"
|
||||
depends on ATH9K
|
||||
select MAC80211_DEBUGFS
|
||||
select RELAY
|
||||
---help---
|
||||
Say Y, if you need access to ath9k's statistics for
|
||||
interrupts, rate control, etc.
|
||||
|
|
|
@ -319,6 +319,8 @@ struct ath_rx {
|
|||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
|
||||
struct sk_buff *frag;
|
||||
|
||||
u32 ampdu_ref;
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
|
@ -754,6 +756,7 @@ struct ath_softc {
|
|||
/* relay(fs) channel for spectral scan */
|
||||
struct rchan *rfs_chan_spec_scan;
|
||||
enum spectral_mode spectral_mode;
|
||||
struct ath_spec_scan spec_config;
|
||||
int scanning;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -863,31 +866,31 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
|
|||
* interface.
|
||||
*/
|
||||
enum ath_fft_sample_type {
|
||||
ATH_FFT_SAMPLE_HT20 = 0,
|
||||
ATH_FFT_SAMPLE_HT20 = 1,
|
||||
};
|
||||
|
||||
struct fft_sample_tlv {
|
||||
u8 type; /* see ath_fft_sample */
|
||||
u16 length;
|
||||
__be16 length;
|
||||
/* type dependent data follows */
|
||||
} __packed;
|
||||
|
||||
struct fft_sample_ht20 {
|
||||
struct fft_sample_tlv tlv;
|
||||
|
||||
u8 __alignment;
|
||||
u8 max_exp;
|
||||
|
||||
u16 freq;
|
||||
__be16 freq;
|
||||
s8 rssi;
|
||||
s8 noise;
|
||||
|
||||
u16 max_magnitude;
|
||||
__be16 max_magnitude;
|
||||
u8 max_index;
|
||||
u8 bitmap_weight;
|
||||
|
||||
u64 tsf;
|
||||
__be64 tsf;
|
||||
|
||||
u16 data[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 data[SPECTRAL_HT20_NUM_BINS];
|
||||
} __packed;
|
||||
|
||||
void ath9k_tasklet(unsigned long data);
|
||||
|
|
|
@ -895,6 +895,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
|||
RXS_ERR("RX-Bytes-All", rx_bytes_all);
|
||||
RXS_ERR("RX-Beacons", rx_beacons);
|
||||
RXS_ERR("RX-Frags", rx_frags);
|
||||
RXS_ERR("RX-Spectral", rx_spectral);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
@ -1035,6 +1036,182 @@ static const struct file_operations fops_spec_scan_ctl = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_short_repeat(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_short_repeat(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.short_repeat = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_short_repeat = {
|
||||
.read = read_file_spectral_short_repeat,
|
||||
.write = write_file_spectral_short_repeat,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_count(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.count);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_count(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.count = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_count = {
|
||||
.read = read_file_spectral_count,
|
||||
.write = write_file_spectral_count,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_period(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.period);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_period(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.period = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_period = {
|
||||
.read = read_file_spectral_period,
|
||||
.write = write_file_spectral_period,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_fft_period(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_fft_period(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 15)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.fft_period = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_fft_period = {
|
||||
.read = read_file_spectral_fft_period,
|
||||
.write = write_file_spectral_fft_period,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static struct dentry *create_buf_file_handler(const char *filename,
|
||||
struct dentry *parent,
|
||||
umode_t mode,
|
||||
|
@ -1059,11 +1236,13 @@ static int remove_buf_file_handler(struct dentry *dentry)
|
|||
void ath_debug_send_fft_sample(struct ath_softc *sc,
|
||||
struct fft_sample_tlv *fft_sample_tlv)
|
||||
{
|
||||
int length;
|
||||
if (!sc->rfs_chan_spec_scan)
|
||||
return;
|
||||
|
||||
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv,
|
||||
fft_sample_tlv->length + sizeof(*fft_sample_tlv));
|
||||
length = __be16_to_cpu(fft_sample_tlv->length) +
|
||||
sizeof(*fft_sample_tlv);
|
||||
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
|
@ -1893,6 +2072,16 @@ int ath9k_init_debug(struct ath_hw *ah)
|
|||
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spec_scan_ctl);
|
||||
debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spectral_short_repeat);
|
||||
debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_spectral_count);
|
||||
debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_spectral_period);
|
||||
debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spectral_fft_period);
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
|
|
|
@ -219,6 +219,7 @@ struct ath_tx_stats {
|
|||
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
|
||||
* @rx_beacons: No. of beacons received.
|
||||
* @rx_frags: No. of rx-fragements received.
|
||||
* @rx_spectral: No of spectral packets received.
|
||||
*/
|
||||
struct ath_rx_stats {
|
||||
u32 rx_pkts_all;
|
||||
|
@ -237,6 +238,7 @@ struct ath_rx_stats {
|
|||
u32 rx_too_many_frags_err;
|
||||
u32 rx_beacons;
|
||||
u32 rx_frags;
|
||||
u32 rx_spectral;
|
||||
};
|
||||
|
||||
struct ath_stats {
|
||||
|
|
|
@ -497,6 +497,13 @@ static void ath9k_init_misc(struct ath_softc *sc)
|
|||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
|
||||
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
|
||||
|
||||
sc->spec_config.enabled = 0;
|
||||
sc->spec_config.short_repeat = true;
|
||||
sc->spec_config.count = 8;
|
||||
sc->spec_config.endless = false;
|
||||
sc->spec_config.period = 0xFF;
|
||||
sc->spec_config.fft_period = 0xF;
|
||||
}
|
||||
|
||||
static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
|
||||
|
@ -915,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
|
|||
|
||||
ath9k_eeprom_release(sc);
|
||||
|
||||
if (sc->rfs_chan_spec_scan) {
|
||||
if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
|
||||
relay_close(sc->rfs_chan_spec_scan);
|
||||
sc->rfs_chan_spec_scan = NULL;
|
||||
}
|
||||
|
|
|
@ -605,13 +605,13 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
|||
* reported, then decryption and MIC errors are irrelevant,
|
||||
* the frame is going to be dropped either way
|
||||
*/
|
||||
if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
rs->rs_status |= ATH9K_RXERR_PHY;
|
||||
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
|
||||
rs->rs_phyerr = phyerr;
|
||||
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
} else if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
else if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
rs->rs_status |= ATH9K_RXERR_MIC;
|
||||
|
|
|
@ -1099,45 +1099,34 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
|
|||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_spec_scan param;
|
||||
|
||||
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
||||
ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NOTE: this will generate a few samples ...
|
||||
*
|
||||
* TODO: review default parameters, and/or define an interface to set
|
||||
* them.
|
||||
*/
|
||||
param.enabled = 1;
|
||||
param.short_repeat = true;
|
||||
param.count = 8;
|
||||
param.endless = false;
|
||||
param.period = 0xFF;
|
||||
param.fft_period = 0xF;
|
||||
|
||||
switch (spectral_mode) {
|
||||
case SPECTRAL_DISABLED:
|
||||
param.enabled = 0;
|
||||
sc->spec_config.enabled = 0;
|
||||
break;
|
||||
case SPECTRAL_BACKGROUND:
|
||||
/* send endless samples.
|
||||
* TODO: is this really useful for "background"?
|
||||
*/
|
||||
param.endless = 1;
|
||||
sc->spec_config.endless = 1;
|
||||
sc->spec_config.enabled = 1;
|
||||
break;
|
||||
case SPECTRAL_CHANSCAN:
|
||||
break;
|
||||
case SPECTRAL_MANUAL:
|
||||
sc->spec_config.endless = 0;
|
||||
sc->spec_config.enabled = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_ops(ah)->spectral_scan_config(ah, ¶m);
|
||||
ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
sc->spectral_mode = spectral_mode;
|
||||
|
|
|
@ -474,8 +474,6 @@ void ath_mci_cleanup(struct ath_softc *sc)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_mci_coex *mci = &sc->mci_coex;
|
||||
struct ath_mci_buf *buf = &mci->sched_buf;
|
||||
|
||||
ar9003_mci_cleanup(ah);
|
||||
|
||||
|
|
|
@ -1016,18 +1016,20 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
|||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
static s8 fix_rssi_inv_only(u8 rssi_val)
|
||||
{
|
||||
if (rssi_val == 128)
|
||||
rssi_val = 0;
|
||||
return (s8) rssi_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
/* returns 1 if this was a spectral frame, even if not handled. */
|
||||
static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
{
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
u8 bins[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 *vdata = (u8 *)hdr;
|
||||
|
@ -1035,7 +1037,8 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
struct ath_radar_info *radar_info;
|
||||
struct ath_ht20_mag_info *mag_info;
|
||||
int len = rs->rs_datalen;
|
||||
int i, dc_pos;
|
||||
int dc_pos;
|
||||
u16 length, max_magnitude;
|
||||
|
||||
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
|
||||
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
|
||||
|
@ -1044,7 +1047,14 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* check if spectral scan bit is set. This does not have to be checked
|
||||
* if received through a SPECTRAL phy error, but shouldn't hurt.
|
||||
*/
|
||||
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
|
||||
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
|
||||
return 0;
|
||||
|
||||
/* Variation in the data length is possible and will be fixed later.
|
||||
* Note that we only support HT20 for now.
|
||||
|
@ -1053,19 +1063,13 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
*/
|
||||
if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
|
||||
(len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
|
||||
return;
|
||||
|
||||
/* check if spectral scan bit is set. This does not have to be checked
|
||||
* if received through a SPECTRAL phy error, but shouldn't hurt.
|
||||
*/
|
||||
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
|
||||
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
|
||||
fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
fft_sample.tlv.length = __cpu_to_be16(length);
|
||||
|
||||
fft_sample.freq = ah->curchan->chan->center_freq;
|
||||
fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
|
||||
fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
|
||||
fft_sample.noise = ah->noise;
|
||||
|
||||
|
@ -1093,7 +1097,7 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DC value (value in the middle) is the blind spot of the spectral
|
||||
|
@ -1105,19 +1109,41 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
/* mag data is at the end of the frame, in front of radar_info */
|
||||
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
|
||||
|
||||
/* Apply exponent and grab further auxiliary information. */
|
||||
for (i = 0; i < SPECTRAL_HT20_NUM_BINS; i++)
|
||||
fft_sample.data[i] = bins[i] << mag_info->max_exp;
|
||||
/* copy raw bins without scaling them */
|
||||
memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
|
||||
fft_sample.max_exp = mag_info->max_exp & 0xf;
|
||||
|
||||
fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
fft_sample.max_magnitude = __cpu_to_be16(max_magnitude);
|
||||
fft_sample.max_index = spectral_max_index(mag_info->all_bins);
|
||||
fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
|
||||
fft_sample.tsf = tsf;
|
||||
fft_sample.tsf = __cpu_to_be64(tsf);
|
||||
|
||||
ath_debug_send_fft_sample(sc, &fft_sample.tlv);
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ath9k_apply_ampdu_details(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
if (rs->rs_isaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
|
||||
|
||||
rxs->ampdu_reference = sc->rx.ampdu_ref;
|
||||
|
||||
if (!rs->rs_moreaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_IS_LAST;
|
||||
sc->rx.ampdu_ref++;
|
||||
}
|
||||
|
||||
if (rs->rs_flags & ATH9K_RX_DELIM_CRC_PRE)
|
||||
rxs->flag |= RX_FLAG_AMPDU_DELIM_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
|
@ -1202,8 +1228,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
|
||||
rxs->mactime += 0x100000000ULL;
|
||||
|
||||
if ((rs.rs_status & ATH9K_RXERR_PHY))
|
||||
ath_process_fft(sc, hdr, &rs, rxs->mactime);
|
||||
if (rs.rs_status & ATH9K_RXERR_PHY) {
|
||||
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
|
||||
RX_STAT_INC(rx_spectral);
|
||||
goto requeue_drop_frag;
|
||||
}
|
||||
}
|
||||
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
|
@ -1320,6 +1350,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
|
||||
ath_ant_comb_scan(sc, &rs);
|
||||
|
||||
ath9k_apply_ampdu_details(sc, &rs, rxs);
|
||||
|
||||
ieee80211_rx(hw, skb);
|
||||
|
||||
requeue_drop_frag:
|
||||
|
|
|
@ -204,7 +204,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
}
|
||||
|
||||
/* FW don't support scan after connection attempt */
|
||||
|
@ -228,8 +227,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
}
|
||||
/* 0-based channel indexes */
|
||||
cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
|
||||
wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch,
|
||||
request->channels[i]->center_freq);
|
||||
wil_dbg_misc(wil, "Scan for ch %d : %d MHz\n", ch,
|
||||
request->channels[i]->center_freq);
|
||||
}
|
||||
|
||||
return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
|
||||
|
@ -425,8 +424,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
|
||||
channel->center_freq, info->privacy ? "secure" : "open");
|
||||
wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
|
||||
channel->center_freq, info->privacy ? "secure" : "open");
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
info->ssid, info->ssid_len);
|
||||
|
||||
|
|
|
@ -38,7 +38,9 @@
|
|||
#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE
|
||||
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
|
||||
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
|
||||
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT)
|
||||
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \
|
||||
ISR_MISC_MBOX_EVT | \
|
||||
ISR_MISC_FW_ERROR)
|
||||
|
||||
#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
|
||||
BIT_DMA_PSEUDO_CAUSE_TX | \
|
||||
|
@ -50,7 +52,6 @@
|
|||
|
||||
static inline void wil_icr_clear(u32 x, void __iomem *addr)
|
||||
{
|
||||
|
||||
}
|
||||
#else /* defined(CONFIG_WIL6210_ISR_COR) */
|
||||
/* configure to Write-1-to-Clear mode */
|
||||
|
@ -94,7 +95,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
|
|||
|
||||
static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
|
||||
HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
|
||||
|
@ -125,7 +126,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
|
|||
|
||||
static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
set_bit(wil_status_irqen, &wil->status);
|
||||
|
||||
|
@ -135,7 +136,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
|
|||
|
||||
void wil6210_disable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
wil6210_mask_irq_tx(wil);
|
||||
wil6210_mask_irq_rx(wil);
|
||||
|
@ -145,7 +146,7 @@ void wil6210_disable_irq(struct wil6210_priv *wil)
|
|||
|
||||
void wil6210_enable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICC));
|
||||
|
@ -167,7 +168,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
|||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: RX\n");
|
||||
|
@ -177,7 +178,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
|||
wil6210_mask_irq_rx(wil);
|
||||
|
||||
if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
|
||||
wil_dbg_IRQ(wil, "RX done\n");
|
||||
wil_dbg_irq(wil, "RX done\n");
|
||||
isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
|
||||
wil_rx_handle(wil);
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
|||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: TX\n");
|
||||
|
@ -208,13 +209,13 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
|||
|
||||
if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
|
||||
uint i;
|
||||
wil_dbg_IRQ(wil, "TX done\n");
|
||||
wil_dbg_irq(wil, "TX done\n");
|
||||
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
|
||||
for (i = 0; i < 24; i++) {
|
||||
u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i);
|
||||
if (isr & mask) {
|
||||
isr &= ~mask;
|
||||
wil_dbg_IRQ(wil, "TX done(%i)\n", i);
|
||||
wil_dbg_irq(wil, "TX done(%i)\n", i);
|
||||
wil_tx_complete(wil, i);
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +229,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void wil_notify_fw_error(struct wil6210_priv *wil)
|
||||
{
|
||||
struct device *dev = &wil_to_ndev(wil)->dev;
|
||||
char *envp[3] = {
|
||||
[0] = "SOURCE=wil6210",
|
||||
[1] = "EVENT=FW_ERROR",
|
||||
[2] = NULL,
|
||||
};
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
|
@ -235,7 +247,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
HOSTADDR(RGF_DMA_EP_MISC_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: MISC\n");
|
||||
|
@ -244,8 +256,15 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
|
||||
wil6210_mask_irq_misc(wil);
|
||||
|
||||
if (isr & ISR_MISC_FW_ERROR) {
|
||||
wil_dbg_irq(wil, "IRQ: Firmware error\n");
|
||||
clear_bit(wil_status_fwready, &wil->status);
|
||||
wil_notify_fw_error(wil);
|
||||
isr &= ~ISR_MISC_FW_ERROR;
|
||||
}
|
||||
|
||||
if (isr & ISR_MISC_FW_READY) {
|
||||
wil_dbg_IRQ(wil, "IRQ: FW ready\n");
|
||||
wil_dbg_irq(wil, "IRQ: FW ready\n");
|
||||
/**
|
||||
* Actual FW ready indicated by the
|
||||
* WMI_FW_READY_EVENTID
|
||||
|
@ -268,10 +287,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
|
|||
struct wil6210_priv *wil = cookie;
|
||||
u32 isr = wil->isr_misc;
|
||||
|
||||
wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
|
||||
|
||||
if (isr & ISR_MISC_MBOX_EVT) {
|
||||
wil_dbg_IRQ(wil, "MBOX event\n");
|
||||
wil_dbg_irq(wil, "MBOX event\n");
|
||||
wmi_recv_cmd(wil);
|
||||
isr &= ~ISR_MISC_MBOX_EVT;
|
||||
}
|
||||
|
@ -293,7 +312,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
|
|||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
|
||||
wil_dbg_IRQ(wil, "Thread IRQ\n");
|
||||
wil_dbg_irq(wil, "Thread IRQ\n");
|
||||
/* Discover real IRQ cause */
|
||||
if (wil->isr_misc)
|
||||
wil6210_irq_misc_thread(irq, cookie);
|
||||
|
@ -370,6 +389,8 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
|||
if (wil6210_debug_irq_mask(wil, pseudo_cause))
|
||||
return IRQ_NONE;
|
||||
|
||||
wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause);
|
||||
|
||||
wil6210_mask_irq_pseudo(wil);
|
||||
|
||||
/* Discover real IRQ cause
|
||||
|
@ -401,8 +422,6 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
|||
if (rc != IRQ_WAKE_THREAD)
|
||||
wil6210_unmask_irq_pseudo(wil);
|
||||
|
||||
wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
|||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
wil_link_off(wil);
|
||||
clear_bit(wil_status_fwconnected, &wil->status);
|
||||
|
@ -80,11 +80,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
|||
GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++)
|
||||
wil_vring_fini_tx(wil, i);
|
||||
|
||||
clear_bit(wil_status_dontscan, &wil->status);
|
||||
}
|
||||
|
||||
static void wil_disconnect_worker(struct work_struct *work)
|
||||
|
@ -99,7 +101,7 @@ static void wil_connect_timer_fn(ulong x)
|
|||
{
|
||||
struct wil6210_priv *wil = (void *)x;
|
||||
|
||||
wil_dbg(wil, "Connect timeout\n");
|
||||
wil_dbg_misc(wil, "Connect timeout\n");
|
||||
|
||||
/* reschedule to thread context - disconnect won't
|
||||
* run from atomic context
|
||||
|
@ -107,9 +109,18 @@ static void wil_connect_timer_fn(ulong x)
|
|||
schedule_work(&wil->disconnect_worker);
|
||||
}
|
||||
|
||||
static void wil_cache_mbox_regs(struct wil6210_priv *wil)
|
||||
{
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
}
|
||||
|
||||
int wil_priv_init(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
mutex_init(&wil->mutex);
|
||||
mutex_init(&wil->wmi_mutex);
|
||||
|
@ -136,11 +147,7 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
wil_cache_mbox_regs(wil);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,7 +169,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
|
|||
|
||||
static void wil_target_reset(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg(wil, "Resetting...\n");
|
||||
wil_dbg_misc(wil, "Resetting...\n");
|
||||
|
||||
/* register write */
|
||||
#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a))
|
||||
|
@ -202,7 +209,7 @@ static void wil_target_reset(struct wil6210_priv *wil)
|
|||
|
||||
msleep(2000);
|
||||
|
||||
wil_dbg(wil, "Reset completed\n");
|
||||
wil_dbg_misc(wil, "Reset completed\n");
|
||||
|
||||
#undef W
|
||||
#undef S
|
||||
|
@ -225,8 +232,8 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
|
|||
wil_err(wil, "Firmware not ready\n");
|
||||
return -ETIME;
|
||||
} else {
|
||||
wil_dbg(wil, "FW ready after %d ms\n",
|
||||
jiffies_to_msecs(to-left));
|
||||
wil_dbg_misc(wil, "FW ready after %d ms\n",
|
||||
jiffies_to_msecs(to-left));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -243,14 +250,14 @@ int wil_reset(struct wil6210_priv *wil)
|
|||
cancel_work_sync(&wil->disconnect_worker);
|
||||
wil6210_disconnect(wil, NULL);
|
||||
|
||||
wmi_event_flush(wil);
|
||||
|
||||
flush_workqueue(wil->wmi_wq);
|
||||
flush_workqueue(wil->wmi_wq_conn);
|
||||
|
||||
wil6210_disable_irq(wil);
|
||||
wil->status = 0;
|
||||
|
||||
wmi_event_flush(wil);
|
||||
|
||||
flush_workqueue(wil->wmi_wq_conn);
|
||||
flush_workqueue(wil->wmi_wq);
|
||||
|
||||
/* TODO: put MAC in reset */
|
||||
wil_target_reset(wil);
|
||||
|
||||
|
@ -258,11 +265,7 @@ int wil_reset(struct wil6210_priv *wil)
|
|||
wil->pending_connect_cid = -1;
|
||||
INIT_COMPLETION(wil->wmi_ready);
|
||||
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
wil_cache_mbox_regs(wil);
|
||||
|
||||
/* TODO: release MAC reset */
|
||||
wil6210_enable_irq(wil);
|
||||
|
@ -278,7 +281,7 @@ void wil_link_on(struct wil6210_priv *wil)
|
|||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
netif_carrier_on(ndev);
|
||||
netif_tx_wake_all_queues(ndev);
|
||||
|
@ -288,7 +291,7 @@ void wil_link_off(struct wil6210_priv *wil)
|
|||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
netif_carrier_off(ndev);
|
||||
|
@ -311,27 +314,27 @@ static int __wil_up(struct wil6210_priv *wil)
|
|||
wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC);
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wil_dbg(wil, "type: STATION\n");
|
||||
wil_dbg_misc(wil, "type: STATION\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
wil_dbg(wil, "type: AP\n");
|
||||
wil_dbg_misc(wil, "type: AP\n");
|
||||
bi = 100;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
wil_dbg(wil, "type: P2P_CLIENT\n");
|
||||
wil_dbg_misc(wil, "type: P2P_CLIENT\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
wil_dbg(wil, "type: P2P_GO\n");
|
||||
wil_dbg_misc(wil, "type: P2P_GO\n");
|
||||
bi = 100;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
wil_dbg(wil, "type: Monitor\n");
|
||||
wil_dbg_misc(wil, "type: Monitor\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
|
||||
|
@ -354,7 +357,7 @@ static int __wil_up(struct wil6210_priv *wil)
|
|||
wmi_set_channel(wil, channel->hw_value);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
/* MAC address - pre-requisite for other commands */
|
||||
|
|
|
@ -35,37 +35,12 @@ static int wil_stop(struct net_device *ndev)
|
|||
return wil_down(wil);
|
||||
}
|
||||
|
||||
/*
|
||||
* AC to queue mapping
|
||||
*
|
||||
* AC_VO -> queue 3
|
||||
* AC_VI -> queue 2
|
||||
* AC_BE -> queue 1
|
||||
* AC_BK -> queue 0
|
||||
*/
|
||||
static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb)
|
||||
{
|
||||
static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
|
||||
struct wil6210_priv *wil = ndev_to_wil(ndev);
|
||||
u16 rc;
|
||||
|
||||
skb->priority = cfg80211_classify8021d(skb);
|
||||
|
||||
rc = wil_1d_to_queue[skb->priority];
|
||||
|
||||
wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority,
|
||||
(int)rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct net_device_ops wil_netdev_ops = {
|
||||
.ndo_open = wil_open,
|
||||
.ndo_stop = wil_stop,
|
||||
.ndo_start_xmit = wil_start_xmit,
|
||||
.ndo_select_queue = wil_select_queue,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
||||
|
@ -97,7 +72,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
|||
ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
|
||||
cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
|
||||
|
||||
ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1);
|
||||
ndev = alloc_netdev(0, "wlan%d", ether_setup);
|
||||
if (!ndev) {
|
||||
dev_err(dev, "alloc_netdev_mqs failed\n");
|
||||
rc = -ENOMEM;
|
||||
|
|
|
@ -53,7 +53,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
|||
}
|
||||
wil->n_msi = use_msi;
|
||||
if (wil->n_msi) {
|
||||
wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi);
|
||||
wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
|
||||
rc = pci_enable_msi_block(pdev, wil->n_msi);
|
||||
if (rc && (wil->n_msi == 3)) {
|
||||
wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
|
||||
|
@ -65,7 +65,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
|||
wil->n_msi = 0;
|
||||
}
|
||||
} else {
|
||||
wil_dbg(wil, "MSI interrupts disabled, use INTx\n");
|
||||
wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
|
||||
}
|
||||
|
||||
rc = wil6210_init_irq(wil, pdev->irq);
|
||||
|
|
|
@ -100,8 +100,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
|
|||
d->dma.status = TX_DMA_STATUS_DU;
|
||||
}
|
||||
|
||||
wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
|
||||
vring->va, (unsigned long long)vring->pa, vring->ctx);
|
||||
wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
|
||||
vring->va, (unsigned long long)vring->pa, vring->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -353,8 +353,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
|||
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
|
||||
wil_rx_add_radiotap_header(wil, skb, d);
|
||||
|
||||
wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
|
||||
wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
wil_vring_advance_head(vring, 1);
|
||||
|
@ -369,7 +369,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
|||
*/
|
||||
ftype = wil_rxdesc_ftype(d) << 2;
|
||||
if (ftype != IEEE80211_FTYPE_DATA) {
|
||||
wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
/* TODO: process it */
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
|
@ -430,6 +430,8 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
|||
int rc;
|
||||
unsigned int len = skb->len;
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (in_interrupt())
|
||||
rc = netif_rx(skb);
|
||||
else
|
||||
|
@ -459,13 +461,11 @@ void wil_rx_handle(struct wil6210_priv *wil)
|
|||
wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
|
||||
return;
|
||||
}
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
while (NULL != (skb = wil_vring_reap_rx(wil, v))) {
|
||||
wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
skb->dev = ndev;
|
||||
skb_reset_mac_header(skb);
|
||||
|
@ -484,53 +484,18 @@ void wil_rx_handle(struct wil6210_priv *wil)
|
|||
|
||||
int wil_rx_init(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct vring *vring = &wil->vring_rx;
|
||||
int rc;
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = WMI_RX_CHAIN_ADD,
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
},
|
||||
.mid = 0, /* TODO - what is it? */
|
||||
.decap_trans_type = WMI_DECAP_TYPE_802_3,
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event evt;
|
||||
} __packed evt;
|
||||
|
||||
vring->size = WIL6210_RX_RING_SIZE;
|
||||
rc = wil_vring_alloc(wil, vring);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
||||
cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size);
|
||||
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
struct ieee80211_channel *ch = wdev->preset_chandef.chan;
|
||||
|
||||
cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
|
||||
if (ch)
|
||||
cmd.sniffer_cfg.channel = ch->hw_value - 1;
|
||||
cmd.sniffer_cfg.phy_info_mode =
|
||||
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
|
||||
cmd.sniffer_cfg.phy_support =
|
||||
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
|
||||
? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
|
||||
}
|
||||
/* typical time for secure PCP is 840ms */
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
|
||||
rc = wmi_rx_chain_add(wil, vring);
|
||||
if (rc)
|
||||
goto err_free;
|
||||
|
||||
vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
|
||||
|
||||
wil_dbg(wil, "Rx init: status %d tail 0x%08x\n",
|
||||
le32_to_cpu(evt.evt.status), vring->hwtail);
|
||||
|
||||
rc = wil_rx_refill(wil, vring->size);
|
||||
if (rc)
|
||||
goto err_free;
|
||||
|
@ -546,25 +511,8 @@ void wil_rx_fini(struct wil6210_priv *wil)
|
|||
{
|
||||
struct vring *vring = &wil->vring_rx;
|
||||
|
||||
if (vring->va) {
|
||||
int rc;
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = cpu_to_le32(WMI_RX_CHAIN_DEL),
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
},
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event cfg;
|
||||
} __packed wmi_rx_cfg_reply;
|
||||
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID,
|
||||
&wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply),
|
||||
100);
|
||||
if (vring->va)
|
||||
wil_vring_free(wil, vring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
||||
|
@ -617,6 +565,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|||
if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
|
||||
wil_err(wil, "Tx config failed, status 0x%02x\n",
|
||||
reply.cmd.status);
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
||||
|
@ -689,7 +638,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
|||
uint i = swhead;
|
||||
dma_addr_t pa;
|
||||
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
|
||||
if (avail < vring->size/8)
|
||||
netif_tx_stop_all_queues(wil_to_ndev(wil));
|
||||
|
@ -706,9 +655,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
|||
pa = dma_map_single(dev, skb->data,
|
||||
skb_headlen(skb), DMA_TO_DEVICE);
|
||||
|
||||
wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
|
||||
wil_dbg_txrx(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
|
||||
skb->data, (unsigned long long)pa);
|
||||
wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
if (unlikely(dma_mapping_error(dev, pa)))
|
||||
|
@ -737,12 +686,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
|||
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
|
||||
d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
|
||||
|
||||
wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
/* advance swhead */
|
||||
wil_vring_advance_head(vring, nr_frags + 1);
|
||||
wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
|
||||
/* hold reference to skb
|
||||
* to prevent skb release before accounting
|
||||
|
@ -775,7 +724,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
struct vring *vring;
|
||||
int rc;
|
||||
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
if (!test_bit(wil_status_fwready, &wil->status)) {
|
||||
wil_err(wil, "FW not ready\n");
|
||||
goto drop;
|
||||
|
@ -802,15 +751,13 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
}
|
||||
switch (rc) {
|
||||
case 0:
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
/* statistics will be updated on the tx_complete */
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
case -ENOMEM:
|
||||
return NETDEV_TX_BUSY;
|
||||
default:
|
||||
; /* goto drop; */
|
||||
break;
|
||||
break; /* goto drop; */
|
||||
}
|
||||
drop:
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
|
@ -827,6 +774,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
*/
|
||||
void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
struct vring *vring = &wil->vring_tx[ringid];
|
||||
|
||||
|
@ -835,7 +783,7 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
|||
return;
|
||||
}
|
||||
|
||||
wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid);
|
||||
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
||||
|
||||
while (!wil_vring_is_empty(vring)) {
|
||||
volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
|
||||
|
@ -844,16 +792,23 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
|||
if (!(d->dma.status & TX_DMA_STATUS_DU))
|
||||
break;
|
||||
|
||||
wil_dbg_TXRX(wil,
|
||||
wil_dbg_txrx(wil,
|
||||
"Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
|
||||
vring->swtail, d->dma.length, d->dma.status,
|
||||
d->dma.error);
|
||||
wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
|
||||
skb = vring->ctx[vring->swtail];
|
||||
if (skb) {
|
||||
if (d->dma.error == 0) {
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
} else {
|
||||
ndev->stats.tx_errors++;
|
||||
}
|
||||
|
||||
dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
vring->ctx[vring->swtail] = NULL;
|
||||
|
|
|
@ -36,8 +36,6 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
|||
|
||||
#define WIL6210_MEM_SIZE (2*1024*1024UL)
|
||||
|
||||
#define WIL6210_TX_QUEUES (4)
|
||||
|
||||
#define WIL6210_RX_RING_SIZE (128)
|
||||
#define WIL6210_TX_RING_SIZE (128)
|
||||
#define WIL6210_MAX_TX_RINGS (24)
|
||||
|
@ -101,8 +99,7 @@ struct RGF_ICR {
|
|||
#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */
|
||||
#define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0)
|
||||
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */
|
||||
|
||||
/* Interrupt moderation control */
|
||||
#define RGF_DMA_ITR_CNT_TRSH (0x881c5c)
|
||||
|
@ -121,8 +118,9 @@ struct RGF_ICR {
|
|||
#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2
|
||||
|
||||
/* ISR register bits */
|
||||
#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0
|
||||
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1
|
||||
#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT(0)
|
||||
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT(1)
|
||||
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
|
||||
|
||||
/* Hardware definitions end */
|
||||
|
||||
|
@ -272,17 +270,18 @@ struct wil6210_priv {
|
|||
#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg)
|
||||
#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg)
|
||||
|
||||
#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
|
||||
#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
|
||||
#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
|
||||
#define wil_dbg_irq(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
|
||||
#define wil_dbg_txrx(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
|
||||
#define wil_dbg_wmi(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
|
||||
#define wil_dbg_misc(wil, fmt, arg...) wil_dbg(wil, "DBG[MISC]" fmt, ##arg)
|
||||
|
||||
#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \
|
||||
#define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii)
|
||||
|
||||
#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \
|
||||
#define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
|
@ -328,6 +327,7 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
|
|||
const void *mac_addr, int key_len, const void *key);
|
||||
int wmi_echo(struct wil6210_priv *wil);
|
||||
int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
|
||||
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq);
|
||||
void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include "wil6210.h"
|
||||
#include "txrx.h"
|
||||
#include "wmi.h"
|
||||
|
||||
/**
|
||||
|
@ -186,7 +188,6 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
|
||||
(int)(sizeof(cmd) + len), r->entry_size);
|
||||
return -ERANGE;
|
||||
|
||||
}
|
||||
|
||||
might_sleep();
|
||||
|
@ -213,7 +214,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
}
|
||||
/* next head */
|
||||
next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
|
||||
wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
|
||||
wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
|
||||
/* wait till FW finish with previous command */
|
||||
for (retry = 5; retry > 0; retry--) {
|
||||
r->tail = ioread32(wil->csr + HOST_MBOX +
|
||||
|
@ -234,10 +235,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
}
|
||||
cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
|
||||
/* set command */
|
||||
wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
|
||||
wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
|
||||
wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
|
||||
wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
|
||||
sizeof(cmd), true);
|
||||
wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
len, true);
|
||||
wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
|
||||
wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
|
||||
|
@ -273,7 +274,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
struct wmi_ready_event *evt = d;
|
||||
u32 ver = le32_to_cpu(evt->sw_version);
|
||||
|
||||
wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
|
||||
wil_dbg_wmi(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
|
||||
|
||||
if (!is_valid_ether_addr(ndev->dev_addr)) {
|
||||
memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
|
||||
|
@ -286,7 +287,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
|
||||
int len)
|
||||
{
|
||||
wil_dbg_WMI(wil, "WMI: FW ready\n");
|
||||
wil_dbg_wmi(wil, "WMI: FW ready\n");
|
||||
|
||||
set_bit(wil_status_fwready, &wil->status);
|
||||
/* reuse wmi_ready for the firmware ready indication */
|
||||
|
@ -309,11 +310,11 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
u32 d_len = le32_to_cpu(data->info.len);
|
||||
u16 d_status = le16_to_cpu(data->info.status);
|
||||
|
||||
wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n",
|
||||
wil_dbg_wmi(wil, "MGMT: channel %d MCS %d SNR %d\n",
|
||||
data->info.channel, data->info.mcs, data->info.snr);
|
||||
wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
|
||||
wil_dbg_wmi(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
|
||||
le16_to_cpu(data->info.stype));
|
||||
wil_dbg_WMI(wil, "qid %d mid %d cid %d\n",
|
||||
wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
|
||||
data->info.qid, data->info.mid, data->info.cid);
|
||||
|
||||
if (!channel) {
|
||||
|
@ -329,13 +330,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
|
||||
size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
|
||||
u.beacon.variable);
|
||||
wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap);
|
||||
wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
|
||||
|
||||
bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
|
||||
tsf, cap, bi, ie_buf, ie_len,
|
||||
signal, GFP_KERNEL);
|
||||
if (bss) {
|
||||
wil_dbg_WMI(wil, "Added BSS %pM\n",
|
||||
wil_dbg_wmi(wil, "Added BSS %pM\n",
|
||||
rx_mgmt_frame->bssid);
|
||||
cfg80211_put_bss(bss);
|
||||
} else {
|
||||
|
@ -351,7 +352,7 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
|
|||
struct wmi_scan_complete_event *data = d;
|
||||
bool aborted = (data->status != 0);
|
||||
|
||||
wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
|
||||
wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
|
||||
cfg80211_scan_done(wil->scan_request, aborted);
|
||||
wil->scan_request = NULL;
|
||||
} else {
|
||||
|
@ -386,9 +387,9 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
return;
|
||||
}
|
||||
ch = evt->channel + 1;
|
||||
wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n",
|
||||
wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n",
|
||||
evt->bssid, ch, evt->cid);
|
||||
wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
evt->assoc_info, len - sizeof(*evt), true);
|
||||
|
||||
/* figure out IE's */
|
||||
|
@ -450,14 +451,13 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
|
|||
{
|
||||
struct wmi_disconnect_event *evt = d;
|
||||
|
||||
wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n",
|
||||
wil_dbg_wmi(wil, "Disconnect %pM reason %d proto %d wmi\n",
|
||||
evt->bssid,
|
||||
evt->protocol_reason_status, evt->disconnect_reason);
|
||||
|
||||
wil->sinfo_gen++;
|
||||
|
||||
wil6210_disconnect(wil, evt->bssid);
|
||||
clear_bit(wil_status_dontscan, &wil->status);
|
||||
}
|
||||
|
||||
static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
|
@ -476,7 +476,7 @@ static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector);
|
||||
wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector);
|
||||
wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector);
|
||||
wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n"
|
||||
wil_dbg_wmi(wil, "Link status, MCS %d TSF 0x%016llx\n"
|
||||
"BF status 0x%08x SNR 0x%08x\n"
|
||||
"Tx Tpt %d goodput %d Rx goodput %d\n"
|
||||
"Sectors(rx:tx) my %d:%d peer %d:%d\n",
|
||||
|
@ -501,7 +501,7 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
|
|||
struct sk_buff *skb;
|
||||
struct ethhdr *eth;
|
||||
|
||||
wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len,
|
||||
wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
|
||||
evt->src_mac);
|
||||
|
||||
if (eapol_len > 196) { /* TODO: revisit size limit */
|
||||
|
@ -599,15 +599,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
|
|||
iowrite32(0, wil->csr + HOSTADDR(r->tail) +
|
||||
offsetof(struct wil6210_mbox_ring_desc, sync));
|
||||
/* indicate */
|
||||
wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n",
|
||||
wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
|
||||
le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
|
||||
hdr.flags);
|
||||
if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
|
||||
(len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
|
||||
wil_dbg_WMI(wil, "WMI event 0x%04x\n",
|
||||
wil_dbg_wmi(wil, "WMI event 0x%04x\n",
|
||||
evt->event.wmi.id);
|
||||
}
|
||||
wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
&evt->event.hdr, sizeof(hdr) + len, true);
|
||||
|
||||
/* advance tail */
|
||||
|
@ -623,7 +623,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
|
|||
{
|
||||
int q = queue_work(wil->wmi_wq,
|
||||
&wil->wmi_event_worker);
|
||||
wil_dbg_WMI(wil, "queue_work -> %d\n", q);
|
||||
wil_dbg_wmi(wil, "queue_work -> %d\n", q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -650,7 +650,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
|
|||
cmdid, reply_id, to_msec);
|
||||
rc = -ETIME;
|
||||
} else {
|
||||
wil_dbg_WMI(wil,
|
||||
wil_dbg_wmi(wil,
|
||||
"wmi_call(0x%04x->0x%04x) completed in %d msec\n",
|
||||
cmdid, reply_id,
|
||||
to_msec - jiffies_to_msecs(remain));
|
||||
|
@ -680,7 +680,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
|
|||
|
||||
memcpy(cmd.mac, addr, ETH_ALEN);
|
||||
|
||||
wil_dbg_WMI(wil, "Set MAC %pM\n", addr);
|
||||
wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
|
||||
|
||||
return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
@ -778,7 +778,7 @@ int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
|
|||
|
||||
skb_set_mac_header(skb, 0);
|
||||
eth = eth_hdr(skb);
|
||||
wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
|
||||
wil_dbg_wmi(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
|
||||
if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0)
|
||||
goto found_dest;
|
||||
|
@ -853,11 +853,60 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
|
||||
{
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = WMI_RX_CHAIN_ADD,
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
.ring_mem_base = cpu_to_le64(vring->pa),
|
||||
.ring_size = cpu_to_le16(vring->size),
|
||||
},
|
||||
.mid = 0, /* TODO - what is it? */
|
||||
.decap_trans_type = WMI_DECAP_TYPE_802_3,
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event evt;
|
||||
} __packed evt;
|
||||
int rc;
|
||||
|
||||
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
struct ieee80211_channel *ch = wdev->preset_chandef.chan;
|
||||
|
||||
cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
|
||||
if (ch)
|
||||
cmd.sniffer_cfg.channel = ch->hw_value - 1;
|
||||
cmd.sniffer_cfg.phy_info_mode =
|
||||
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
|
||||
cmd.sniffer_cfg.phy_support =
|
||||
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
|
||||
? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
|
||||
}
|
||||
/* typical time for secure PCP is 840ms */
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
|
||||
|
||||
wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
|
||||
le32_to_cpu(evt.evt.status), vring->hwtail);
|
||||
|
||||
if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
|
||||
rc = -EINVAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wmi_event_flush(struct wil6210_priv *wil)
|
||||
{
|
||||
struct pending_wmi_event *evt, *t;
|
||||
|
||||
wil_dbg_WMI(wil, "%s()\n", __func__);
|
||||
wil_dbg_wmi(wil, "%s()\n", __func__);
|
||||
|
||||
list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
|
||||
list_del(&evt->list);
|
||||
|
@ -899,7 +948,7 @@ static void wmi_event_handle(struct wil6210_priv *wil,
|
|||
wmi_evt_call_handler(wil, id, evt_data,
|
||||
len - sizeof(*wmi));
|
||||
}
|
||||
wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id);
|
||||
wil_dbg_wmi(wil, "Complete WMI 0x%04x\n", id);
|
||||
complete(&wil->wmi_ready);
|
||||
return;
|
||||
}
|
||||
|
@ -964,7 +1013,7 @@ void wmi_connect_worker(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
wil_dbg_WMI(wil, "Configure for connection CID %d\n",
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d\n",
|
||||
wil->pending_connect_cid);
|
||||
|
||||
rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
|
||||
|
|
|
@ -542,9 +542,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
|
||||
if (changed & BSS_CHANGED_ARP_FILTER) {
|
||||
/* Hardware ARP filter address list or state changed */
|
||||
brcms_err(core, "%s: arp filtering: enabled %s, count %d"
|
||||
" (implement)\n", __func__, info->arp_filter_enabled ?
|
||||
"true" : "false", info->arp_addr_cnt);
|
||||
brcms_err(core, "%s: arp filtering: %d addresses"
|
||||
" (implement)\n", __func__, info->arp_addr_cnt);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_QOS) {
|
||||
|
|
|
@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
return;
|
||||
|
@ -1035,26 +1035,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of RB/SKB */
|
||||
rxb->page_dma =
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
rxb->page = page;
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
|
@ -1284,8 +1292,15 @@ il3945_rx_handle(struct il_priv *il)
|
|||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
|
|
|
@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
|
@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get physical address of the RB */
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
BUG_ON(rxb->page);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of the RB */
|
||||
rxb->page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
/* dma address must be no more than 36 bits */
|
||||
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
|
||||
/* and also 256 byte aligned! */
|
||||
BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
|
@ -725,6 +728,16 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
|
|||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
|
||||
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
|
||||
/* We know which subframes of an A-MPDU belong
|
||||
* together since we get a single PHY response
|
||||
* from the firmware for all of them.
|
||||
*/
|
||||
|
||||
rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status.ampdu_reference = il->_4965.ampdu_ref;
|
||||
}
|
||||
|
||||
il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
|
||||
&rx_status);
|
||||
}
|
||||
|
@ -736,6 +749,7 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
|
|||
{
|
||||
struct il_rx_pkt *pkt = rxb_addr(rxb);
|
||||
il->_4965.last_phy_res_valid = true;
|
||||
il->_4965.ampdu_ref++;
|
||||
memcpy(&il->_4965.last_phy_res, pkt->u.raw,
|
||||
sizeof(struct il_rx_phy_res));
|
||||
}
|
||||
|
@ -4281,8 +4295,16 @@ il4965_rx_handle(struct il_priv *il)
|
|||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
|
@ -6573,9 +6595,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
/* extract MAC Address */
|
||||
il4965_eeprom_get_mac(il, il->addresses[0].addr);
|
||||
D_INFO("MAC address: %pM\n", il->addresses[0].addr);
|
||||
|
|
|
@ -1748,7 +1748,6 @@ static void
|
|||
il4965_post_associate(struct il_priv *il)
|
||||
{
|
||||
struct ieee80211_vif *vif = il->vif;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vif || !il->is_open)
|
||||
|
@ -1759,8 +1758,6 @@ il4965_post_associate(struct il_priv *il)
|
|||
|
||||
il_scan_cancel_timeout(il, 200);
|
||||
|
||||
conf = &il->hw->conf;
|
||||
|
||||
il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
il_commit_rxon(il);
|
||||
|
||||
|
|
|
@ -1134,8 +1134,9 @@ struct il_wep_cmd {
|
|||
#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1)
|
||||
#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
|
||||
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0xf0
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_POS 4
|
||||
#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7)
|
||||
|
||||
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
|
||||
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
|
||||
|
|
|
@ -1356,6 +1356,7 @@ struct il_priv {
|
|||
struct {
|
||||
struct il_rx_phy_res last_phy_res;
|
||||
bool last_phy_res_valid;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
|
||||
|
|
|
@ -43,8 +43,20 @@ config IWLWIFI
|
|||
module will be called iwlwifi.
|
||||
|
||||
config IWLDVM
|
||||
tristate "Intel Wireless WiFi"
|
||||
tristate "Intel Wireless WiFi DVM Firmware support"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This is the driver supporting the DVM firmware which is
|
||||
currently the only firmware available for existing devices.
|
||||
|
||||
config IWLMVM
|
||||
tristate "Intel Wireless WiFi MVM Firmware support"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This is the driver supporting the MVM firmware which is
|
||||
currently only available for 7000 series devices.
|
||||
|
||||
Say yes if you have such a device.
|
||||
|
||||
menu "Debugging Options"
|
||||
depends on IWLWIFI
|
||||
|
|
|
@ -5,8 +5,10 @@ iwlwifi-objs += iwl-drv.o
|
|||
iwlwifi-objs += iwl-debug.o
|
||||
iwlwifi-objs += iwl-notif-wait.o
|
||||
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
|
||||
iwlwifi-objs += pcie/7000.o
|
||||
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
|
||||
|
@ -15,5 +17,6 @@ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
|
|||
|
||||
|
||||
obj-$(CONFIG_IWLDVM) += dvm/
|
||||
obj-$(CONFIG_IWLMVM) += mvm/
|
||||
|
||||
CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -459,14 +459,12 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
|||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true)) {
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true, &flags)) {
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
|
||||
status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
iwl_trans_release_nic_access(priv->trans, &flags);
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (ret == 0) {
|
||||
|
@ -1154,6 +1152,7 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_rssi_event rssi_event)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -353,11 +353,8 @@ 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->trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(priv->trans, false)) {
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(priv->trans, false, ®_flags))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
|
@ -388,8 +385,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
|||
}
|
||||
}
|
||||
/* Allow device to power down */
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
iwl_trans_release_nic_access(priv->trans, ®_flags);
|
||||
}
|
||||
|
||||
static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
||||
|
@ -1717,9 +1713,8 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false))
|
||||
goto out_unlock;
|
||||
if (!iwl_trans_grab_nic_access(trans, false, ®_flags))
|
||||
return pos;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
|
@ -1757,9 +1752,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
}
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_trans_release_nic_access(trans);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
|
||||
iwl_trans_release_nic_access(trans, ®_flags);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -1991,13 +1984,13 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
/* SKU Control */
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
|
||||
/* write radio config values to register */
|
||||
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
||||
|
@ -2009,10 +2002,11 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|||
priv->nvm_data->radio_cfg_dash <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
|
||||
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val);
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH,
|
||||
reg_val);
|
||||
|
||||
IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
|
||||
priv->nvm_data->radio_cfg_type,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 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
|
||||
|
@ -411,8 +411,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
|
|||
* BT traffic, as they would just be disrupted by BT.
|
||||
*/
|
||||
if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) {
|
||||
IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n",
|
||||
priv->bt_traffic_load);
|
||||
IWL_DEBUG_COEX(priv,
|
||||
"BT traffic (%d), no aggregation allowed\n",
|
||||
priv->bt_traffic_load);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portionhelp of the ieee80211 subsystem header files.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -185,10 +185,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
|||
priv->thermal_throttle.ct_kill_toggle = true;
|
||||
}
|
||||
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, false))
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, false, &flags))
|
||||
iwl_trans_release_nic_access(priv->trans, &flags);
|
||||
|
||||
/* Reschedule the ct_kill timer to occur in
|
||||
* CT_KILL_EXIT_DURATION seconds to ensure we get a
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -83,6 +83,7 @@ enum iwl_device_family {
|
|||
IWL_DEVICE_FAMILY_6030,
|
||||
IWL_DEVICE_FAMILY_6050,
|
||||
IWL_DEVICE_FAMILY_6150,
|
||||
IWL_DEVICE_FAMILY_7000,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
|
@ -116,6 +116,7 @@ do { \
|
|||
#define IWL_DL_HCMD 0x00000004
|
||||
#define IWL_DL_STATE 0x00000008
|
||||
/* 0x000000F0 - 0x00000010 */
|
||||
#define IWL_DL_TE 0x00000020
|
||||
#define IWL_DL_EEPROM 0x00000040
|
||||
#define IWL_DL_RADIO 0x00000080
|
||||
/* 0x00000F00 - 0x00000100 */
|
||||
|
@ -156,6 +157,7 @@ do { \
|
|||
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
|
||||
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
|
||||
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
|
||||
#define IWL_DEBUG_TE(p, f, a...) IWL_DEBUG(p, IWL_DL_TE, f, ## a)
|
||||
#define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a)
|
||||
#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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 - 2013 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 - 2013 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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -139,8 +139,10 @@ struct iwl_drv {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define DVM_OP_MODE 0
|
||||
#define MVM_OP_MODE 1
|
||||
enum {
|
||||
DVM_OP_MODE = 0,
|
||||
MVM_OP_MODE = 1,
|
||||
};
|
||||
|
||||
/* Protects the table contents, i.e. the ops pointer & drv list */
|
||||
static struct mutex iwlwifi_opmode_table_mtx;
|
||||
|
@ -149,8 +151,8 @@ static struct iwlwifi_opmode_table {
|
|||
const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */
|
||||
struct list_head drv; /* list of devices using this op_mode */
|
||||
} iwlwifi_opmode_table[] = { /* ops set when driver is initialized */
|
||||
{ .name = "iwldvm", .ops = NULL },
|
||||
{ .name = "iwlmvm", .ops = NULL },
|
||||
[DVM_OP_MODE] = { .name = "iwldvm", .ops = NULL },
|
||||
[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -268,7 +270,7 @@ struct fw_sec_parsing {
|
|||
*/
|
||||
struct iwl_tlv_calib_data {
|
||||
__le32 ucode_type;
|
||||
__le64 calib;
|
||||
struct iwl_tlv_calib_ctrl calib;
|
||||
} __packed;
|
||||
|
||||
struct iwl_firmware_pieces {
|
||||
|
@ -358,7 +360,11 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
|
|||
ucode_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
drv->fw.default_calib[ucode_type] = le64_to_cpu(def_calib->calib);
|
||||
drv->fw.default_calib[ucode_type].flow_trigger =
|
||||
def_calib->calib.flow_trigger;
|
||||
drv->fw.default_calib[ucode_type].event_trigger =
|
||||
def_calib->calib.event_trigger;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -959,7 +965,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
release_firmware(ucode_raw);
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
op = &iwlwifi_opmode_table[DVM_OP_MODE];
|
||||
if (fw->mvm_fw)
|
||||
op = &iwlwifi_opmode_table[MVM_OP_MODE];
|
||||
else
|
||||
op = &iwlwifi_opmode_table[DVM_OP_MODE];
|
||||
|
||||
/* add this device to the list of devices using this op_mode */
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -66,7 +66,7 @@
|
|||
/* for all modules */
|
||||
#define DRV_NAME "iwlwifi"
|
||||
#define IWLWIFI_VERSION "in-tree:"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2003-2012 Intel Corporation"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2003-2013 Intel Corporation"
|
||||
#define DRV_AUTHOR "<ilw@linux.intel.com>"
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -703,9 +703,9 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
|||
return n_channels;
|
||||
}
|
||||
|
||||
static int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band)
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band)
|
||||
{
|
||||
struct ieee80211_channel *chan = &data->channels[0];
|
||||
int n = 0, idx = 0;
|
||||
|
@ -728,10 +728,10 @@ static int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
|||
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||
|
||||
static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
int max_bit_rate = 0;
|
||||
u8 rx_chains;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -126,4 +126,13 @@ static inline void iwl_free_nvm_data(struct iwl_nvm_data *data)
|
|||
int iwl_nvm_check_version(struct iwl_nvm_data *data,
|
||||
struct iwl_trans *trans);
|
||||
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band);
|
||||
|
||||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band);
|
||||
|
||||
#endif /* __iwl_eeprom_parse_h__ */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -414,6 +414,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
|||
* uCode/driver must write "1" in order to clear this flag
|
||||
*/
|
||||
#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
|
||||
#define FH_TSSR_TX_MSG_CONFIG_REG (FH_TSSR_LOWER_BOUND + 0x008)
|
||||
|
||||
#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -139,6 +139,19 @@ struct fw_img {
|
|||
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
|
||||
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
|
||||
|
||||
/*
|
||||
* Calibration control struct.
|
||||
* Sent as part of the phy configuration command.
|
||||
* @flow_trigger: bitmap for which calibrations to perform according to
|
||||
* flow triggers.
|
||||
* @event_trigger: bitmap for which calibrations to perform according to
|
||||
* event triggers.
|
||||
*/
|
||||
struct iwl_tlv_calib_ctrl {
|
||||
__le32 flow_trigger;
|
||||
__le32 event_trigger;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
|
@ -153,6 +166,7 @@ struct fw_img {
|
|||
* @inst_evtlog_ptr: event log offset for runtime ucode.
|
||||
* @inst_evtlog_size: event log size for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offfset for runtime ucode.
|
||||
* @mvm_fw: indicates this is MVM firmware
|
||||
*/
|
||||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
|
@ -168,7 +182,7 @@ struct iwl_fw {
|
|||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
|
||||
u64 default_calib[IWL_UCODE_TYPE_MAX];
|
||||
struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX];
|
||||
u32 phy_config;
|
||||
|
||||
bool mvm_fw;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
|
@ -35,54 +35,6 @@
|
|||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
|
||||
}
|
||||
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
|
||||
}
|
||||
|
||||
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
__iwl_set_bit(trans, reg, mask);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bit);
|
||||
|
||||
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
__iwl_clear_bit(trans, reg, mask);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bit);
|
||||
|
||||
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 v;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
WARN_ON_ONCE(value & ~mask);
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
v = iwl_read32(trans, reg);
|
||||
v &= ~mask;
|
||||
v |= value;
|
||||
iwl_write32(trans, reg, v);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_mask);
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
|
@ -103,13 +55,10 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
|||
{
|
||||
u32 value = 0x5a5a5a5a;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
value = iwl_read32(trans, reg);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -119,12 +68,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
iwl_write32(trans, reg, value);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_direct32);
|
||||
|
||||
|
@ -162,12 +109,10 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
|||
unsigned long flags;
|
||||
u32 val = 0x5a5a5a5a;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_prph);
|
||||
|
@ -176,12 +121,10 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_prph);
|
||||
|
||||
|
@ -189,13 +132,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
__iwl_read_prph(trans, ofs) | mask);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
|
||||
|
||||
|
@ -204,13 +145,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
(__iwl_read_prph(trans, ofs) & mask) | bits);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
|
||||
|
||||
|
@ -219,12 +158,10 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
|||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
__iwl_write_prph(trans, ofs, (val & ~mask));
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
|
@ -51,12 +51,15 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
|
|||
return val;
|
||||
}
|
||||
|
||||
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, mask);
|
||||
}
|
||||
|
||||
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value);
|
||||
static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -0,0 +1,346 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2008 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 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.
|
||||
*****************************************************************************/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
|
||||
/* NVM offsets (in words) definitions */
|
||||
enum wkp_nvm_offsets {
|
||||
/* NVM HW-Section offset (in words) definitions */
|
||||
HW_ADDR = 0x15,
|
||||
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
NVM_SW_SECTION = 0x1C0,
|
||||
NVM_VERSION = 0,
|
||||
RADIO_CFG = 1,
|
||||
SKU = 2,
|
||||
N_HW_ADDRS = 3,
|
||||
NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
|
||||
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
NVM_CALIB_SECTION = 0x2B8,
|
||||
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
|
||||
};
|
||||
|
||||
/* SKU Capabilities (actual values from NVM definition) */
|
||||
enum nvm_sku_bits {
|
||||
NVM_SKU_CAP_BAND_24GHZ = BIT(0),
|
||||
NVM_SKU_CAP_BAND_52GHZ = BIT(1),
|
||||
NVM_SKU_CAP_11N_ENABLE = BIT(2),
|
||||
};
|
||||
|
||||
/* radio config bits (actual values from NVM definition) */
|
||||
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
|
||||
#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
|
||||
#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
|
||||
#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
|
||||
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
|
||||
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
|
||||
|
||||
/*
|
||||
* These are the channel numbers in the order that they are stored in the NVM
|
||||
*/
|
||||
static const u8 iwl_nvm_channels[] = {
|
||||
/* 2.4 GHz */
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
/* 5 GHz */
|
||||
36, 40, 44 , 48, 52, 56, 60, 64,
|
||||
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
|
||||
149, 153, 157, 161, 165
|
||||
};
|
||||
|
||||
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
|
||||
#define NUM_2GHZ_CHANNELS 14
|
||||
#define FIRST_2GHZ_HT_MINUS 5
|
||||
#define LAST_2GHZ_HT_PLUS 9
|
||||
#define LAST_5GHZ_HT 161
|
||||
|
||||
|
||||
/* rate data (static) */
|
||||
static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
|
||||
{ .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
|
||||
{ .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
|
||||
{ .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
|
||||
{ .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
|
||||
{ .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
|
||||
{ .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
|
||||
{ .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
|
||||
{ .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
|
||||
};
|
||||
#define RATES_24_OFFS 0
|
||||
#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
|
||||
#define RATES_52_OFFS 4
|
||||
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
|
||||
|
||||
/**
|
||||
* enum iwl_nvm_channel_flags - channel flags in NVM
|
||||
* @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
|
||||
* @NVM_CHANNEL_IBSS: usable as an IBSS channel
|
||||
* @NVM_CHANNEL_ACTIVE: active scanning allowed
|
||||
* @NVM_CHANNEL_RADAR: radar detection required
|
||||
* @NVM_CHANNEL_DFS: dynamic freq selection candidate
|
||||
* @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
|
||||
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
|
||||
*/
|
||||
enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
NVM_CHANNEL_IBSS = BIT(1),
|
||||
NVM_CHANNEL_ACTIVE = BIT(3),
|
||||
NVM_CHANNEL_RADAR = BIT(4),
|
||||
NVM_CHANNEL_DFS = BIT(7),
|
||||
NVM_CHANNEL_WIDE = BIT(8),
|
||||
NVM_CHANNEL_40MHZ = BIT(9),
|
||||
};
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) \
|
||||
((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
|
||||
|
||||
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 * const nvm_ch_flags)
|
||||
{
|
||||
int ch_idx;
|
||||
int n_channels = 0;
|
||||
struct ieee80211_channel *channel;
|
||||
u16 ch_flags;
|
||||
bool is_5ghz;
|
||||
|
||||
for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
|
||||
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
|
||||
if (!(ch_flags & NVM_CHANNEL_VALID)) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d Flags %x [%sGHz] - No traffic\n",
|
||||
iwl_nvm_channels[ch_idx],
|
||||
ch_flags,
|
||||
(ch_idx >= NUM_2GHZ_CHANNELS) ?
|
||||
"5.2" : "2.4");
|
||||
continue;
|
||||
}
|
||||
|
||||
channel = &data->channels[n_channels];
|
||||
n_channels++;
|
||||
|
||||
channel->hw_value = iwl_nvm_channels[ch_idx];
|
||||
channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
|
||||
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
|
||||
channel->center_freq =
|
||||
ieee80211_channel_to_frequency(
|
||||
channel->hw_value, channel->band);
|
||||
|
||||
/* TODO: Need to be dependent to the NVM */
|
||||
channel->flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (ch_idx < NUM_2GHZ_CHANNELS &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
} else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
else
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
}
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_IBSS))
|
||||
channel->flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_ACTIVE))
|
||||
channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
|
||||
if (ch_flags & NVM_CHANNEL_RADAR)
|
||||
channel->flags |= IEEE80211_CHAN_RADAR;
|
||||
|
||||
/* Initialize regulatory-based run-time data */
|
||||
|
||||
/* TODO: read the real value from the NVM */
|
||||
channel->max_power = 0;
|
||||
is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
channel->hw_value,
|
||||
is_5ghz ? "5.2" : "2.4",
|
||||
CHECK_AND_PRINT_I(VALID),
|
||||
CHECK_AND_PRINT_I(IBSS),
|
||||
CHECK_AND_PRINT_I(ACTIVE),
|
||||
CHECK_AND_PRINT_I(RADAR),
|
||||
CHECK_AND_PRINT_I(WIDE),
|
||||
CHECK_AND_PRINT_I(DFS),
|
||||
ch_flags,
|
||||
channel->max_power,
|
||||
((ch_flags & NVM_CHANNEL_IBSS) &&
|
||||
!(ch_flags & NVM_CHANNEL_RADAR))
|
||||
? "" : "not ");
|
||||
}
|
||||
|
||||
return n_channels;
|
||||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw)
|
||||
{
|
||||
int n_channels = iwl_init_channel_map(dev, cfg, data,
|
||||
&nvm_sw[NVM_CHANNELS]);
|
||||
int n_used = 0;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_2GHZ];
|
||||
sband->band = IEEE80211_BAND_2GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
||||
sband->n_bitrates = N_RATES_24;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_5GHZ];
|
||||
sband->band = IEEE80211_BAND_5GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
|
||||
sband->n_bitrates = N_RATES_52;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
n_used, n_channels);
|
||||
}
|
||||
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
u8 hw_addr[ETH_ALEN];
|
||||
u16 radio_cfg, sku;
|
||||
|
||||
data = kzalloc(sizeof(*data) +
|
||||
sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
|
||||
radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
|
||||
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
|
||||
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
|
||||
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
|
||||
data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
|
||||
data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
|
||||
sku = le16_to_cpup(nvm_sw + SKU);
|
||||
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
|
||||
data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
|
||||
data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
||||
data->sku_cap_11n_enable = false;
|
||||
|
||||
/* check overrides (some devices have wrong NVM) */
|
||||
if (cfg->valid_tx_ant)
|
||||
data->valid_tx_ant = cfg->valid_tx_ant;
|
||||
if (cfg->valid_rx_ant)
|
||||
data->valid_rx_ant = cfg->valid_rx_ant;
|
||||
|
||||
if (!data->valid_tx_ant || !data->valid_rx_ant) {
|
||||
IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
|
||||
|
||||
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
|
||||
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
|
||||
|
||||
/* The byte order is little endian 16 bit, meaning 214365 */
|
||||
memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
|
||||
data->hw_addr[0] = hw_addr[1];
|
||||
data->hw_addr[1] = hw_addr[0];
|
||||
data->hw_addr[2] = hw_addr[3];
|
||||
data->hw_addr[3] = hw_addr[2];
|
||||
data->hw_addr[4] = hw_addr[5];
|
||||
data->hw_addr[5] = hw_addr[4];
|
||||
|
||||
iwl_init_sbands(dev, cfg, data, nvm_sw);
|
||||
|
||||
data->calib_version = 255; /* TODO:
|
||||
this value will prevent some checks from
|
||||
failing, we need to check if this
|
||||
field is still needed, and if it does,
|
||||
where is it in the NVM*/
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);
|
|
@ -0,0 +1,80 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2008 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 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_nvm_parse_h__
|
||||
#define __iwl_nvm_parse_h__
|
||||
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
/**
|
||||
* iwl_parse_nvm_data - parse NVM data and return values
|
||||
*
|
||||
* This function parses all NVM values we need and then
|
||||
* returns a (newly allocated) struct containing all the
|
||||
* relevant values for driver use. The struct must be freed
|
||||
* later with iwl_free_nvm_data().
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib);
|
||||
|
||||
#endif /* __iwl_nvm_parse_h__ */
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -63,6 +63,8 @@
|
|||
#ifndef __iwl_op_mode_h__
|
||||
#define __iwl_op_mode_h__
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
struct iwl_op_mode;
|
||||
struct iwl_trans;
|
||||
struct sk_buff;
|
||||
|
|
|
@ -0,0 +1,514 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-phy-db.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */
|
||||
#define IWL_NUM_PAPD_CH_GROUPS 4
|
||||
#define IWL_NUM_TXP_CH_GROUPS 9
|
||||
|
||||
struct iwl_phy_db_entry {
|
||||
u16 size;
|
||||
u8 *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_phy_db - stores phy configuration and calibration data.
|
||||
*
|
||||
* @cfg: phy configuration.
|
||||
* @calib_nch: non channel specific calibration data.
|
||||
* @calib_ch: channel specific calibration data.
|
||||
* @calib_ch_group_papd: calibration data related to papd channel group.
|
||||
* @calib_ch_group_txp: calibration data related to tx power chanel group.
|
||||
*/
|
||||
struct iwl_phy_db {
|
||||
struct iwl_phy_db_entry cfg;
|
||||
struct iwl_phy_db_entry calib_nch;
|
||||
struct iwl_phy_db_entry calib_ch;
|
||||
struct iwl_phy_db_entry calib_ch_group_papd[IWL_NUM_PAPD_CH_GROUPS];
|
||||
struct iwl_phy_db_entry calib_ch_group_txp[IWL_NUM_TXP_CH_GROUPS];
|
||||
|
||||
u32 channel_num;
|
||||
u32 channel_size;
|
||||
|
||||
struct iwl_trans *trans;
|
||||
};
|
||||
|
||||
enum iwl_phy_db_section_type {
|
||||
IWL_PHY_DB_CFG = 1,
|
||||
IWL_PHY_DB_CALIB_NCH,
|
||||
IWL_PHY_DB_CALIB_CH,
|
||||
IWL_PHY_DB_CALIB_CHG_PAPD,
|
||||
IWL_PHY_DB_CALIB_CHG_TXP,
|
||||
IWL_PHY_DB_MAX
|
||||
};
|
||||
|
||||
#define PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
|
||||
|
||||
/*
|
||||
* phy db - configure operational ucode
|
||||
*/
|
||||
struct iwl_phy_db_cmd {
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/* for parsing of tx power channel group data that comes from the firmware*/
|
||||
struct iwl_phy_db_chg_txp {
|
||||
__le32 space;
|
||||
__le16 max_channel_idx;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* phy db - Receieve phy db chunk after calibrations
|
||||
*/
|
||||
struct iwl_calib_res_notif_phy_db {
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
|
||||
static inline void iwl_phy_db_test_pic(__le32 pic)
|
||||
{
|
||||
WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
|
||||
}
|
||||
|
||||
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!phy_db)
|
||||
return phy_db;
|
||||
|
||||
phy_db->trans = trans;
|
||||
|
||||
/* TODO: add default values of the phy db. */
|
||||
return phy_db;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_init);
|
||||
|
||||
/*
|
||||
* get phy db section: returns a pointer to a phy db section specified by
|
||||
* type and channel group id.
|
||||
*/
|
||||
static struct iwl_phy_db_entry *
|
||||
iwl_phy_db_get_section(struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u16 chg_id)
|
||||
{
|
||||
if (!phy_db || type >= IWL_PHY_DB_MAX)
|
||||
return NULL;
|
||||
|
||||
switch (type) {
|
||||
case IWL_PHY_DB_CFG:
|
||||
return &phy_db->cfg;
|
||||
case IWL_PHY_DB_CALIB_NCH:
|
||||
return &phy_db->calib_nch;
|
||||
case IWL_PHY_DB_CALIB_CH:
|
||||
return &phy_db->calib_ch;
|
||||
case IWL_PHY_DB_CALIB_CHG_PAPD:
|
||||
if (chg_id >= IWL_NUM_PAPD_CH_GROUPS)
|
||||
return NULL;
|
||||
return &phy_db->calib_ch_group_papd[chg_id];
|
||||
case IWL_PHY_DB_CALIB_CHG_TXP:
|
||||
if (chg_id >= IWL_NUM_TXP_CH_GROUPS)
|
||||
return NULL;
|
||||
return &phy_db->calib_ch_group_txp[chg_id];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void iwl_phy_db_free_section(struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u16 chg_id)
|
||||
{
|
||||
struct iwl_phy_db_entry *entry =
|
||||
iwl_phy_db_get_section(phy_db, type, chg_id);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
kfree(entry->data);
|
||||
entry->data = NULL;
|
||||
entry->size = 0;
|
||||
}
|
||||
|
||||
void iwl_phy_db_free(struct iwl_phy_db *phy_db)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!phy_db)
|
||||
return;
|
||||
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0);
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0);
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CH, 0);
|
||||
for (i = 0; i < IWL_NUM_PAPD_CH_GROUPS; i++)
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i);
|
||||
for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++)
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_TXP, i);
|
||||
|
||||
kfree(phy_db);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_free);
|
||||
|
||||
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
gfp_t alloc_ctx)
|
||||
{
|
||||
struct iwl_calib_res_notif_phy_db *phy_db_notif =
|
||||
(struct iwl_calib_res_notif_phy_db *)pkt->data;
|
||||
enum iwl_phy_db_section_type type = le16_to_cpu(phy_db_notif->type);
|
||||
u16 size = le16_to_cpu(phy_db_notif->length);
|
||||
struct iwl_phy_db_entry *entry;
|
||||
u16 chg_id = 0;
|
||||
|
||||
if (!phy_db)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CHG_PAPD ||
|
||||
type == IWL_PHY_DB_CALIB_CHG_TXP)
|
||||
chg_id = le16_to_cpup((__le16 *)phy_db_notif->data);
|
||||
|
||||
entry = iwl_phy_db_get_section(phy_db, type, chg_id);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
kfree(entry->data);
|
||||
entry->data = kmemdup(phy_db_notif->data, size, alloc_ctx);
|
||||
if (!entry->data) {
|
||||
entry->size = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
entry->size = size;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CH) {
|
||||
phy_db->channel_num =
|
||||
le32_to_cpup((__le32 *)phy_db_notif->data);
|
||||
phy_db->channel_size =
|
||||
(size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
|
||||
(size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_set_section);
|
||||
|
||||
static int is_valid_channel(u16 ch_id)
|
||||
{
|
||||
if (ch_id <= 14 ||
|
||||
(36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
|
||||
(100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
|
||||
(145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 ch_id_to_ch_index(u16 ch_id)
|
||||
{
|
||||
if (WARN_ON(!is_valid_channel(ch_id)))
|
||||
return 0xff;
|
||||
|
||||
if (ch_id <= 14)
|
||||
return ch_id - 1;
|
||||
if (ch_id <= 64)
|
||||
return (ch_id + 20) / 4;
|
||||
if (ch_id <= 140)
|
||||
return (ch_id - 12) / 4;
|
||||
return (ch_id - 13) / 4;
|
||||
}
|
||||
|
||||
|
||||
static u16 channel_id_to_papd(u16 ch_id)
|
||||
{
|
||||
if (WARN_ON(!is_valid_channel(ch_id)))
|
||||
return 0xff;
|
||||
|
||||
if (1 <= ch_id && ch_id <= 14)
|
||||
return 0;
|
||||
if (36 <= ch_id && ch_id <= 64)
|
||||
return 1;
|
||||
if (100 <= ch_id && ch_id <= 140)
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id)
|
||||
{
|
||||
struct iwl_phy_db_chg_txp *txp_chg;
|
||||
int i;
|
||||
u8 ch_index = ch_id_to_ch_index(ch_id);
|
||||
if (ch_index == 0xff)
|
||||
return 0xff;
|
||||
|
||||
for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++) {
|
||||
txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
|
||||
if (!txp_chg)
|
||||
return 0xff;
|
||||
/*
|
||||
* Looking for the first channel group that its max channel is
|
||||
* higher then wanted channel.
|
||||
*/
|
||||
if (le16_to_cpu(txp_chg->max_channel_idx) >= ch_index)
|
||||
return i;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
static
|
||||
int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
|
||||
u32 type, u8 **data, u16 *size, u16 ch_id)
|
||||
{
|
||||
struct iwl_phy_db_entry *entry;
|
||||
u32 channel_num;
|
||||
u32 channel_size;
|
||||
u16 ch_group_id = 0;
|
||||
u16 index;
|
||||
|
||||
if (!phy_db)
|
||||
return -EINVAL;
|
||||
|
||||
/* find wanted channel group */
|
||||
if (type == IWL_PHY_DB_CALIB_CHG_PAPD)
|
||||
ch_group_id = channel_id_to_papd(ch_id);
|
||||
else if (type == IWL_PHY_DB_CALIB_CHG_TXP)
|
||||
ch_group_id = channel_id_to_txp(phy_db, ch_id);
|
||||
|
||||
entry = iwl_phy_db_get_section(phy_db, type, ch_group_id);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CH) {
|
||||
index = ch_id_to_ch_index(ch_id);
|
||||
channel_num = phy_db->channel_num;
|
||||
channel_size = phy_db->channel_size;
|
||||
if (index >= channel_num) {
|
||||
IWL_ERR(phy_db->trans, "Wrong channel number %d\n",
|
||||
ch_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
*data = entry->data + CHANNEL_NUM_SIZE + index * channel_size;
|
||||
*size = channel_size;
|
||||
} else {
|
||||
*data = entry->data;
|
||||
*size = entry->size;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)*data) +
|
||||
(*size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, *size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type,
|
||||
u16 length, void *data)
|
||||
{
|
||||
struct iwl_phy_db_cmd phy_db_cmd;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = PHY_DB_CMD,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sending PHY-DB hcmd of type %d, of length %d\n",
|
||||
type, length);
|
||||
|
||||
/* Set phy db cmd variables */
|
||||
phy_db_cmd.type = cpu_to_le16(type);
|
||||
phy_db_cmd.length = cpu_to_le16(length);
|
||||
|
||||
/* Set hcmd variables */
|
||||
cmd.data[0] = &phy_db_cmd;
|
||||
cmd.len[0] = sizeof(struct iwl_phy_db_cmd);
|
||||
cmd.data[1] = data;
|
||||
cmd.len[1] = length;
|
||||
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
|
||||
|
||||
return iwl_trans_send_cmd(phy_db->trans, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_phy_db_send_all_channel_groups(
|
||||
struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u8 max_ch_groups)
|
||||
{
|
||||
u16 i;
|
||||
int err;
|
||||
struct iwl_phy_db_entry *entry;
|
||||
|
||||
/* Send all the channel specific groups to operational fw */
|
||||
for (i = 0; i < max_ch_groups; i++) {
|
||||
entry = iwl_phy_db_get_section(phy_db,
|
||||
type,
|
||||
i);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
/* Send the requested PHY DB section */
|
||||
err = iwl_send_phy_db_cmd(phy_db,
|
||||
type,
|
||||
entry->size,
|
||||
entry->data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Can't SEND phy_db section %d (%d), err %d",
|
||||
type, i, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sent PHY_DB HCMD, type = %d num = %d",
|
||||
type, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
|
||||
{
|
||||
u8 *data = NULL;
|
||||
u16 size = 0;
|
||||
int err;
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sending phy db data and configuration to runtime image\n");
|
||||
|
||||
/* Send PHY DB CFG section */
|
||||
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CFG,
|
||||
&data, &size, 0);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans, "Cannot get Phy DB cfg section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CFG, size, data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send HCMD of Phy DB cfg section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CALIB_NCH,
|
||||
&data, &size, 0);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot get Phy DB non specific channel section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CALIB_NCH, size, data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send HCMD of Phy DB non specific channel section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send all the TXP channel specific data */
|
||||
err = iwl_phy_db_send_all_channel_groups(phy_db,
|
||||
IWL_PHY_DB_CALIB_CHG_PAPD,
|
||||
IWL_NUM_PAPD_CH_GROUPS);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send channel specific PAPD groups");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send all the TXP channel specific data */
|
||||
err = iwl_phy_db_send_all_channel_groups(phy_db,
|
||||
IWL_PHY_DB_CALIB_CHG_TXP,
|
||||
IWL_NUM_TXP_CH_GROUPS);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send channel specific TX power groups");
|
||||
return err;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Finished sending phy db non channel data\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_phy_db_data);
|
|
@ -0,0 +1,82 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 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_PHYDB_H__
|
||||
#define __IWL_PHYDB_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans);
|
||||
|
||||
void iwl_phy_db_free(struct iwl_phy_db *phy_db);
|
||||
|
||||
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
gfp_t alloc_ctx);
|
||||
|
||||
|
||||
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db);
|
||||
|
||||
#endif /* __IWL_PHYDB_H__ */
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -97,6 +97,9 @@
|
|||
|
||||
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
|
||||
|
||||
/* Device system time */
|
||||
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
|
||||
|
||||
/**
|
||||
* Tx Scheduler
|
||||
*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -466,9 +466,7 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size)
|
|||
/* Hard-coded periphery absolute address */
|
||||
if (IWL_ABS_PRPH_START <= addr &&
|
||||
addr < IWL_ABS_PRPH_START + PRPH_END) {
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false)) {
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
return -EIO;
|
||||
}
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
|
||||
|
@ -476,8 +474,7 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size)
|
|||
for (i = 0; i < size; i += 4)
|
||||
*(u32 *)(tst->mem.addr + i) =
|
||||
iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
} else { /* target memory (SRAM) */
|
||||
iwl_trans_read_mem(trans, addr, tst->mem.addr,
|
||||
tst->mem.size / 4);
|
||||
|
@ -506,19 +503,13 @@ static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr,
|
|||
/* Periphery writes can be 1-3 bytes long, or DWORDs */
|
||||
if (size < 4) {
|
||||
memcpy(&val, buf, size);
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false)) {
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
||||
return -EIO;
|
||||
}
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
(addr & 0x0000FFFF) |
|
||||
((size - 1) << 24));
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
/* needed after consecutive writes w/o read */
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
} else {
|
||||
if (size % 4)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -193,11 +193,11 @@ struct iwl_rx_packet {
|
|||
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_WANT_HCMD = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_WANT_HCMD = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
};
|
||||
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
|
@ -274,6 +274,7 @@ struct iwl_rx_cmd_buffer {
|
|||
struct page *_page;
|
||||
int _offset;
|
||||
bool _page_stolen;
|
||||
u32 _rx_page_order;
|
||||
unsigned int truesize;
|
||||
};
|
||||
|
||||
|
@ -294,6 +295,11 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
|
|||
return r->_page;
|
||||
}
|
||||
|
||||
static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
|
||||
{
|
||||
__free_pages(r->_page, r->_rx_page_order);
|
||||
}
|
||||
|
||||
#define MAX_NO_RECLAIM_CMDS 6
|
||||
|
||||
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
|
||||
|
@ -410,8 +416,12 @@ struct iwl_trans;
|
|||
* the op_mode. May be called several times before start_fw, can't be
|
||||
* called after that.
|
||||
* @set_pmi: set the power pmi state
|
||||
* @grab_nic_access: wake the NIC to be able to access non-HBUS regs
|
||||
* @release_nic_access: let the NIC go to sleep
|
||||
* @grab_nic_access: wake the NIC to be able to access non-HBUS regs.
|
||||
* Sleeping is not allowed between grab_nic_access and
|
||||
* release_nic_access.
|
||||
* @release_nic_access: let the NIC go to sleep. The "flags" parameter
|
||||
* must be the same one that was sent before to the grab_nic_access.
|
||||
* @set_bits_mask - set SRAM register according to value and mask.
|
||||
*/
|
||||
struct iwl_trans_ops {
|
||||
|
||||
|
@ -454,8 +464,12 @@ struct iwl_trans_ops {
|
|||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void (*set_pmi)(struct iwl_trans *trans, bool state);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans, bool silent);
|
||||
void (*release_nic_access)(struct iwl_trans *trans);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans, bool silent,
|
||||
unsigned long *flags);
|
||||
void (*release_nic_access)(struct iwl_trans *trans,
|
||||
unsigned long *flags);
|
||||
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
|
||||
u32 value);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -475,7 +489,6 @@ enum iwl_trans_state {
|
|||
* @ops - pointer to iwl_trans_ops
|
||||
* @op_mode - pointer to the op_mode
|
||||
* @cfg - pointer to the configuration
|
||||
* @reg_lock - protect hw register access
|
||||
* @dev - pointer to struct device * that represents the device
|
||||
* @hw_id: a u32 with the ID of the device / subdevice.
|
||||
* Set during transport allocation.
|
||||
|
@ -496,7 +509,6 @@ struct iwl_trans {
|
|||
struct iwl_op_mode *op_mode;
|
||||
const struct iwl_cfg *cfg;
|
||||
enum iwl_trans_state state;
|
||||
spinlock_t reg_lock;
|
||||
|
||||
struct device *dev;
|
||||
u32 hw_rev;
|
||||
|
@ -756,14 +768,20 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
|||
trans->ops->set_pmi(trans, state);
|
||||
}
|
||||
|
||||
#define iwl_trans_grab_nic_access(trans, silent) \
|
||||
static inline void
|
||||
iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
|
||||
{
|
||||
trans->ops->set_bits_mask(trans, reg, mask, value);
|
||||
}
|
||||
|
||||
#define iwl_trans_grab_nic_access(trans, silent, flags) \
|
||||
__cond_lock(nic_access, \
|
||||
likely((trans)->ops->grab_nic_access(trans, silent)))
|
||||
likely((trans)->ops->grab_nic_access(trans, silent, flags)))
|
||||
|
||||
static inline void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
|
||||
{
|
||||
trans->ops->release_nic_access(trans);
|
||||
trans->ops->release_nic_access(trans, flags);
|
||||
__release(nic_access);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
obj-$(CONFIG_IWLMVM) += iwlmvm.o
|
||||
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
|
||||
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
|
||||
iwlmvm-y += scan.o time-event.o rs.o
|
||||
iwlmvm-y += power.o
|
||||
iwlmvm-y += led.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
|
|
@ -0,0 +1,197 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include "fw-api.h"
|
||||
#include "mvm.h"
|
||||
|
||||
struct iwl_mvm_iface_iterator_data {
|
||||
struct ieee80211_vif *ignore_vif;
|
||||
int idx;
|
||||
|
||||
struct iwl_mvm_phy_ctxt *phyctxt;
|
||||
|
||||
u16 ids[MAX_MACS_IN_BINDING];
|
||||
u16 colors[MAX_MACS_IN_BINDING];
|
||||
};
|
||||
|
||||
static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
|
||||
struct iwl_mvm_iface_iterator_data *data)
|
||||
{
|
||||
struct iwl_binding_cmd cmd;
|
||||
struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
|
||||
int i, ret;
|
||||
u32 status;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
|
||||
phyctxt->color));
|
||||
cmd.action = cpu_to_le32(action);
|
||||
cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
|
||||
phyctxt->color));
|
||||
|
||||
for (i = 0; i < MAX_MACS_IN_BINDING; i++)
|
||||
cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
|
||||
for (i = 0; i < data->idx; i++)
|
||||
cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
|
||||
data->colors[i]));
|
||||
|
||||
status = 0;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
|
||||
sizeof(cmd), &cmd, &status);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
|
||||
action, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
IWL_ERR(mvm, "Binding command failed: %u\n", status);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_iface_iterator_data *data = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif == data->ignore_vif)
|
||||
return;
|
||||
|
||||
if (mvmvif->phy_ctxt != data->phyctxt)
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
|
||||
return;
|
||||
|
||||
data->ids[data->idx] = mvmvif->id;
|
||||
data->colors[data->idx] = mvmvif->color;
|
||||
data->idx++;
|
||||
}
|
||||
|
||||
static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_phy_ctxt *phyctxt,
|
||||
bool add)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_iface_iterator_data data = {
|
||||
.ignore_vif = vif,
|
||||
.phyctxt = phyctxt,
|
||||
};
|
||||
u32 action = FW_CTXT_ACTION_MODIFY;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_iface_iterator,
|
||||
&data);
|
||||
|
||||
/*
|
||||
* If there are no other interfaces yet we
|
||||
* need to create a new binding.
|
||||
*/
|
||||
if (data.idx == 0) {
|
||||
if (add)
|
||||
action = FW_CTXT_ACTION_ADD;
|
||||
else
|
||||
action = FW_CTXT_ACTION_REMOVE;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
|
||||
return -EINVAL;
|
||||
|
||||
data.ids[data.idx] = mvmvif->id;
|
||||
data.colors[data.idx] = mvmvif->color;
|
||||
data.idx++;
|
||||
}
|
||||
|
||||
return iwl_mvm_binding_cmd(mvm, action, &data);
|
||||
}
|
||||
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
|
||||
}
|
||||
|
||||
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
|
||||
}
|
|
@ -0,0 +1,841 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "iwl-modparams.h"
|
||||
#include "fw-api.h"
|
||||
#include "mvm.h"
|
||||
|
||||
void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (iwlwifi_mod_params.sw_crypto)
|
||||
return;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
memcpy(mvmvif->rekey_data.kek, data->kek, NL80211_KEK_LEN);
|
||||
memcpy(mvmvif->rekey_data.kck, data->kck, NL80211_KCK_LEN);
|
||||
mvmvif->rekey_data.replay_ctr =
|
||||
cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr));
|
||||
mvmvif->rekey_data.valid = true;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct inet6_dev *idev)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct inet6_ifaddr *ifa;
|
||||
int idx = 0;
|
||||
|
||||
read_lock(&idev->lock);
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
mvmvif->target_ipv6_addrs[idx] = ifa->addr;
|
||||
idx++;
|
||||
if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS)
|
||||
break;
|
||||
}
|
||||
read_unlock(&idev->lock);
|
||||
|
||||
mvmvif->num_target_ipv6_addrs = idx;
|
||||
}
|
||||
#endif
|
||||
|
||||
void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int idx)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
mvmvif->tx_key_idx = idx;
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_p1k(u16 *p1k, __le16 *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_P1K_SIZE; i++)
|
||||
out[i] = cpu_to_le16(p1k[i]);
|
||||
}
|
||||
|
||||
struct wowlan_key_data {
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
|
||||
struct iwl_wowlan_tkip_params_cmd *tkip;
|
||||
bool error, use_rsc_tsc, use_tkip;
|
||||
int gtk_key_idx;
|
||||
};
|
||||
|
||||
static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *_data)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct wowlan_key_data *data = _data;
|
||||
struct aes_sc *aes_sc, *aes_tx_sc = NULL;
|
||||
struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
|
||||
struct iwl_p1k_cache *rx_p1ks;
|
||||
u8 *rx_mic_key;
|
||||
struct ieee80211_key_seq seq;
|
||||
u32 cur_rx_iv32 = 0;
|
||||
u16 p1k[IWL_P1K_SIZE];
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */
|
||||
struct {
|
||||
struct iwl_mvm_wep_key_cmd wep_key_cmd;
|
||||
struct iwl_mvm_wep_key wep_key;
|
||||
} __packed wkc = {
|
||||
.wep_key_cmd.mac_id_n_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.wep_key_cmd.num_keys = 1,
|
||||
/* firmware sets STA_KEY_FLG_WEP_13BYTES */
|
||||
.wep_key_cmd.decryption_type = STA_KEY_FLG_WEP,
|
||||
.wep_key.key_index = key->keyidx,
|
||||
.wep_key.key_size = key->keylen,
|
||||
};
|
||||
|
||||
/*
|
||||
* This will fail -- the key functions don't set support
|
||||
* pairwise WEP keys. However, that's better than silently
|
||||
* failing WoWLAN. Or maybe not?
|
||||
*/
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
break;
|
||||
|
||||
memcpy(&wkc.wep_key.key[3], key->key, key->keylen);
|
||||
if (key->keyidx == mvmvif->tx_key_idx) {
|
||||
/* TX key must be at offset 0 */
|
||||
wkc.wep_key.key_offset = 0;
|
||||
} else {
|
||||
/* others start at 1 */
|
||||
data->gtk_key_idx++;
|
||||
wkc.wep_key.key_offset = data->gtk_key_idx;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, CMD_SYNC,
|
||||
sizeof(wkc), &wkc);
|
||||
data->error = ret != 0;
|
||||
|
||||
/* don't upload key again */
|
||||
goto out_unlock;
|
||||
}
|
||||
default:
|
||||
data->error = true;
|
||||
goto out_unlock;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
/*
|
||||
* Ignore CMAC keys -- the WoWLAN firmware doesn't support them
|
||||
* but we also shouldn't abort suspend due to that. It does have
|
||||
* support for the IGTK key renewal, but doesn't really use the
|
||||
* IGTK for anything. This means we could spuriously wake up or
|
||||
* be deauthenticated, but that was considered acceptable.
|
||||
*/
|
||||
goto out_unlock;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
if (sta) {
|
||||
tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
|
||||
tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
|
||||
|
||||
rx_p1ks = data->tkip->rx_uni;
|
||||
|
||||
ieee80211_get_key_tx_seq(key, &seq);
|
||||
tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
|
||||
tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
|
||||
|
||||
ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
|
||||
iwl_mvm_convert_p1k(p1k, data->tkip->tx.p1k);
|
||||
|
||||
memcpy(data->tkip->mic_keys.tx,
|
||||
&key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
|
||||
IWL_MIC_KEY_SIZE);
|
||||
|
||||
rx_mic_key = data->tkip->mic_keys.rx_unicast;
|
||||
} else {
|
||||
tkip_sc =
|
||||
data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
|
||||
rx_p1ks = data->tkip->rx_multi;
|
||||
rx_mic_key = data->tkip->mic_keys.rx_mcast;
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-QoS this relies on the fact that both the uCode and
|
||||
* mac80211 use TID 0 (as they need to to avoid replay attacks)
|
||||
* for checking the IV in the frames.
|
||||
*/
|
||||
for (i = 0; i < IWL_NUM_RSC; i++) {
|
||||
ieee80211_get_key_rx_seq(key, i, &seq);
|
||||
tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
|
||||
tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
|
||||
/* wrapping isn't allowed, AP must rekey */
|
||||
if (seq.tkip.iv32 > cur_rx_iv32)
|
||||
cur_rx_iv32 = seq.tkip.iv32;
|
||||
}
|
||||
|
||||
ieee80211_get_tkip_rx_p1k(key, vif->bss_conf.bssid,
|
||||
cur_rx_iv32, p1k);
|
||||
iwl_mvm_convert_p1k(p1k, rx_p1ks[0].p1k);
|
||||
ieee80211_get_tkip_rx_p1k(key, vif->bss_conf.bssid,
|
||||
cur_rx_iv32 + 1, p1k);
|
||||
iwl_mvm_convert_p1k(p1k, rx_p1ks[1].p1k);
|
||||
|
||||
memcpy(rx_mic_key,
|
||||
&key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
|
||||
IWL_MIC_KEY_SIZE);
|
||||
|
||||
data->use_tkip = true;
|
||||
data->use_rsc_tsc = true;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
if (sta) {
|
||||
u8 *pn = seq.ccmp.pn;
|
||||
|
||||
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
|
||||
aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
|
||||
|
||||
ieee80211_get_key_tx_seq(key, &seq);
|
||||
aes_tx_sc->pn = cpu_to_le64((u64)pn[5] |
|
||||
((u64)pn[4] << 8) |
|
||||
((u64)pn[3] << 16) |
|
||||
((u64)pn[2] << 24) |
|
||||
((u64)pn[1] << 32) |
|
||||
((u64)pn[0] << 40));
|
||||
} else {
|
||||
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-QoS this relies on the fact that both the uCode and
|
||||
* mac80211 use TID 0 for checking the IV in the frames.
|
||||
*/
|
||||
for (i = 0; i < IWL_NUM_RSC; i++) {
|
||||
u8 *pn = seq.ccmp.pn;
|
||||
|
||||
ieee80211_get_key_rx_seq(key, i, &seq);
|
||||
aes_sc->pn = cpu_to_le64((u64)pn[5] |
|
||||
((u64)pn[4] << 8) |
|
||||
((u64)pn[3] << 16) |
|
||||
((u64)pn[2] << 24) |
|
||||
((u64)pn[1] << 32) |
|
||||
((u64)pn[0] << 40));
|
||||
}
|
||||
data->use_rsc_tsc = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The D3 firmware hardcodes the key offset 0 as the key it uses
|
||||
* to transmit packets to the AP, i.e. the PTK.
|
||||
*/
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||
key->hw_key_idx = 0;
|
||||
} else {
|
||||
data->gtk_key_idx++;
|
||||
key->hw_key_idx = data->gtk_key_idx;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
|
||||
data->error = ret != 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
|
||||
struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
struct iwl_wowlan_patterns_cmd *pattern_cmd;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WOWLAN_PATTERNS,
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
int i, err;
|
||||
|
||||
if (!wowlan->n_patterns)
|
||||
return 0;
|
||||
|
||||
cmd.len[0] = sizeof(*pattern_cmd) +
|
||||
wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern);
|
||||
|
||||
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
|
||||
if (!pattern_cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
|
||||
|
||||
for (i = 0; i < wowlan->n_patterns; i++) {
|
||||
int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
|
||||
|
||||
memcpy(&pattern_cmd->patterns[i].mask,
|
||||
wowlan->patterns[i].mask, mask_len);
|
||||
memcpy(&pattern_cmd->patterns[i].pattern,
|
||||
wowlan->patterns[i].pattern,
|
||||
wowlan->patterns[i].pattern_len);
|
||||
pattern_cmd->patterns[i].mask_size = mask_len;
|
||||
pattern_cmd->patterns[i].pattern_size =
|
||||
wowlan->patterns[i].pattern_len;
|
||||
}
|
||||
|
||||
cmd.data[0] = pattern_cmd;
|
||||
err = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
kfree(pattern_cmd);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_proto_offload_cmd cmd = {};
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int i;
|
||||
|
||||
if (mvmvif->num_target_ipv6_addrs) {
|
||||
cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS);
|
||||
memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) !=
|
||||
sizeof(mvmvif->target_ipv6_addrs[i]));
|
||||
|
||||
for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++)
|
||||
memcpy(cmd.target_ipv6_addr[i],
|
||||
&mvmvif->target_ipv6_addrs[i],
|
||||
sizeof(cmd.target_ipv6_addr[i]));
|
||||
#endif
|
||||
|
||||
if (vif->bss_conf.arp_addr_cnt) {
|
||||
cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP);
|
||||
cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
|
||||
memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (!cmd.enabled)
|
||||
return 0;
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
struct iwl_d3_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct ieee80211_vif *vif;
|
||||
bool error;
|
||||
};
|
||||
|
||||
static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_d3_iter_data *data = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return;
|
||||
|
||||
if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
|
||||
return;
|
||||
|
||||
if (data->vif) {
|
||||
IWL_ERR(data->mvm, "More than one managed interface active!\n");
|
||||
data->error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
data->vif = vif;
|
||||
}
|
||||
|
||||
static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *ap_sta)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
u8 chains_static, chains_dynamic;
|
||||
struct cfg80211_chan_def chandef;
|
||||
int ret, i;
|
||||
struct iwl_binding_cmd binding_cmd = {};
|
||||
struct iwl_time_quota_cmd quota_cmd = {};
|
||||
u32 status;
|
||||
|
||||
/* add back the PHY */
|
||||
if (WARN_ON(!mvmvif->phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
ctx = rcu_dereference(vif->chanctx_conf);
|
||||
if (WARN_ON(!ctx)) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
chandef = ctx->def;
|
||||
chains_static = ctx->rx_chains_static;
|
||||
chains_dynamic = ctx->rx_chains_dynamic;
|
||||
rcu_read_unlock();
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt, &chandef,
|
||||
chains_static, chains_dynamic);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* add back the MAC */
|
||||
mvmvif->uploaded = false;
|
||||
|
||||
if (WARN_ON(!vif->bss_conf.assoc))
|
||||
return -EINVAL;
|
||||
/* hack */
|
||||
vif->bss_conf.assoc = false;
|
||||
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
|
||||
vif->bss_conf.assoc = true;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* add back binding - XXX refactor? */
|
||||
binding_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
binding_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
binding_cmd.phy =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
binding_cmd.macs[0] = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
for (i = 1; i < MAX_MACS_IN_BINDING; i++)
|
||||
binding_cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
|
||||
|
||||
status = 0;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
|
||||
sizeof(binding_cmd), &binding_cmd,
|
||||
&status);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to add binding: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
IWL_ERR(mvm, "Binding command failed: %u\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_sta_add_to_fw(mvm, ap_sta);
|
||||
if (ret)
|
||||
return ret;
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
|
||||
|
||||
ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* and some quota */
|
||||
quota_cmd.quotas[0].id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
quota_cmd.quotas[0].quota = cpu_to_le32(100);
|
||||
quota_cmd.quotas[0].max_duration = cpu_to_le32(1000);
|
||||
|
||||
for (i = 1; i < MAX_BINDINGS; i++)
|
||||
quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,
|
||||
sizeof(quota_cmd), "a_cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_d3_iter_data suspend_iter_data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct ieee80211_sta *ap_sta;
|
||||
struct iwl_mvm_sta *mvm_ap_sta;
|
||||
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
|
||||
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
|
||||
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
|
||||
struct iwl_d3_manager_config d3_cfg_cmd = {};
|
||||
struct wowlan_key_data key_data = {
|
||||
.use_rsc_tsc = false,
|
||||
.tkip = &tkip_cmd,
|
||||
.use_tkip = false,
|
||||
};
|
||||
int ret, i;
|
||||
u16 seq;
|
||||
u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
|
||||
if (WARN_ON(!wowlan))
|
||||
return -EINVAL;
|
||||
|
||||
key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
|
||||
if (!key_data.rsc_tsc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
old_aux_sta_id = mvm->aux_sta.sta_id;
|
||||
|
||||
/* see if there's only a single BSS vif and it's associated */
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_d3_iface_iterator, &suspend_iter_data);
|
||||
|
||||
if (suspend_iter_data.error || !suspend_iter_data.vif) {
|
||||
ret = 1;
|
||||
goto out_noreset;
|
||||
}
|
||||
|
||||
vif = suspend_iter_data.vif;
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
ap_sta = rcu_dereference_protected(
|
||||
mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(ap_sta)) {
|
||||
ret = -EINVAL;
|
||||
goto out_noreset;
|
||||
}
|
||||
|
||||
mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
|
||||
|
||||
/*
|
||||
* The D3 firmware still hardcodes the AP station ID for the
|
||||
* BSS we're associated with as 0. Store the real STA ID here
|
||||
* and assign 0. When we leave this function, we'll restore
|
||||
* the original value for the resume code.
|
||||
*/
|
||||
old_ap_sta_id = mvm_ap_sta->sta_id;
|
||||
mvm_ap_sta->sta_id = 0;
|
||||
mvmvif->ap_sta_id = 0;
|
||||
|
||||
/* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */
|
||||
|
||||
wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported;
|
||||
|
||||
/*
|
||||
* We know the last used seqno, and the uCode expects to know that
|
||||
* one, it will increment before TX.
|
||||
*/
|
||||
seq = mvm_ap_sta->last_seq_ctl & IEEE80211_SCTL_SEQ;
|
||||
wowlan_config_cmd.non_qos_seq = cpu_to_le16(seq);
|
||||
|
||||
/*
|
||||
* For QoS counters, we store the one to use next, so subtract 0x10
|
||||
* since the uCode will add 0x10 *before* using the value while we
|
||||
* increment after using the value (i.e. store the next value to use).
|
||||
*/
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
seq = mvm_ap_sta->tid_data[i].seq_number;
|
||||
seq -= 0x10;
|
||||
wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq);
|
||||
}
|
||||
|
||||
if (wowlan->disconnect)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
|
||||
IWL_WOWLAN_WAKEUP_LINK_CHANGE);
|
||||
if (wowlan->magic_pkt)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
|
||||
if (wowlan->gtk_rekey_failure)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
|
||||
if (wowlan->eap_identity_req)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
|
||||
if (wowlan->four_way_handshake)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
|
||||
if (wowlan->n_patterns)
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
|
||||
|
||||
if (wowlan->rfkill_release)
|
||||
d3_cfg_cmd.wakeup_flags |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
|
||||
|
||||
iwl_mvm_cancel_scan(mvm);
|
||||
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
|
||||
/*
|
||||
* Set the HW restart bit -- this is mostly true as we're
|
||||
* going to load new firmware and reprogram that, though
|
||||
* the reprogramming is going to be manual to avoid adding
|
||||
* all the MACs that aren't support.
|
||||
* We don't have to clear up everything though because the
|
||||
* reprogramming is manual. When we resume, we'll actually
|
||||
* go through a proper restart sequence again to switch
|
||||
* back to the runtime firmware image.
|
||||
*/
|
||||
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
||||
|
||||
/* We reprogram keys and shouldn't allocate new key indices */
|
||||
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
|
||||
|
||||
/*
|
||||
* The D3 firmware still hardcodes the AP station ID for the
|
||||
* BSS we're associated with as 0. As a result, we have to move
|
||||
* the auxiliary station to ID 1 so the ID 0 remains free for
|
||||
* the AP station for later.
|
||||
* We set the sta_id to 1 here, and reset it to its previous
|
||||
* value (that we stored above) later.
|
||||
*/
|
||||
mvm->aux_sta.sta_id = 1;
|
||||
|
||||
ret = iwl_mvm_load_d3_fw(mvm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!iwlwifi_mod_params.sw_crypto) {
|
||||
/*
|
||||
* This needs to be unlocked due to lock ordering
|
||||
* constraints. Since we're in the suspend path
|
||||
* that isn't really a problem though.
|
||||
*/
|
||||
mutex_unlock(&mvm->mutex);
|
||||
ieee80211_iter_keys(mvm->hw, vif,
|
||||
iwl_mvm_wowlan_program_keys,
|
||||
&key_data);
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (key_data.error) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_data.use_rsc_tsc) {
|
||||
struct iwl_host_cmd rsc_tsc_cmd = {
|
||||
.id = WOWLAN_TSC_RSC_PARAM,
|
||||
.flags = CMD_SYNC,
|
||||
.data[0] = key_data.rsc_tsc,
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
.len[0] = sizeof(*key_data.rsc_tsc),
|
||||
};
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &rsc_tsc_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_data.use_tkip) {
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WOWLAN_TKIP_PARAM,
|
||||
CMD_SYNC, sizeof(tkip_cmd),
|
||||
&tkip_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mvmvif->rekey_data.valid) {
|
||||
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
|
||||
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
|
||||
NL80211_KCK_LEN);
|
||||
kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
|
||||
memcpy(kek_kck_cmd.kek, mvmvif->rekey_data.kek,
|
||||
NL80211_KEK_LEN);
|
||||
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
|
||||
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WOWLAN_KEK_KCK_MATERIAL,
|
||||
CMD_SYNC,
|
||||
sizeof(kek_kck_cmd),
|
||||
&kek_kck_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION,
|
||||
CMD_SYNC, sizeof(wowlan_config_cmd),
|
||||
&wowlan_config_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_mvm_send_patterns(mvm, wowlan);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_mvm_send_proto_offload(mvm, vif);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* must be last -- this switches firmware state */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC,
|
||||
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
||||
|
||||
iwl_trans_d3_suspend(mvm->trans);
|
||||
out:
|
||||
mvm->aux_sta.sta_id = old_aux_sta_id;
|
||||
mvm_ap_sta->sta_id = old_ap_sta_id;
|
||||
mvmvif->ap_sta_id = old_ap_sta_id;
|
||||
out_noreset:
|
||||
kfree(key_data.rsc_tsc);
|
||||
if (ret < 0)
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_resume(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_d3_iter_data resume_iter_data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
u32 base;
|
||||
int ret;
|
||||
enum iwl_d3_status d3_status;
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
u32 error_id;
|
||||
} err_info;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
/* get the BSS vif pointer again */
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_d3_iface_iterator, &resume_iter_data);
|
||||
|
||||
if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif))
|
||||
goto out_unlock;
|
||||
|
||||
vif = resume_iter_data.vif;
|
||||
|
||||
ret = iwl_trans_d3_resume(mvm->trans, &d3_status);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (d3_status != IWL_D3_STATUS_ALIVE) {
|
||||
IWL_INFO(mvm, "Device was reset during suspend\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
base = mvm->error_event_table;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, base,
|
||||
&err_info, sizeof(err_info));
|
||||
|
||||
if (err_info.valid) {
|
||||
IWL_INFO(mvm, "error table is valid (%d)\n",
|
||||
err_info.valid);
|
||||
if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN)
|
||||
IWL_ERR(mvm, "this was due to RF-kill\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* TODO: get status and whatever else ... */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_GET_STATUSES, CMD_SYNC, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to query status (%d)\n", ret);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to query offloads (%d)\n", ret);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
if (vif)
|
||||
ieee80211_resume_disconnect(vif);
|
||||
|
||||
/* return 1 to reconfigure the device */
|
||||
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
device_set_wakeup_enable(mvm->trans->dev, enabled);
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
#include "iwl-io.h"
|
||||
|
||||
struct iwl_dbgfs_mvm_ctx {
|
||||
struct iwl_mvm *mvm;
|
||||
struct ieee80211_vif *vif;
|
||||
};
|
||||
|
||||
static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
|
||||
char buf[16];
|
||||
int buf_size, ret;
|
||||
u32 scd_q_msk;
|
||||
|
||||
if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
|
||||
return -EIO;
|
||||
|
||||
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", &scd_q_msk) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
char buf[8];
|
||||
int buf_size, sta_id, drain, ret;
|
||||
|
||||
if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
|
||||
return -EIO;
|
||||
|
||||
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 %d", &sta_id, &drain) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(sta))
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = iwl_mvm_drain_sta(mvm, (void *)sta->drv_priv, drain) ? :
|
||||
count;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
const struct fw_img *img;
|
||||
int ofs, len, pos = 0;
|
||||
size_t bufsz, ret;
|
||||
char *buf;
|
||||
u8 *ptr;
|
||||
|
||||
/* default is to dump the entire data segment */
|
||||
if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) {
|
||||
mvm->dbgfs_sram_offset = 0x800000;
|
||||
if (!mvm->ucode_loaded)
|
||||
return -EINVAL;
|
||||
img = &mvm->fw->img[mvm->cur_ucode];
|
||||
mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
}
|
||||
len = mvm->dbgfs_sram_len;
|
||||
|
||||
bufsz = len * 4 + 256;
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ptr = kzalloc(len, GFP_KERNEL);
|
||||
if (!ptr) {
|
||||
kfree(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
|
||||
mvm->dbgfs_sram_offset);
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans,
|
||||
mvm->dbgfs_sram_offset,
|
||||
ptr, len);
|
||||
for (ofs = 0; ofs < len; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs);
|
||||
hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
|
||||
bufsz - pos, false);
|
||||
pos += strlen(buf + pos);
|
||||
if (bufsz - pos > 0)
|
||||
buf[pos++] = '\n';
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
|
||||
kfree(buf);
|
||||
kfree(ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_write(struct file *file,
|
||||
const char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char buf[64];
|
||||
int buf_size;
|
||||
u32 offset, len;
|
||||
|
||||
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,%x", &offset, &len) == 2) {
|
||||
if ((offset & 0x3) || (len & 0x3))
|
||||
return -EINVAL;
|
||||
mvm->dbgfs_sram_offset = offset;
|
||||
mvm->dbgfs_sram_len = len;
|
||||
} else {
|
||||
mvm->dbgfs_sram_offset = 0;
|
||||
mvm->dbgfs_sram_len = 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct ieee80211_sta *sta;
|
||||
char buf[400];
|
||||
int i, pos = 0, bufsz = sizeof(buf);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!sta)
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
|
||||
else if (IS_ERR(sta))
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
|
||||
PTR_ERR(sta));
|
||||
else
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
|
||||
sta->addr);
|
||||
}
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_power_down_allow_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char buf[8] = {};
|
||||
int allow;
|
||||
|
||||
if (!mvm->ucode_loaded)
|
||||
return -EIO;
|
||||
|
||||
if (copy_from_user(buf, user_buf, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (sscanf(buf, "%d", &allow) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "%s device power down\n",
|
||||
allow ? "allow" : "prevent");
|
||||
|
||||
/*
|
||||
* TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it
|
||||
*/
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char buf[8] = {};
|
||||
int allow;
|
||||
|
||||
if (copy_from_user(buf, user_buf, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (sscanf(buf, "%d", &allow) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "%s device power down in d3\n",
|
||||
allow ? "allow" : "prevent");
|
||||
|
||||
/*
|
||||
* TODO: When WoWLAN FW alive notification happens, driver will send
|
||||
* REPLY_DEBUG_CMD setting power_down_allow flag according to
|
||||
* mvm->prevent_power_down_d3
|
||||
*/
|
||||
mvm->prevent_power_down_d3 = !allow;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#define MVM_DEBUGFS_READ_FILE_OPS(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 MVM_DEBUGFS_READ_WRITE_FILE_OPS(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, \
|
||||
};
|
||||
|
||||
#define MVM_DEBUGFS_WRITE_FILE_OPS(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 MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
if (!debugfs_create_file(#name, mode, parent, mvm, \
|
||||
&iwl_dbgfs_##name##_ops)) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
|
||||
if (!debugfs_create_file(#name, mode, parent, vif, \
|
||||
&iwl_dbgfs_##name##_ops)) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
/* Device wide debugfs entries */
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(stations);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
|
||||
|
||||
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
mvm->debugfs_dir = dbgfs_dir;
|
||||
|
||||
MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
|
||||
/*
|
||||
* Create a symlink with mac80211. It will be removed when mac80211
|
||||
* exists (before the opmode exists which removes the target.)
|
||||
*/
|
||||
snprintf(buf, 100, "../../%s/%s",
|
||||
dbgfs_dir->d_parent->d_parent->d_name.name,
|
||||
dbgfs_dir->d_parent->d_name.name);
|
||||
if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
|
||||
return -ENOMEM;
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_d3_h__
|
||||
#define __fw_api_d3_h__
|
||||
|
||||
/**
|
||||
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
|
||||
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
|
||||
*/
|
||||
enum iwl_d3_wakeup_flags {
|
||||
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
|
||||
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_d3_manager_config - D3 manager configuration command
|
||||
* @min_sleep_time: minimum sleep time (in usec)
|
||||
* @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags
|
||||
*
|
||||
* The structure is used for the D3_CONFIG_CMD command.
|
||||
*/
|
||||
struct iwl_d3_manager_config {
|
||||
__le32 min_sleep_time;
|
||||
__le32 wakeup_flags;
|
||||
} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */
|
||||
|
||||
|
||||
/* TODO: OFFLOADS_QUERY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_d3_proto_offloads - enabled protocol offloads
|
||||
* @IWL_D3_PROTO_OFFLOAD_ARP: ARP data is enabled
|
||||
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
|
||||
*/
|
||||
enum iwl_proto_offloads {
|
||||
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
|
||||
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
|
||||
};
|
||||
|
||||
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2
|
||||
|
||||
/**
|
||||
* struct iwl_proto_offload_cmd - ARP/NS offload configuration
|
||||
* @enabled: enable flags
|
||||
* @remote_ipv4_addr: remote address to answer to (or zero if all)
|
||||
* @host_ipv4_addr: our IPv4 address to respond to queries for
|
||||
* @arp_mac_addr: our MAC address for ARP responses
|
||||
* @remote_ipv6_addr: remote address to answer to (or zero if all)
|
||||
* @solicited_node_ipv6_addr: broken -- solicited node address exists
|
||||
* for each target address
|
||||
* @target_ipv6_addr: our target addresses
|
||||
* @ndp_mac_addr: neighbor soliciation response MAC address
|
||||
*/
|
||||
struct iwl_proto_offload_cmd {
|
||||
__le32 enabled;
|
||||
__be32 remote_ipv4_addr;
|
||||
__be32 host_ipv4_addr;
|
||||
u8 arp_mac_addr[ETH_ALEN];
|
||||
__le16 reserved1;
|
||||
|
||||
u8 remote_ipv6_addr[16];
|
||||
u8 solicited_node_ipv6_addr[16];
|
||||
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16];
|
||||
u8 ndp_mac_addr[ETH_ALEN];
|
||||
__le16 reserved2;
|
||||
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
|
||||
|
||||
|
||||
/*
|
||||
* WOWLAN_PATTERNS
|
||||
*/
|
||||
#define IWL_WOWLAN_MIN_PATTERN_LEN 16
|
||||
#define IWL_WOWLAN_MAX_PATTERN_LEN 128
|
||||
|
||||
struct iwl_wowlan_pattern {
|
||||
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
|
||||
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
|
||||
u8 mask_size;
|
||||
u8 pattern_size;
|
||||
__le16 reserved;
|
||||
} __packed; /* WOWLAN_PATTERN_API_S_VER_1 */
|
||||
|
||||
#define IWL_WOWLAN_MAX_PATTERNS 20
|
||||
|
||||
struct iwl_wowlan_patterns_cmd {
|
||||
__le32 n_patterns;
|
||||
struct iwl_wowlan_pattern patterns[];
|
||||
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
|
||||
|
||||
enum iwl_wowlan_wakeup_filters {
|
||||
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
|
||||
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
|
||||
IWL_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
|
||||
IWL_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
|
||||
IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
|
||||
IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(5),
|
||||
IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(6),
|
||||
IWL_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(7),
|
||||
IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT = BIT(8),
|
||||
IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS = BIT(9),
|
||||
IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE = BIT(10),
|
||||
/* BIT(11) reserved */
|
||||
IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET = BIT(12),
|
||||
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
|
||||
|
||||
struct iwl_wowlan_config_cmd {
|
||||
__le32 wakeup_filter;
|
||||
__le16 non_qos_seq;
|
||||
__le16 qos_seq[8];
|
||||
u8 wowlan_ba_teardown_tids;
|
||||
u8 is_11n_connection;
|
||||
} __packed; /* WOWLAN_CONFIG_API_S_VER_2 */
|
||||
|
||||
/*
|
||||
* WOWLAN_TSC_RSC_PARAMS
|
||||
*/
|
||||
#define IWL_NUM_RSC 16
|
||||
|
||||
struct tkip_sc {
|
||||
__le16 iv16;
|
||||
__le16 pad;
|
||||
__le32 iv32;
|
||||
} __packed; /* TKIP_SC_API_U_VER_1 */
|
||||
|
||||
struct iwl_tkip_rsc_tsc {
|
||||
struct tkip_sc unicast_rsc[IWL_NUM_RSC];
|
||||
struct tkip_sc multicast_rsc[IWL_NUM_RSC];
|
||||
struct tkip_sc tsc;
|
||||
} __packed; /* TKIP_TSC_RSC_API_S_VER_1 */
|
||||
|
||||
struct aes_sc {
|
||||
__le64 pn;
|
||||
} __packed; /* TKIP_AES_SC_API_U_VER_1 */
|
||||
|
||||
struct iwl_aes_rsc_tsc {
|
||||
struct aes_sc unicast_rsc[IWL_NUM_RSC];
|
||||
struct aes_sc multicast_rsc[IWL_NUM_RSC];
|
||||
struct aes_sc tsc;
|
||||
} __packed; /* AES_TSC_RSC_API_S_VER_1 */
|
||||
|
||||
union iwl_all_tsc_rsc {
|
||||
struct iwl_tkip_rsc_tsc tkip;
|
||||
struct iwl_aes_rsc_tsc aes;
|
||||
}; /* ALL_TSC_RSC_API_S_VER_2 */
|
||||
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd {
|
||||
union iwl_all_tsc_rsc all_tsc_rsc;
|
||||
} __packed; /* ALL_TSC_RSC_API_S_VER_2 */
|
||||
|
||||
#define IWL_MIC_KEY_SIZE 8
|
||||
struct iwl_mic_keys {
|
||||
u8 tx[IWL_MIC_KEY_SIZE];
|
||||
u8 rx_unicast[IWL_MIC_KEY_SIZE];
|
||||
u8 rx_mcast[IWL_MIC_KEY_SIZE];
|
||||
} __packed; /* MIC_KEYS_API_S_VER_1 */
|
||||
|
||||
#define IWL_P1K_SIZE 5
|
||||
struct iwl_p1k_cache {
|
||||
__le16 p1k[IWL_P1K_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define IWL_NUM_RX_P1K_CACHE 2
|
||||
|
||||
struct iwl_wowlan_tkip_params_cmd {
|
||||
struct iwl_mic_keys mic_keys;
|
||||
struct iwl_p1k_cache tx;
|
||||
struct iwl_p1k_cache rx_uni[IWL_NUM_RX_P1K_CACHE];
|
||||
struct iwl_p1k_cache rx_multi[IWL_NUM_RX_P1K_CACHE];
|
||||
} __packed; /* WOWLAN_TKIP_SETTING_API_S_VER_1 */
|
||||
|
||||
#define IWL_KCK_MAX_SIZE 32
|
||||
#define IWL_KEK_MAX_SIZE 32
|
||||
|
||||
struct iwl_wowlan_kek_kck_material_cmd {
|
||||
u8 kck[IWL_KCK_MAX_SIZE];
|
||||
u8 kek[IWL_KEK_MAX_SIZE];
|
||||
__le16 kck_len;
|
||||
__le16 kek_len;
|
||||
__le64 replay_ctr;
|
||||
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_2 */
|
||||
|
||||
#define RF_KILL_INDICATOR_FOR_WOWLAN 0x87
|
||||
|
||||
enum iwl_wowlan_rekey_status {
|
||||
IWL_WOWLAN_REKEY_POST_REKEY = 0,
|
||||
IWL_WOWLAN_REKEY_WHILE_REKEY = 1,
|
||||
}; /* WOWLAN_REKEY_STATUS_API_E_VER_1 */
|
||||
|
||||
enum iwl_wowlan_wakeup_reason {
|
||||
IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS = 0,
|
||||
IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET = BIT(0),
|
||||
IWL_WOWLAN_WAKEUP_BY_PATTERN = BIT(1),
|
||||
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON = BIT(2),
|
||||
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH = BIT(3),
|
||||
IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE = BIT(4),
|
||||
IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED = BIT(5),
|
||||
IWL_WOWLAN_WAKEUP_BY_UCODE_ERROR = BIT(6),
|
||||
IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST = BIT(7),
|
||||
IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
|
||||
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
|
||||
|
||||
struct iwl_wowlan_status {
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 rekey_status;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
|
||||
|
||||
/* TODO: NetDetect API */
|
||||
|
||||
#endif /* __fw_api_d3_h__ */
|
|
@ -0,0 +1,369 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_mac_h__
|
||||
#define __fw_api_mac_h__
|
||||
|
||||
/*
|
||||
* The first MAC indices (starting from 0)
|
||||
* are available to the driver, AUX follows
|
||||
*/
|
||||
#define MAC_INDEX_AUX 4
|
||||
#define MAC_INDEX_MIN_DRIVER 0
|
||||
#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX
|
||||
|
||||
#define AC_NUM 4 /* Number of access categories */
|
||||
|
||||
/**
|
||||
* enum iwl_mac_protection_flags - MAC context flags
|
||||
* @MAC_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,
|
||||
* this will require CCK RTS/CTS2self.
|
||||
* RTS/CTS will protect full burst time.
|
||||
* @MAC_PROT_FLG_HT_PROT: enable HT protection
|
||||
* @MAC_PROT_FLG_FAT_PROT: protect 40 MHz transmissions
|
||||
* @MAC_PROT_FLG_SELF_CTS_EN: allow CTS2self
|
||||
*/
|
||||
enum iwl_mac_protection_flags {
|
||||
MAC_PROT_FLG_TGG_PROTECT = BIT(3),
|
||||
MAC_PROT_FLG_HT_PROT = BIT(23),
|
||||
MAC_PROT_FLG_FAT_PROT = BIT(24),
|
||||
MAC_PROT_FLG_SELF_CTS_EN = BIT(30),
|
||||
};
|
||||
|
||||
#define MAC_FLG_SHORT_SLOT BIT(4)
|
||||
#define MAC_FLG_SHORT_PREAMBLE BIT(5)
|
||||
|
||||
/**
|
||||
* enum iwl_mac_types - Supported MAC types
|
||||
* @FW_MAC_TYPE_FIRST: lowest supported MAC type
|
||||
* @FW_MAC_TYPE_AUX: Auxiliary MAC (internal)
|
||||
* @FW_MAC_TYPE_LISTENER: monitor MAC type (?)
|
||||
* @FW_MAC_TYPE_PIBSS: Pseudo-IBSS
|
||||
* @FW_MAC_TYPE_IBSS: IBSS
|
||||
* @FW_MAC_TYPE_BSS_STA: BSS (managed) station
|
||||
* @FW_MAC_TYPE_P2P_DEVICE: P2P Device
|
||||
* @FW_MAC_TYPE_P2P_STA: P2P client
|
||||
* @FW_MAC_TYPE_GO: P2P GO
|
||||
* @FW_MAC_TYPE_TEST: ?
|
||||
* @FW_MAC_TYPE_MAX: highest support MAC type
|
||||
*/
|
||||
enum iwl_mac_types {
|
||||
FW_MAC_TYPE_FIRST = 1,
|
||||
FW_MAC_TYPE_AUX = FW_MAC_TYPE_FIRST,
|
||||
FW_MAC_TYPE_LISTENER,
|
||||
FW_MAC_TYPE_PIBSS,
|
||||
FW_MAC_TYPE_IBSS,
|
||||
FW_MAC_TYPE_BSS_STA,
|
||||
FW_MAC_TYPE_P2P_DEVICE,
|
||||
FW_MAC_TYPE_P2P_STA,
|
||||
FW_MAC_TYPE_GO,
|
||||
FW_MAC_TYPE_TEST,
|
||||
FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
|
||||
}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_tsf_id - TSF hw timer ID
|
||||
* @TSF_ID_A: use TSF A
|
||||
* @TSF_ID_B: use TSF B
|
||||
* @TSF_ID_C: use TSF C
|
||||
* @TSF_ID_D: use TSF D
|
||||
* @NUM_TSF_IDS: number of TSF timers available
|
||||
*/
|
||||
enum iwl_tsf_id {
|
||||
TSF_ID_A = 0,
|
||||
TSF_ID_B = 1,
|
||||
TSF_ID_C = 2,
|
||||
TSF_ID_D = 3,
|
||||
NUM_TSF_IDS = 4,
|
||||
}; /* TSF_ID_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_ap - configuration data for AP MAC context
|
||||
* @beacon_time: beacon transmit time in system time
|
||||
* @beacon_tsf: beacon transmit time in TSF
|
||||
* @bi: beacon interval in TU
|
||||
* @bi_reciprocal: 2^32 / bi
|
||||
* @dtim_interval: dtim transmit time in TU
|
||||
* @dtim_reciprocal: 2^32 / dtim_interval
|
||||
* @mcast_qid: queue ID for multicast traffic
|
||||
* @beacon_template: beacon template ID
|
||||
*/
|
||||
struct iwl_mac_data_ap {
|
||||
__le32 beacon_time;
|
||||
__le64 beacon_tsf;
|
||||
__le32 bi;
|
||||
__le32 bi_reciprocal;
|
||||
__le32 dtim_interval;
|
||||
__le32 dtim_reciprocal;
|
||||
__le32 mcast_qid;
|
||||
__le32 beacon_template;
|
||||
} __packed; /* AP_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_ibss - configuration data for IBSS MAC context
|
||||
* @beacon_time: beacon transmit time in system time
|
||||
* @beacon_tsf: beacon transmit time in TSF
|
||||
* @bi: beacon interval in TU
|
||||
* @bi_reciprocal: 2^32 / bi
|
||||
*/
|
||||
struct iwl_mac_data_ibss {
|
||||
__le32 beacon_time;
|
||||
__le64 beacon_tsf;
|
||||
__le32 bi;
|
||||
__le32 bi_reciprocal;
|
||||
} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_sta - configuration data for station MAC context
|
||||
* @is_assoc: 1 for associated state, 0 otherwise
|
||||
* @dtim_time: DTIM arrival time in system time
|
||||
* @dtim_tsf: DTIM arrival time in TSF
|
||||
* @bi: beacon interval in TU, applicable only when associated
|
||||
* @bi_reciprocal: 2^32 / bi , applicable only when associated
|
||||
* @dtim_interval: DTIM interval in TU, applicable only when associated
|
||||
* @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated
|
||||
* @listen_interval: in beacon intervals, applicable only when associated
|
||||
* @assoc_id: unique ID assigned by the AP during association
|
||||
*/
|
||||
struct iwl_mac_data_sta {
|
||||
__le32 is_assoc;
|
||||
__le32 dtim_time;
|
||||
__le64 dtim_tsf;
|
||||
__le32 bi;
|
||||
__le32 bi_reciprocal;
|
||||
__le32 dtim_interval;
|
||||
__le32 dtim_reciprocal;
|
||||
__le32 listen_interval;
|
||||
__le32 assoc_id;
|
||||
__le32 assoc_beacon_arrive_time;
|
||||
} __packed; /* STA_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_go - configuration data for P2P GO MAC context
|
||||
* @ap: iwl_mac_data_ap struct with most config data
|
||||
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
|
||||
* 0 indicates that there is no CT window.
|
||||
* @opp_ps_enabled: indicate that opportunistic PS allowed
|
||||
*/
|
||||
struct iwl_mac_data_go {
|
||||
struct iwl_mac_data_ap ap;
|
||||
__le32 ctwin;
|
||||
__le32 opp_ps_enabled;
|
||||
} __packed; /* GO_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_p2p_sta - configuration data for P2P client MAC context
|
||||
* @sta: iwl_mac_data_sta struct with most config data
|
||||
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
|
||||
* 0 indicates that there is no CT window.
|
||||
*/
|
||||
struct iwl_mac_data_p2p_sta {
|
||||
struct iwl_mac_data_sta sta;
|
||||
__le32 ctwin;
|
||||
} __packed; /* P2P_STA_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_data_pibss - Pseudo IBSS config data
|
||||
* @stats_interval: interval in TU between statistics notifications to host.
|
||||
*/
|
||||
struct iwl_mac_data_pibss {
|
||||
__le32 stats_interval;
|
||||
} __packed; /* PIBSS_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* struct iwl_mac_data_p2p_dev - configuration data for the P2P Device MAC
|
||||
* context.
|
||||
* @is_disc_extended: if set to true, P2P Device discoverability is enabled on
|
||||
* other channels as well. This should be to true only in case that the
|
||||
* device is discoverable and there is an active GO. Note that setting this
|
||||
* field when not needed, will increase the number of interrupts and have
|
||||
* effect on the platform power, as this setting opens the Rx filters on
|
||||
* all macs.
|
||||
*/
|
||||
struct iwl_mac_data_p2p_dev {
|
||||
__le32 is_disc_extended;
|
||||
} __packed; /* _P2P_DEV_MAC_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mac_filter_flags - MAC context filter flags
|
||||
* @MAC_FILTER_IN_PROMISC: accept all data frames
|
||||
* @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and
|
||||
* control frames to the host
|
||||
* @MAC_FILTER_ACCEPT_GRP: accept multicast frames
|
||||
* @MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames
|
||||
* @MAC_FILTER_DIS_GRP_DECRYPT: don't decrypt multicast frames
|
||||
* @MAC_FILTER_IN_BEACON: transfer foreign BSS's beacons to host
|
||||
* (in station mode when associated)
|
||||
* @MAC_FILTER_OUT_BCAST: filter out all broadcast frames
|
||||
* @MAC_FILTER_IN_CRC32: extract FCS and append it to frames
|
||||
* @MAC_FILTER_IN_PROBE_REQUEST: pass probe requests to host
|
||||
*/
|
||||
enum iwl_mac_filter_flags {
|
||||
MAC_FILTER_IN_PROMISC = BIT(0),
|
||||
MAC_FILTER_IN_CONTROL_AND_MGMT = BIT(1),
|
||||
MAC_FILTER_ACCEPT_GRP = BIT(2),
|
||||
MAC_FILTER_DIS_DECRYPT = BIT(3),
|
||||
MAC_FILTER_DIS_GRP_DECRYPT = BIT(4),
|
||||
MAC_FILTER_IN_BEACON = BIT(6),
|
||||
MAC_FILTER_OUT_BCAST = BIT(8),
|
||||
MAC_FILTER_IN_CRC32 = BIT(11),
|
||||
MAC_FILTER_IN_PROBE_REQUEST = BIT(12),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_mac_qos_flags - QoS flags
|
||||
* @MAC_QOS_FLG_UPDATE_EDCA: ?
|
||||
* @MAC_QOS_FLG_TGN: HT is enabled
|
||||
* @MAC_QOS_FLG_TXOP_TYPE: ?
|
||||
*
|
||||
*/
|
||||
enum iwl_mac_qos_flags {
|
||||
MAC_QOS_FLG_UPDATE_EDCA = BIT(0),
|
||||
MAC_QOS_FLG_TGN = BIT(1),
|
||||
MAC_QOS_FLG_TXOP_TYPE = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_ac_qos - QOS timing params for MAC_CONTEXT_CMD
|
||||
* @cw_min: Contention window, start value in numbers of slots.
|
||||
* Should be a power-of-2, minus 1. Device's default is 0x0f.
|
||||
* @cw_max: Contention window, max value in numbers of slots.
|
||||
* Should be a power-of-2, minus 1. Device's default is 0x3f.
|
||||
* @aifsn: Number of slots in Arbitration Interframe Space (before
|
||||
* performing random backoff timing prior to Tx). Device default 1.
|
||||
* @fifos_mask: FIFOs used by this MAC for this AC
|
||||
* @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0.
|
||||
*
|
||||
* One instance of this config struct for each of 4 EDCA access categories
|
||||
* in struct iwl_qosparam_cmd.
|
||||
*
|
||||
* Device will automatically increase contention window by (2*CW) + 1 for each
|
||||
* transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
|
||||
* value, to cap the CW value.
|
||||
*/
|
||||
struct iwl_ac_qos {
|
||||
__le16 cw_min;
|
||||
__le16 cw_max;
|
||||
u8 aifsn;
|
||||
u8 fifos_mask;
|
||||
__le16 edca_txop;
|
||||
} __packed; /* AC_QOS_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
|
||||
* ( MAC_CONTEXT_CMD = 0x28 )
|
||||
* @id_and_color: ID and color of the MAC
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @mac_type: one of FW_MAC_TYPE_*
|
||||
* @tsd_id: TSF HW timer, one of TSF_ID_*
|
||||
* @node_addr: MAC address
|
||||
* @bssid_addr: BSSID
|
||||
* @cck_rates: basic rates available for CCK
|
||||
* @ofdm_rates: basic rates available for OFDM
|
||||
* @protection_flags: combination of MAC_PROT_FLG_FLAG_*
|
||||
* @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise
|
||||
* @short_slot: 0x10 for enabling short slots, 0 otherwise
|
||||
* @filter_flags: combination of MAC_FILTER_*
|
||||
* @qos_flags: from MAC_QOS_FLG_*
|
||||
* @ac: one iwl_mac_qos configuration for each AC
|
||||
* @mac_specific: one of struct iwl_mac_data_*, according to mac_type
|
||||
*/
|
||||
struct iwl_mac_ctx_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* MAC_CONTEXT_COMMON_DATA_API_S_VER_1 */
|
||||
__le32 mac_type;
|
||||
__le32 tsf_id;
|
||||
u8 node_addr[6];
|
||||
__le16 reserved_for_node_addr;
|
||||
u8 bssid_addr[6];
|
||||
__le16 reserved_for_bssid_addr;
|
||||
__le32 cck_rates;
|
||||
__le32 ofdm_rates;
|
||||
__le32 protection_flags;
|
||||
__le32 cck_short_preamble;
|
||||
__le32 short_slot;
|
||||
__le32 filter_flags;
|
||||
/* MAC_QOS_PARAM_API_S_VER_1 */
|
||||
__le32 qos_flags;
|
||||
struct iwl_ac_qos ac[AC_NUM+1];
|
||||
/* MAC_CONTEXT_COMMON_DATA_API_S */
|
||||
union {
|
||||
struct iwl_mac_data_ap ap;
|
||||
struct iwl_mac_data_go go;
|
||||
struct iwl_mac_data_sta sta;
|
||||
struct iwl_mac_data_p2p_sta p2p_sta;
|
||||
struct iwl_mac_data_p2p_dev p2p_dev;
|
||||
struct iwl_mac_data_pibss pibss;
|
||||
struct iwl_mac_data_ibss ibss;
|
||||
};
|
||||
} __packed; /* MAC_CONTEXT_CMD_API_S_VER_1 */
|
||||
|
||||
static inline u32 iwl_mvm_reciprocal(u32 v)
|
||||
{
|
||||
if (!v)
|
||||
return 0;
|
||||
return 0xFFFFFFFF / v;
|
||||
}
|
||||
|
||||
#endif /* __fw_api_mac_h__ */
|
|
@ -0,0 +1,140 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_power_h__
|
||||
#define __fw_api_power_h__
|
||||
|
||||
/* Power Management Commands, Responses, Notifications */
|
||||
|
||||
/**
|
||||
* enum iwl_scan_flags - masks for power table command flags
|
||||
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
|
||||
* '1' Driver enables PM (use rest of parameters)
|
||||
* @POWER_FLAGS_SLEEP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
|
||||
* '1' PM could sleep over DTIM till listen Interval.
|
||||
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
|
||||
* @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
|
||||
* access categories are both delivery and trigger enabled.
|
||||
* @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
|
||||
* PBW Snoozing enabled
|
||||
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
|
||||
*/
|
||||
enum iwl_power_flags {
|
||||
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(0),
|
||||
POWER_FLAGS_SLEEP_OVER_DTIM_MSK = BIT(1),
|
||||
POWER_FLAGS_LPRX_ENA_MSK = BIT(2),
|
||||
POWER_FLAGS_SNOOZE_ENA_MSK = BIT(3),
|
||||
POWER_FLAGS_BT_SCO_ENA = BIT(4),
|
||||
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(5)
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_powertable_cmd - Power Table Command
|
||||
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
|
||||
*
|
||||
* @id_and_color: MAC contex identifier
|
||||
* @action: Action on context - no action, add new,
|
||||
* modify existent, remove
|
||||
* @flags: Power table command flags from POWER_FLAGS_*
|
||||
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
|
||||
* Minimum allowed:- 3 * DTIM
|
||||
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
|
||||
* PSM transition - legacy PM
|
||||
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
|
||||
* PSM transition - legacy PM
|
||||
* @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
|
||||
* PSM transition - uAPSD
|
||||
* @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
|
||||
* PSM transition - uAPSD
|
||||
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
|
||||
* Default: 80dbm
|
||||
* @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
|
||||
* @snooze_interval: TBD
|
||||
* @snooze_window: TBD
|
||||
* @snooze_step: TBD
|
||||
* @qndp_tid: TBD
|
||||
* @uapsd_ac_flags: TBD
|
||||
* @uapsd_max_sp: TBD
|
||||
*/
|
||||
struct iwl_powertable_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
__le16 flags;
|
||||
u8 reserved;
|
||||
__le16 keep_alive_seconds;
|
||||
__le32 rx_data_timeout;
|
||||
__le32 tx_data_timeout;
|
||||
__le32 rx_data_timeout_uapsd;
|
||||
__le32 tx_data_timeout_uapsd;
|
||||
u8 lprx_rssi_threshold;
|
||||
u8 num_skip_dtim;
|
||||
__le16 snooze_interval;
|
||||
__le16 snooze_window;
|
||||
u8 snooze_step;
|
||||
u8 qndp_tid;
|
||||
u8 uapsd_ac_flags;
|
||||
u8 uapsd_max_sp;
|
||||
} __packed;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,312 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_rs_h__
|
||||
#define __fw_api_rs_h__
|
||||
|
||||
#include "fw-api-mac.h"
|
||||
|
||||
/*
|
||||
* These serve as indexes into
|
||||
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
|
||||
*/
|
||||
enum {
|
||||
IWL_RATE_1M_INDEX = 0,
|
||||
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
|
||||
IWL_RATE_2M_INDEX,
|
||||
IWL_RATE_5M_INDEX,
|
||||
IWL_RATE_11M_INDEX,
|
||||
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
|
||||
IWL_RATE_6M_INDEX,
|
||||
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
|
||||
IWL_RATE_9M_INDEX,
|
||||
IWL_RATE_12M_INDEX,
|
||||
IWL_RATE_18M_INDEX,
|
||||
IWL_RATE_24M_INDEX,
|
||||
IWL_RATE_36M_INDEX,
|
||||
IWL_RATE_48M_INDEX,
|
||||
IWL_RATE_54M_INDEX,
|
||||
IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX,
|
||||
IWL_RATE_60M_INDEX,
|
||||
IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
|
||||
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
|
||||
IWL_RATE_COUNT,
|
||||
};
|
||||
|
||||
#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
|
||||
|
||||
/* fw API values for legacy bit rates, both OFDM and CCK */
|
||||
enum {
|
||||
IWL_RATE_6M_PLCP = 13,
|
||||
IWL_RATE_9M_PLCP = 15,
|
||||
IWL_RATE_12M_PLCP = 5,
|
||||
IWL_RATE_18M_PLCP = 7,
|
||||
IWL_RATE_24M_PLCP = 9,
|
||||
IWL_RATE_36M_PLCP = 11,
|
||||
IWL_RATE_48M_PLCP = 1,
|
||||
IWL_RATE_54M_PLCP = 3,
|
||||
IWL_RATE_1M_PLCP = 10,
|
||||
IWL_RATE_2M_PLCP = 20,
|
||||
IWL_RATE_5M_PLCP = 55,
|
||||
IWL_RATE_11M_PLCP = 110,
|
||||
};
|
||||
|
||||
/*
|
||||
* rate_n_flags bit fields
|
||||
*
|
||||
* The 32-bit value has different layouts in the low 8 bites depending on the
|
||||
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
|
||||
* for CCK and OFDM).
|
||||
*
|
||||
* High-throughput (HT) rate format
|
||||
* bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM)
|
||||
* Very High-throughput (VHT) rate format
|
||||
* bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM)
|
||||
* Legacy OFDM rate format for bits 7:0
|
||||
* bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM)
|
||||
* Legacy CCK rate format for bits 7:0:
|
||||
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK)
|
||||
*/
|
||||
|
||||
/* Bit 8: (1) HT format, (0) legacy or VHT format */
|
||||
#define RATE_MCS_HT_POS 8
|
||||
#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS)
|
||||
|
||||
/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */
|
||||
#define RATE_MCS_CCK_POS 9
|
||||
#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS)
|
||||
|
||||
/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */
|
||||
#define RATE_MCS_VHT_POS 26
|
||||
#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS)
|
||||
|
||||
|
||||
/*
|
||||
* High-throughput (HT) rate format for bits 7:0
|
||||
*
|
||||
* 2-0: MCS rate base
|
||||
* 0) 6 Mbps
|
||||
* 1) 12 Mbps
|
||||
* 2) 18 Mbps
|
||||
* 3) 24 Mbps
|
||||
* 4) 36 Mbps
|
||||
* 5) 48 Mbps
|
||||
* 6) 54 Mbps
|
||||
* 7) 60 Mbps
|
||||
* 4-3: 0) Single stream (SISO)
|
||||
* 1) Dual stream (MIMO)
|
||||
* 2) Triple stream (MIMO)
|
||||
* 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
|
||||
* (bits 7-6 are zero)
|
||||
*
|
||||
* Together the low 5 bits work out to the MCS index because we don't
|
||||
* support MCSes above 15/23, and 0-7 have one stream, 8-15 have two
|
||||
* streams and 16-23 have three streams. We could also support MCS 32
|
||||
* which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
|
||||
*/
|
||||
#define RATE_HT_MCS_RATE_CODE_MSK 0x7
|
||||
|
||||
/* Bit 10: (1) Use Green Field preamble */
|
||||
#define RATE_HT_MCS_GF_POS 10
|
||||
#define RATE_HT_MCS_GF_MSK (1 << RATE_HT_MCS_GF_POS)
|
||||
|
||||
#define RATE_HT_MCS_INDEX_MSK 0x3f
|
||||
|
||||
/*
|
||||
* Very High-throughput (VHT) rate format for bits 7:0
|
||||
*
|
||||
* 3-0: VHT MCS (0-9)
|
||||
* 5-4: number of streams - 1:
|
||||
* 0) Single stream (SISO)
|
||||
* 1) Dual stream (MIMO)
|
||||
* 2) Triple stream (MIMO)
|
||||
*/
|
||||
|
||||
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
|
||||
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
|
||||
#define RATE_VHT_MCS_NSS_POS 4
|
||||
#define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS)
|
||||
|
||||
/*
|
||||
* Legacy OFDM rate format for bits 7:0
|
||||
*
|
||||
* 3-0: 0xD) 6 Mbps
|
||||
* 0xF) 9 Mbps
|
||||
* 0x5) 12 Mbps
|
||||
* 0x7) 18 Mbps
|
||||
* 0x9) 24 Mbps
|
||||
* 0xB) 36 Mbps
|
||||
* 0x1) 48 Mbps
|
||||
* 0x3) 54 Mbps
|
||||
* (bits 7-4 are 0)
|
||||
*
|
||||
* Legacy CCK rate format for bits 7:0:
|
||||
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK):
|
||||
*
|
||||
* 6-0: 10) 1 Mbps
|
||||
* 20) 2 Mbps
|
||||
* 55) 5.5 Mbps
|
||||
* 110) 11 Mbps
|
||||
* (bit 7 is 0)
|
||||
*/
|
||||
#define RATE_LEGACY_RATE_MSK 0xff
|
||||
|
||||
|
||||
/*
|
||||
* Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz
|
||||
* 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT
|
||||
*/
|
||||
#define RATE_MCS_CHAN_WIDTH_POS 11
|
||||
#define RATE_MCS_CHAN_WIDTH_MSK (3 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
|
||||
/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
|
||||
#define RATE_MCS_SGI_POS 13
|
||||
#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS)
|
||||
|
||||
/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */
|
||||
#define RATE_MCS_ANT_POS 14
|
||||
#define RATE_MCS_ANT_A_MSK (1 << RATE_MCS_ANT_POS)
|
||||
#define RATE_MCS_ANT_B_MSK (2 << RATE_MCS_ANT_POS)
|
||||
#define RATE_MCS_ANT_C_MSK (4 << RATE_MCS_ANT_POS)
|
||||
#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | \
|
||||
RATE_MCS_ANT_B_MSK)
|
||||
#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \
|
||||
RATE_MCS_ANT_C_MSK)
|
||||
#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK
|
||||
#define RATE_MCS_ANT_NUM 3
|
||||
|
||||
/* Bit 17-18: (0) SS, (1) SS*2 */
|
||||
#define RATE_MCS_STBC_POS 17
|
||||
#define RATE_MCS_STBC_MSK (1 << RATE_MCS_STBC_POS)
|
||||
|
||||
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */
|
||||
#define RATE_MCS_BF_POS 19
|
||||
#define RATE_MCS_BF_MSK (1 << RATE_MCS_BF_POS)
|
||||
|
||||
/* Bit 20: (0) ZLF is off, (1) ZLF is on */
|
||||
#define RATE_MCS_ZLF_POS 20
|
||||
#define RATE_MCS_ZLF_MSK (1 << RATE_MCS_ZLF_POS)
|
||||
|
||||
/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */
|
||||
#define RATE_MCS_DUP_POS 24
|
||||
#define RATE_MCS_DUP_MSK (3 << RATE_MCS_DUP_POS)
|
||||
|
||||
/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */
|
||||
#define RATE_MCS_LDPC_POS 27
|
||||
#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS)
|
||||
|
||||
|
||||
/* Link Quality definitions */
|
||||
|
||||
/* # entries in rate scale table to support Tx retries */
|
||||
#define LQ_MAX_RETRY_NUM 16
|
||||
|
||||
/* Link quality command flags, only this one is available */
|
||||
#define LQ_FLAG_SET_STA_TLC_RTS_MSK BIT(0)
|
||||
|
||||
/**
|
||||
* struct iwl_lq_cmd - link quality command
|
||||
* @sta_id: station to update
|
||||
* @control: not used
|
||||
* @flags: combination of LQ_FLAG_*
|
||||
* @mimo_delim: the first SISO index in rs_table, which separates MIMO
|
||||
* and SISO rates
|
||||
* @single_stream_ant_msk: best antenna for SISO (can be dual in CDD).
|
||||
* Should be ANT_[ABC]
|
||||
* @dual_stream_ant_msk: best antennas for MIMO, combination of ANT_[ABC]
|
||||
* @initial_rate_index: first index from rs_table per AC category
|
||||
* @agg_time_limit: aggregation max time threshold in usec/100, meaning
|
||||
* value of 100 is one usec. Range is 100 to 8000
|
||||
* @agg_disable_start_th: try-count threshold for starting aggregation.
|
||||
* If a frame has higher try-count, it should not be selected for
|
||||
* starting an aggregation sequence.
|
||||
* @agg_frame_cnt_limit: max frame count in an aggregation.
|
||||
* 0: no limit
|
||||
* 1: no aggregation (one frame per aggregation)
|
||||
* 2 - 0x3f: maximal number of frames (up to 3f == 63)
|
||||
* @rs_table: array of rates for each TX try, each is rate_n_flags,
|
||||
* meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP
|
||||
* @bf_params: beam forming params, currently not used
|
||||
*/
|
||||
struct iwl_lq_cmd {
|
||||
u8 sta_id;
|
||||
u8 reserved1;
|
||||
u16 control;
|
||||
/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
|
||||
u8 flags;
|
||||
u8 mimo_delim;
|
||||
u8 single_stream_ant_msk;
|
||||
u8 dual_stream_ant_msk;
|
||||
u8 initial_rate_index[AC_NUM];
|
||||
/* LINK_QUAL_AGG_PARAMS_API_S_VER_1 */
|
||||
__le16 agg_time_limit;
|
||||
u8 agg_disable_start_th;
|
||||
u8 agg_frame_cnt_limit;
|
||||
__le32 reserved2;
|
||||
__le32 rs_table[LQ_MAX_RETRY_NUM];
|
||||
__le32 bf_params;
|
||||
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
|
||||
#endif /* __fw_api_rs_h__ */
|
|
@ -0,0 +1,561 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_scan_h__
|
||||
#define __fw_api_scan_h__
|
||||
|
||||
#include "fw-api.h"
|
||||
|
||||
/* Scan Commands, Responses, Notifications */
|
||||
|
||||
/* Masks for iwl_scan_channel.type flags */
|
||||
#define SCAN_CHANNEL_TYPE_PASSIVE 0
|
||||
#define SCAN_CHANNEL_TYPE_ACTIVE BIT(0)
|
||||
#define SCAN_CHANNEL_NARROW_BAND BIT(22)
|
||||
|
||||
/* Max number of IEs for direct SSID scans in a command */
|
||||
#define PROBE_OPTION_MAX 20
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
|
||||
* @channel: band is selected by iwl_scan_cmd "flags" field
|
||||
* @tx_gain: gain for analog radio
|
||||
* @dsp_atten: gain for DSP
|
||||
* @active_dwell: dwell time for active scan in TU, typically 5-50
|
||||
* @passive_dwell: dwell time for passive scan in TU, typically 20-500
|
||||
* @type: type is broken down to these bits:
|
||||
* bit 0: 0 = passive, 1 = active
|
||||
* bits 1-20: SSID direct bit map. If any of these bits is set then
|
||||
* the corresponding SSID IE is transmitted in probe request
|
||||
* (bit i adds IE in position i to the probe request)
|
||||
* bit 22: channel width, 0 = regular, 1 = TGj narrow channel
|
||||
*
|
||||
* @iteration_count:
|
||||
* @iteration_interval:
|
||||
* This struct is used once for each channel in the scan list.
|
||||
* Each channel can independently select:
|
||||
* 1) SSID for directed active scans
|
||||
* 2) Txpower setting (for rate specified within Tx command)
|
||||
* 3) How long to stay on-channel (behavior may be modified by quiet_time,
|
||||
* quiet_plcp_th, good_CRC_th)
|
||||
*
|
||||
* To avoid uCode errors, make sure the following are true (see comments
|
||||
* under struct iwl_scan_cmd about max_out_time and quiet_time):
|
||||
* 1) If using passive_dwell (i.e. passive_dwell != 0):
|
||||
* active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
|
||||
* 2) quiet_time <= active_dwell
|
||||
* 3) If restricting off-channel time (i.e. max_out_time !=0):
|
||||
* passive_dwell < max_out_time
|
||||
* active_dwell < max_out_time
|
||||
*/
|
||||
struct iwl_scan_channel {
|
||||
__le32 type;
|
||||
__le16 channel;
|
||||
__le16 iteration_count;
|
||||
__le32 iteration_interval;
|
||||
__le16 active_dwell;
|
||||
__le16 passive_dwell;
|
||||
} __packed; /* SCAN_CHANNEL_CONTROL_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_ssid_ie - directed scan network information element
|
||||
*
|
||||
* Up to 20 of these may appear in REPLY_SCAN_CMD,
|
||||
* selected by "type" bit field in struct iwl_scan_channel;
|
||||
* each channel may select different ssids from among the 20 entries.
|
||||
* SSID IEs get transmitted in reverse order of entry.
|
||||
*/
|
||||
struct iwl_ssid_ie {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
} __packed; /* SCAN_DIRECT_SSID_IE_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* iwl_scan_flags - masks for scan command flags
|
||||
*@SCAN_FLAGS_PERIODIC_SCAN:
|
||||
*@SCAN_FLAGS_P2P_PUBLIC_ACTION_FRAME_TX:
|
||||
*@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
|
||||
*@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
|
||||
*@SCAN_FLAGS_FRAGMENTED_SCAN:
|
||||
*/
|
||||
enum iwl_scan_flags {
|
||||
SCAN_FLAGS_PERIODIC_SCAN = BIT(0),
|
||||
SCAN_FLAGS_P2P_PUBLIC_ACTION_FRAME_TX = BIT(1),
|
||||
SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2),
|
||||
SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3),
|
||||
SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_scan_type - Scan types for scan command
|
||||
* @SCAN_TYPE_FORCED:
|
||||
* @SCAN_TYPE_BACKGROUND:
|
||||
* @SCAN_TYPE_OS:
|
||||
* @SCAN_TYPE_ROAMING:
|
||||
* @SCAN_TYPE_ACTION:
|
||||
* @SCAN_TYPE_DISCOVERY:
|
||||
* @SCAN_TYPE_DISCOVERY_FORCED:
|
||||
*/
|
||||
enum iwl_scan_type {
|
||||
SCAN_TYPE_FORCED = 0,
|
||||
SCAN_TYPE_BACKGROUND = 1,
|
||||
SCAN_TYPE_OS = 2,
|
||||
SCAN_TYPE_ROAMING = 3,
|
||||
SCAN_TYPE_ACTION = 4,
|
||||
SCAN_TYPE_DISCOVERY = 5,
|
||||
SCAN_TYPE_DISCOVERY_FORCED = 6,
|
||||
}; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
|
||||
|
||||
/* Maximal number of channels to scan */
|
||||
#define MAX_NUM_SCAN_CHANNELS 0x24
|
||||
|
||||
/**
|
||||
* struct iwl_scan_cmd - scan request command
|
||||
* ( SCAN_REQUEST_CMD = 0x80 )
|
||||
* @len: command length in bytes
|
||||
* @scan_flags: scan flags from SCAN_FLAGS_*
|
||||
* @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS)
|
||||
* @quiet_time: in msecs, dwell this time for active scan on quiet channels
|
||||
* @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
|
||||
* this number of packets were received (typically 1)
|
||||
* @passive2active: is auto switching from passive to active allowed (0 or 1)
|
||||
* @rxchain_sel_flags: RXON_RX_CHAIN_*
|
||||
* @max_out_time: in usecs, max out of serving channel time
|
||||
* @suspend_time: how long to pause scan when returning to service channel:
|
||||
* bits 0-19: beacon interal in usecs (suspend before executing)
|
||||
* bits 20-23: reserved
|
||||
* bits 24-31: number of beacons (suspend between channels)
|
||||
* @rxon_flags: RXON_FLG_*
|
||||
* @filter_flags: RXON_FILTER_*
|
||||
* @tx_cmd: for active scans (zero for passive), w/o payload,
|
||||
* no RS so specify TX rate
|
||||
* @direct_scan: direct scan SSIDs
|
||||
* @type: one of SCAN_TYPE_*
|
||||
* @repeats: how many time to repeat the scan
|
||||
*/
|
||||
struct iwl_scan_cmd {
|
||||
__le16 len;
|
||||
u8 scan_flags;
|
||||
u8 channel_count;
|
||||
__le16 quiet_time;
|
||||
__le16 quiet_plcp_th;
|
||||
__le16 passive2active;
|
||||
__le16 rxchain_sel_flags;
|
||||
__le32 max_out_time;
|
||||
__le32 suspend_time;
|
||||
/* RX_ON_FLAGS_API_S_VER_1 */
|
||||
__le32 rxon_flags;
|
||||
__le32 filter_flags;
|
||||
struct iwl_tx_cmd tx_cmd;
|
||||
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
|
||||
__le32 type;
|
||||
__le32 repeats;
|
||||
|
||||
/*
|
||||
* Probe request frame, followed by channel list.
|
||||
*
|
||||
* Size of probe request frame is specified by byte count in tx_cmd.
|
||||
* Channel list follows immediately after probe request frame.
|
||||
* Number of channels in list is specified by channel_count.
|
||||
* Each channel in list is of type:
|
||||
*
|
||||
* struct iwl_scan_channel channels[0];
|
||||
*
|
||||
* NOTE: Only one band of channels can be scanned per pass. You
|
||||
* must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
|
||||
* for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
|
||||
* before requesting another scan.
|
||||
*/
|
||||
u8 data[0];
|
||||
} __packed; /* SCAN_REQUEST_FIXED_PART_API_S_VER_5 */
|
||||
|
||||
/* Response to scan request contains only status with one of these values */
|
||||
#define SCAN_RESPONSE_OK 0x1
|
||||
#define SCAN_RESPONSE_ERROR 0x2
|
||||
|
||||
/*
|
||||
* SCAN_ABORT_CMD = 0x81
|
||||
* When scan abort is requested, the command has no fields except the common
|
||||
* header. The response contains only a status with one of these values.
|
||||
*/
|
||||
#define SCAN_ABORT_POSSIBLE 0x1
|
||||
#define SCAN_ABORT_IGNORED 0x2 /* no pending scans */
|
||||
|
||||
/* TODO: complete documentation */
|
||||
#define SCAN_OWNER_STATUS 0x1
|
||||
#define MEASURE_OWNER_STATUS 0x2
|
||||
|
||||
/**
|
||||
* struct iwl_scan_start_notif - notifies start of scan in the device
|
||||
* ( SCAN_START_NOTIFICATION = 0x82 )
|
||||
* @tsf_low: TSF timer (lower half) in usecs
|
||||
* @tsf_high: TSF timer (higher half) in usecs
|
||||
* @beacon_timer: structured as follows:
|
||||
* bits 0:19 - beacon interval in usecs
|
||||
* bits 20:23 - reserved (0)
|
||||
* bits 24:31 - number of beacons
|
||||
* @channel: which channel is scanned
|
||||
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
|
||||
* @status: one of *_OWNER_STATUS
|
||||
*/
|
||||
struct iwl_scan_start_notif {
|
||||
__le32 tsf_low;
|
||||
__le32 tsf_high;
|
||||
__le32 beacon_timer;
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 reserved[2];
|
||||
__le32 status;
|
||||
} __packed; /* SCAN_START_NTF_API_S_VER_1 */
|
||||
|
||||
/* scan results probe_status first bit indicates success */
|
||||
#define SCAN_PROBE_STATUS_OK 0
|
||||
#define SCAN_PROBE_STATUS_TX_FAILED BIT(0)
|
||||
/* error statuses combined with TX_FAILED */
|
||||
#define SCAN_PROBE_STATUS_FAIL_TTL BIT(1)
|
||||
#define SCAN_PROBE_STATUS_FAIL_BT BIT(2)
|
||||
|
||||
/* How many statistics are gathered for each channel */
|
||||
#define SCAN_RESULTS_STATISTICS 1
|
||||
|
||||
/**
|
||||
* enum iwl_scan_complete_status - status codes for scan complete notifications
|
||||
* @SCAN_COMP_STATUS_OK: scan completed successfully
|
||||
* @SCAN_COMP_STATUS_ABORT: scan was aborted by user
|
||||
* @SCAN_COMP_STATUS_ERR_SLEEP: sending null sleep packet failed
|
||||
* @SCAN_COMP_STATUS_ERR_CHAN_TIMEOUT: timeout before channel is ready
|
||||
* @SCAN_COMP_STATUS_ERR_PROBE: sending probe request failed
|
||||
* @SCAN_COMP_STATUS_ERR_WAKEUP: sending null wakeup packet failed
|
||||
* @SCAN_COMP_STATUS_ERR_ANTENNAS: invalid antennas chosen at scan command
|
||||
* @SCAN_COMP_STATUS_ERR_INTERNAL: internal error caused scan abort
|
||||
* @SCAN_COMP_STATUS_ERR_COEX: medium was lost ot WiMax
|
||||
* @SCAN_COMP_STATUS_P2P_ACTION_OK: P2P public action frame TX was successful
|
||||
* (not an error!)
|
||||
* @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repeatition the driver
|
||||
* asked for
|
||||
* @SCAN_COMP_STATUS_ERR_ALLOC_TE: scan could not allocate time events
|
||||
*/
|
||||
enum iwl_scan_complete_status {
|
||||
SCAN_COMP_STATUS_OK = 0x1,
|
||||
SCAN_COMP_STATUS_ABORT = 0x2,
|
||||
SCAN_COMP_STATUS_ERR_SLEEP = 0x3,
|
||||
SCAN_COMP_STATUS_ERR_CHAN_TIMEOUT = 0x4,
|
||||
SCAN_COMP_STATUS_ERR_PROBE = 0x5,
|
||||
SCAN_COMP_STATUS_ERR_WAKEUP = 0x6,
|
||||
SCAN_COMP_STATUS_ERR_ANTENNAS = 0x7,
|
||||
SCAN_COMP_STATUS_ERR_INTERNAL = 0x8,
|
||||
SCAN_COMP_STATUS_ERR_COEX = 0x9,
|
||||
SCAN_COMP_STATUS_P2P_ACTION_OK = 0xA,
|
||||
SCAN_COMP_STATUS_ITERATION_END = 0x0B,
|
||||
SCAN_COMP_STATUS_ERR_ALLOC_TE = 0x0C,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scan_results_notif - scan results for one channel
|
||||
* ( SCAN_RESULTS_NOTIFICATION = 0x83 )
|
||||
* @channel: which channel the results are from
|
||||
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
|
||||
* @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
|
||||
* @num_probe_not_sent: # of request that weren't sent due to not enough time
|
||||
* @duration: duration spent in channel, in usecs
|
||||
* @statistics: statistics gathered for this channel
|
||||
*/
|
||||
struct iwl_scan_results_notif {
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 probe_status;
|
||||
u8 num_probe_not_sent;
|
||||
__le32 duration;
|
||||
__le32 statistics[SCAN_RESULTS_STATISTICS];
|
||||
} __packed; /* SCAN_RESULT_NTF_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_complete_notif - notifies end of scanning (all channels)
|
||||
* ( SCAN_COMPLETE_NOTIFICATION = 0x84 )
|
||||
* @scanned_channels: number of channels scanned (and number of valid results)
|
||||
* @status: one of SCAN_COMP_STATUS_*
|
||||
* @bt_status: BT on/off status
|
||||
* @last_channel: last channel that was scanned
|
||||
* @tsf_low: TSF timer (lower half) in usecs
|
||||
* @tsf_high: TSF timer (higher half) in usecs
|
||||
* @results: all scan results, only "scanned_channels" of them are valid
|
||||
*/
|
||||
struct iwl_scan_complete_notif {
|
||||
u8 scanned_channels;
|
||||
u8 status;
|
||||
u8 bt_status;
|
||||
u8 last_channel;
|
||||
__le32 tsf_low;
|
||||
__le32 tsf_high;
|
||||
struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS];
|
||||
} __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
|
||||
|
||||
/* scan offload */
|
||||
#define IWL_MAX_SCAN_CHANNELS 40
|
||||
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
|
||||
#define IWL_SCAN_MAX_PROFILES 11
|
||||
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
|
||||
|
||||
/* Default watchdog (in MS) for scheduled scan iteration */
|
||||
#define IWL_SCHED_SCAN_WATCHDOG cpu_to_le16(15000)
|
||||
|
||||
#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)
|
||||
#define CAN_ABORT_STATUS 1
|
||||
|
||||
#define IWL_FULL_SCAN_MULTIPLIER 5
|
||||
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
|
||||
* @scan_flags: see enum iwl_scan_flags
|
||||
* @channel_count: channels in channel list
|
||||
* @quiet_time: dwell time, in milisiconds, on quiet channel
|
||||
* @quiet_plcp_th: quiet channel num of packets threshold
|
||||
* @good_CRC_th: passive to active promotion threshold
|
||||
* @rx_chain: RXON rx chain.
|
||||
* @max_out_time: max uSec to be out of assoceated channel
|
||||
* @suspend_time: pause scan this long when returning to service channel
|
||||
* @flags: RXON flags
|
||||
* @filter_flags: RXONfilter
|
||||
* @tx_cmd: tx command for active scan; for 2GHz and for 5GHz.
|
||||
* @direct_scan: list of SSIDs for directed active scan
|
||||
* @scan_type: see enum iwl_scan_type.
|
||||
* @rep_count: repetition count for each scheduled scan iteration.
|
||||
*/
|
||||
struct iwl_scan_offload_cmd {
|
||||
__le16 len;
|
||||
u8 scan_flags;
|
||||
u8 channel_count;
|
||||
__le16 quiet_time;
|
||||
__le16 quiet_plcp_th;
|
||||
__le16 good_CRC_th;
|
||||
__le16 rx_chain;
|
||||
__le32 max_out_time;
|
||||
__le32 suspend_time;
|
||||
/* RX_ON_FLAGS_API_S_VER_1 */
|
||||
__le32 flags;
|
||||
__le32 filter_flags;
|
||||
struct iwl_tx_cmd tx_cmd[2];
|
||||
/* SCAN_DIRECT_SSID_IE_API_S_VER_1 */
|
||||
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
|
||||
__le32 scan_type;
|
||||
__le32 rep_count;
|
||||
} __packed;
|
||||
|
||||
enum iwl_scan_offload_channel_flags {
|
||||
IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE = BIT(0),
|
||||
IWL_SCAN_OFFLOAD_CHANNEL_NARROW = BIT(22),
|
||||
IWL_SCAN_OFFLOAD_CHANNEL_FULL = BIT(24),
|
||||
IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL = BIT(25),
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S
|
||||
* @type: bitmap - see enum iwl_scan_offload_channel_flags.
|
||||
* 0: passive (0) or active (1) scan.
|
||||
* 1-20: directed scan to i'th ssid.
|
||||
* 22: channel width configuation - 1 for narrow.
|
||||
* 24: full scan.
|
||||
* 25: partial scan.
|
||||
* @channel_number: channel number 1-13 etc.
|
||||
* @iter_count: repetition count for the channel.
|
||||
* @iter_interval: interval between two innteration on one channel.
|
||||
* @dwell_time: entry 0 - active scan, entry 1 - passive scan.
|
||||
*/
|
||||
struct iwl_scan_channel_cfg {
|
||||
__le32 type[IWL_MAX_SCAN_CHANNELS];
|
||||
__le16 channel_number[IWL_MAX_SCAN_CHANNELS];
|
||||
__le16 iter_count[IWL_MAX_SCAN_CHANNELS];
|
||||
__le32 iter_interval[IWL_MAX_SCAN_CHANNELS];
|
||||
u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S
|
||||
* @scan_cmd: scan command fixed part
|
||||
* @channel_cfg: scan channel configuration
|
||||
* @data: probe request frames (one per band)
|
||||
*/
|
||||
struct iwl_scan_offload_cfg {
|
||||
struct iwl_scan_offload_cmd scan_cmd;
|
||||
struct iwl_scan_channel_cfg channel_cfg;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
|
||||
* @ssid: MAC address to filter out
|
||||
* @reported_rssi: AP rssi reported to the host
|
||||
*/
|
||||
struct iwl_scan_offload_blacklist {
|
||||
u8 ssid[ETH_ALEN];
|
||||
u8 reported_rssi;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
enum iwl_scan_offload_network_type {
|
||||
IWL_NETWORK_TYPE_BSS = 1,
|
||||
IWL_NETWORK_TYPE_IBSS = 2,
|
||||
IWL_NETWORK_TYPE_ANY = 3,
|
||||
};
|
||||
|
||||
enum iwl_scan_offload_band_selection {
|
||||
IWL_SCAN_OFFLOAD_SELECT_2_4 = 0x4,
|
||||
IWL_SCAN_OFFLOAD_SELECT_5_2 = 0x8,
|
||||
IWL_SCAN_OFFLOAD_SELECT_ANY = 0xc,
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
|
||||
* @ssid_index: index to ssid list in fixed part
|
||||
* @unicast_cipher: encryption olgorithm to match - bitmap
|
||||
* @aut_alg: authentication olgorithm to match - bitmap
|
||||
* @network_type: enum iwl_scan_offload_network_type
|
||||
* @band_selection: enum iwl_scan_offload_band_selection
|
||||
*/
|
||||
struct iwl_scan_offload_profile {
|
||||
u8 ssid_index;
|
||||
u8 unicast_cipher;
|
||||
u8 auth_alg;
|
||||
u8 network_type;
|
||||
u8 band_selection;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
|
||||
* @blaclist: AP list to filter off from scan results
|
||||
* @profiles: profiles to search for match
|
||||
* @blacklist_len: length of blacklist
|
||||
* @num_profiles: num of profiles in the list
|
||||
*/
|
||||
struct iwl_scan_offload_profile_cfg {
|
||||
struct iwl_scan_offload_blacklist blacklist[IWL_SCAN_MAX_BLACKLIST_LEN];
|
||||
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
|
||||
u8 blacklist_len;
|
||||
u8 num_profiles;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_schedule - schedule of scan offload
|
||||
* @delay: delay between iterations, in seconds.
|
||||
* @iterations: num of scan iterations
|
||||
* @full_scan_mul: number of partial scans before each full scan
|
||||
*/
|
||||
struct iwl_scan_offload_schedule {
|
||||
u16 delay;
|
||||
u8 iterations;
|
||||
u8 full_scan_mul;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* iwl_scan_offload_flags
|
||||
*
|
||||
* IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID: filter mode - upload every beacon or match
|
||||
* ssid list.
|
||||
* IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
|
||||
* IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan
|
||||
* on A band.
|
||||
*/
|
||||
enum iwl_scan_offload_flags {
|
||||
IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID = BIT(0),
|
||||
IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2),
|
||||
IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN = BIT(3),
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_req - scan offload request command
|
||||
* @flags: bitmap - enum iwl_scan_offload_flags.
|
||||
* @watchdog: maximum scan duration in TU.
|
||||
* @delay: delay in seconds before first iteration.
|
||||
* @schedule_line: scan offload schedule, for fast and regular scan.
|
||||
*/
|
||||
struct iwl_scan_offload_req {
|
||||
__le16 flags;
|
||||
__le16 watchdog;
|
||||
__le16 delay;
|
||||
__le16 reserved;
|
||||
struct iwl_scan_offload_schedule schedule_line[2];
|
||||
} __packed;
|
||||
|
||||
enum iwl_scan_offload_compleate_status {
|
||||
IWL_SCAN_OFFLOAD_COMPLETED = 1,
|
||||
IWL_SCAN_OFFLOAD_ABORTED = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1
|
||||
* @last_schedule_line: last schedule line executed (fast or regular)
|
||||
* @last_schedule_iteration: last scan iteration executed before scan abort
|
||||
* @status: enum iwl_scan_offload_compleate_status
|
||||
*/
|
||||
struct iwl_scan_offload_complete {
|
||||
u8 last_schedule_line;
|
||||
u8 last_schedule_iteration;
|
||||
u8 status;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,380 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_sta_h__
|
||||
#define __fw_api_sta_h__
|
||||
|
||||
/**
|
||||
* enum iwl_sta_flags - flags for the ADD_STA host command
|
||||
* @STA_FLG_REDUCED_TX_PWR_CTRL:
|
||||
* @STA_FLG_REDUCED_TX_PWR_DATA:
|
||||
* @STA_FLG_FLG_ANT_MSK: Antenna selection
|
||||
* @STA_FLG_PS: set if STA is in Power Save
|
||||
* @STA_FLG_INVALID: set if STA is invalid
|
||||
* @STA_FLG_DLP_EN: Direct Link Protocol is enabled
|
||||
* @STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs
|
||||
* @STA_FLG_DRAIN_FLOW: drain flow
|
||||
* @STA_FLG_PAN: STA is for PAN interface
|
||||
* @STA_FLG_CLASS_AUTH:
|
||||
* @STA_FLG_CLASS_ASSOC:
|
||||
* @STA_FLG_CLASS_MIMO_PROT:
|
||||
* @STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU
|
||||
* @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
|
||||
* @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
|
||||
* initialised by driver and can be updated by fw upon reception of
|
||||
* action frames that can change the channel width. When cleared the fw
|
||||
* will send all the frames in 20MHz even when FAT channel is requested.
|
||||
* @STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the
|
||||
* driver and can be updated by fw upon reception of action frames.
|
||||
* @STA_FLG_MFP_EN: Management Frame Protection
|
||||
*/
|
||||
enum iwl_sta_flags {
|
||||
STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3),
|
||||
STA_FLG_REDUCED_TX_PWR_DATA = BIT(6),
|
||||
|
||||
STA_FLG_FLG_ANT_A = (1 << 4),
|
||||
STA_FLG_FLG_ANT_B = (2 << 4),
|
||||
STA_FLG_FLG_ANT_MSK = (STA_FLG_FLG_ANT_A |
|
||||
STA_FLG_FLG_ANT_B),
|
||||
|
||||
STA_FLG_PS = BIT(8),
|
||||
STA_FLG_INVALID = BIT(9),
|
||||
STA_FLG_DLP_EN = BIT(10),
|
||||
STA_FLG_SET_ALL_KEYS = BIT(11),
|
||||
STA_FLG_DRAIN_FLOW = BIT(12),
|
||||
STA_FLG_PAN = BIT(13),
|
||||
STA_FLG_CLASS_AUTH = BIT(14),
|
||||
STA_FLG_CLASS_ASSOC = BIT(15),
|
||||
STA_FLG_RTS_MIMO_PROT = BIT(17),
|
||||
|
||||
STA_FLG_MAX_AGG_SIZE_SHIFT = 19,
|
||||
STA_FLG_MAX_AGG_SIZE_8K = (0 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_16K = (1 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_32K = (2 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_64K = (3 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_128K = (4 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_256K = (5 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_512K = (6 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_1024K = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
STA_FLG_MAX_AGG_SIZE_MSK = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
|
||||
|
||||
STA_FLG_AGG_MPDU_DENS_SHIFT = 23,
|
||||
STA_FLG_AGG_MPDU_DENS_2US = (4 << STA_FLG_AGG_MPDU_DENS_SHIFT),
|
||||
STA_FLG_AGG_MPDU_DENS_4US = (5 << STA_FLG_AGG_MPDU_DENS_SHIFT),
|
||||
STA_FLG_AGG_MPDU_DENS_8US = (6 << STA_FLG_AGG_MPDU_DENS_SHIFT),
|
||||
STA_FLG_AGG_MPDU_DENS_16US = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
|
||||
STA_FLG_AGG_MPDU_DENS_MSK = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
|
||||
|
||||
STA_FLG_FAT_EN_20MHZ = (0 << 26),
|
||||
STA_FLG_FAT_EN_40MHZ = (1 << 26),
|
||||
STA_FLG_FAT_EN_80MHZ = (2 << 26),
|
||||
STA_FLG_FAT_EN_160MHZ = (3 << 26),
|
||||
STA_FLG_FAT_EN_MSK = (3 << 26),
|
||||
|
||||
STA_FLG_MIMO_EN_SISO = (0 << 28),
|
||||
STA_FLG_MIMO_EN_MIMO2 = (1 << 28),
|
||||
STA_FLG_MIMO_EN_MIMO3 = (2 << 28),
|
||||
STA_FLG_MIMO_EN_MSK = (3 << 28),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_sta_key_flag - key flags for the ADD_STA host command
|
||||
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithm
|
||||
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
|
||||
* station info array (1 - n 1X mode)
|
||||
* @STA_KEY_FLG_KEYID_MSK: the index of the key
|
||||
* @STA_KEY_NOT_VALID: key is invalid
|
||||
* @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key
|
||||
* @STA_KEY_MULTICAST: set for multical key
|
||||
* @STA_KEY_MFP: key is used for Management Frame Protection
|
||||
*/
|
||||
enum iwl_sta_key_flag {
|
||||
STA_KEY_FLG_NO_ENC = (0 << 0),
|
||||
STA_KEY_FLG_WEP = (1 << 0),
|
||||
STA_KEY_FLG_CCM = (2 << 0),
|
||||
STA_KEY_FLG_TKIP = (3 << 0),
|
||||
STA_KEY_FLG_CMAC = (6 << 0),
|
||||
STA_KEY_FLG_ENC_UNKNOWN = (7 << 0),
|
||||
STA_KEY_FLG_EN_MSK = (7 << 0),
|
||||
|
||||
STA_KEY_FLG_WEP_KEY_MAP = BIT(3),
|
||||
STA_KEY_FLG_KEYID_POS = 8,
|
||||
STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS),
|
||||
STA_KEY_NOT_VALID = BIT(11),
|
||||
STA_KEY_FLG_WEP_13BYTES = BIT(12),
|
||||
STA_KEY_MULTICAST = BIT(14),
|
||||
STA_KEY_MFP = BIT(15),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
|
||||
* @STA_MODIFY_KEY: this command modifies %key
|
||||
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
|
||||
* @STA_MODIFY_TX_RATE: unused
|
||||
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
|
||||
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
|
||||
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
|
||||
* @STA_MODIFY_PROT_TH:
|
||||
* @STA_MODIFY_QUEUES: modify the queues used by this station
|
||||
*/
|
||||
enum iwl_sta_modify_flag {
|
||||
STA_MODIFY_KEY = BIT(0),
|
||||
STA_MODIFY_TID_DISABLE_TX = BIT(1),
|
||||
STA_MODIFY_TX_RATE = BIT(2),
|
||||
STA_MODIFY_ADD_BA_TID = BIT(3),
|
||||
STA_MODIFY_REMOVE_BA_TID = BIT(4),
|
||||
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
|
||||
STA_MODIFY_PROT_TH = BIT(6),
|
||||
STA_MODIFY_QUEUES = BIT(7),
|
||||
};
|
||||
|
||||
#define STA_MODE_MODIFY 1
|
||||
|
||||
/**
|
||||
* enum iwl_sta_sleep_flag - type of sleep of the station
|
||||
* @STA_SLEEP_STATE_AWAKE:
|
||||
* @STA_SLEEP_STATE_PS_POLL:
|
||||
* @STA_SLEEP_STATE_UAPSD:
|
||||
*/
|
||||
enum iwl_sta_sleep_flag {
|
||||
STA_SLEEP_STATE_AWAKE = 0,
|
||||
STA_SLEEP_STATE_PS_POLL = BIT(0),
|
||||
STA_SLEEP_STATE_UAPSD = BIT(1),
|
||||
};
|
||||
|
||||
/* STA ID and color bits definitions */
|
||||
#define STA_ID_SEED (0x0f)
|
||||
#define STA_ID_POS (0)
|
||||
#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS)
|
||||
|
||||
#define STA_COLOR_SEED (0x7)
|
||||
#define STA_COLOR_POS (4)
|
||||
#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS)
|
||||
|
||||
#define STA_ID_N_COLOR_GET_COLOR(id_n_color) \
|
||||
(((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS)
|
||||
#define STA_ID_N_COLOR_GET_ID(id_n_color) \
|
||||
(((id_n_color) & STA_ID_MSK) >> STA_ID_POS)
|
||||
|
||||
#define STA_KEY_MAX_NUM (16)
|
||||
#define STA_KEY_IDX_INVALID (0xff)
|
||||
#define STA_KEY_MAX_DATA_KEY_NUM (4)
|
||||
#define IWL_MAX_GLOBAL_KEYS (4)
|
||||
#define STA_KEY_LEN_WEP40 (5)
|
||||
#define STA_KEY_LEN_WEP104 (13)
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_keyinfo - key information
|
||||
* @key_flags: type %iwl_sta_key_flag
|
||||
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
|
||||
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
|
||||
* @key_offset: key offset in the fw's key table
|
||||
* @key: 16-byte unicast decryption key
|
||||
* @tx_secur_seq_cnt: initial RSC / PN needed for replay check
|
||||
* @hw_tkip_mic_rx_key: byte: MIC Rx Key - used for TKIP only
|
||||
* @hw_tkip_mic_tx_key: byte: MIC Tx Key - used for TKIP only
|
||||
*/
|
||||
struct iwl_mvm_keyinfo {
|
||||
__le16 key_flags;
|
||||
u8 tkip_rx_tsc_byte2;
|
||||
u8 reserved1;
|
||||
__le16 tkip_rx_ttak[5];
|
||||
u8 key_offset;
|
||||
u8 reserved2;
|
||||
u8 key[16];
|
||||
__le64 tx_secur_seq_cnt;
|
||||
__le64 hw_tkip_mic_rx_key;
|
||||
__le64 hw_tkip_mic_tx_key;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_add_sta_cmd - Add / modify a station in the fw's station table
|
||||
* ( REPLY_ADD_STA = 0x18 )
|
||||
* @add_modify: 1: modify existing, 0: add new station
|
||||
* @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent
|
||||
* @multicast_tx_key_id: multicast tx key id. Relevant only when multicast key
|
||||
* sent
|
||||
* @mac_id_n_color: the Mac context this station belongs to
|
||||
* @addr[ETH_ALEN]: station's MAC address
|
||||
* @sta_id: index of station in uCode's station table
|
||||
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
|
||||
* alone. 1 - modify, 0 - don't change.
|
||||
* @key: look at %iwl_mvm_keyinfo
|
||||
* @station_flags: look at %iwl_sta_flags
|
||||
* @station_flags_msk: what of %station_flags have changed
|
||||
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
|
||||
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
|
||||
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
|
||||
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
|
||||
* add_immediate_ba_ssn.
|
||||
* @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)
|
||||
* Set %STA_MODIFY_REMOVE_BA_TID to use this field
|
||||
* @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with
|
||||
* add_immediate_ba_tid.
|
||||
* @sleep_tx_count: number of packets to transmit to station even though it is
|
||||
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
|
||||
* keeps track of STA sleep state.
|
||||
* @sleep_state_flags: Look at %iwl_sta_sleep_flag.
|
||||
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
|
||||
* mac-addr.
|
||||
* @beamform_flags: beam forming controls
|
||||
* @tfd_queue_msk: tfd queues used by this station
|
||||
*
|
||||
* The device contains an internal table of per-station information, with info
|
||||
* on security keys, aggregation parameters, and Tx rates for initial Tx
|
||||
* attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).
|
||||
*
|
||||
* ADD_STA sets up the table entry for one station, either creating a new
|
||||
* entry, or modifying a pre-existing one.
|
||||
*/
|
||||
struct iwl_mvm_add_sta_cmd {
|
||||
u8 add_modify;
|
||||
u8 unicast_tx_key_id;
|
||||
u8 multicast_tx_key_id;
|
||||
u8 reserved1;
|
||||
__le32 mac_id_n_color;
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 reserved2;
|
||||
u8 sta_id;
|
||||
u8 modify_mask;
|
||||
__le16 reserved3;
|
||||
struct iwl_mvm_keyinfo key;
|
||||
__le32 station_flags;
|
||||
__le32 station_flags_msk;
|
||||
__le16 tid_disable_tx;
|
||||
__le16 reserved4;
|
||||
u8 add_immediate_ba_tid;
|
||||
u8 remove_immediate_ba_tid;
|
||||
__le16 add_immediate_ba_ssn;
|
||||
__le16 sleep_tx_count;
|
||||
__le16 sleep_state_flags;
|
||||
__le16 assoc_id;
|
||||
__le16 beamform_flags;
|
||||
__le32 tfd_queue_msk;
|
||||
} __packed; /* ADD_STA_CMD_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command
|
||||
* @ADD_STA_SUCCESS: operation was executed successfully
|
||||
* @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table
|
||||
* @ADD_STA_IMMEDIATE_BA_FAILURE: can't add Rx block ack session
|
||||
* @ADD_STA_MODIFY_NON_EXISTING_STA: driver requested to modify a station that
|
||||
* doesn't exist.
|
||||
*/
|
||||
enum iwl_mvm_add_sta_rsp_status {
|
||||
ADD_STA_SUCCESS = 0x1,
|
||||
ADD_STA_STATIONS_OVERLOAD = 0x2,
|
||||
ADD_STA_IMMEDIATE_BA_FAILURE = 0x4,
|
||||
ADD_STA_MODIFY_NON_EXISTING_STA = 0x8,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_rm_sta_cmd - Add / modify a station in the fw's station table
|
||||
* ( REMOVE_STA = 0x19 )
|
||||
* @sta_id: the station id of the station to be removed
|
||||
*/
|
||||
struct iwl_mvm_rm_sta_cmd {
|
||||
u8 sta_id;
|
||||
u8 reserved[3];
|
||||
} __packed; /* REMOVE_STA_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_mgmt_mcast_key_cmd
|
||||
* ( MGMT_MCAST_KEY = 0x1f )
|
||||
* @ctrl_flags: %iwl_sta_key_flag
|
||||
* @IGTK:
|
||||
* @K1: IGTK master key
|
||||
* @K2: IGTK sub key
|
||||
* @sta_id: station ID that support IGTK
|
||||
* @key_id:
|
||||
* @receive_seq_cnt: initial RSC/PN needed for replay check
|
||||
*/
|
||||
struct iwl_mvm_mgmt_mcast_key_cmd {
|
||||
__le32 ctrl_flags;
|
||||
u8 IGTK[16];
|
||||
u8 K1[16];
|
||||
u8 K2[16];
|
||||
__le32 key_id;
|
||||
__le32 sta_id;
|
||||
__le64 receive_seq_cnt;
|
||||
} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */
|
||||
|
||||
struct iwl_mvm_wep_key {
|
||||
u8 key_index;
|
||||
u8 key_offset;
|
||||
__le16 reserved1;
|
||||
u8 key_size;
|
||||
u8 reserved2[3];
|
||||
u8 key[16];
|
||||
} __packed;
|
||||
|
||||
struct iwl_mvm_wep_key_cmd {
|
||||
__le32 mac_id_n_color;
|
||||
u8 num_keys;
|
||||
u8 decryption_type;
|
||||
u8 flags;
|
||||
u8 reserved;
|
||||
struct iwl_mvm_wep_key wep_key[0];
|
||||
} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */
|
||||
|
||||
|
||||
#endif /* __fw_api_sta_h__ */
|
|
@ -0,0 +1,580 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_tx_h__
|
||||
#define __fw_api_tx_h__
|
||||
|
||||
/**
|
||||
* enum iwl_tx_flags - bitmasks for tx_flags in TX command
|
||||
* @TX_CMD_FLG_PROT_REQUIRE: use RTS or CTS-to-self to protect the frame
|
||||
* @TX_CMD_FLG_ACK: expect ACK from receiving station
|
||||
* @TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.
|
||||
* Otherwise, use rate_n_flags from the TX command
|
||||
* @TX_CMD_FLG_BA: this frame is a block ack
|
||||
* @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
|
||||
* Must set TX_CMD_FLG_ACK with this flag.
|
||||
* @TX_CMD_FLG_TXOP_PROT: protect frame with full TXOP protection
|
||||
* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
|
||||
* @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
|
||||
* @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
|
||||
* @TX_CMD_FLG_BT_DIS: disable BT priority for this frame
|
||||
* @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.
|
||||
* Should be set for mgmt, non-QOS data, mcast, bcast and in scan command
|
||||
* @TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU
|
||||
* @TX_CMD_FLG_NEXT_FRAME: this frame includes information of the next frame
|
||||
* @TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame
|
||||
* Should be set for beacons and probe responses
|
||||
* @TX_CMD_FLG_CALIB: activate PA TX power calibrations
|
||||
* @TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count
|
||||
* @TX_CMD_FLG_AGG_START: allow this frame to start aggregation
|
||||
* @TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.
|
||||
* Should be set for 26/30 length MAC headers
|
||||
* @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
|
||||
* @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration
|
||||
* @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
|
||||
* @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that
|
||||
* @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
|
||||
* @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
|
||||
* @TX_CMD_FLG_EXEC_PAPD: execute PAPD
|
||||
* @TX_CMD_FLG_PAPD_TYPE: 0 for reference power, 1 for nominal power
|
||||
* @TX_CMD_FLG_HCCA_CHUNK: mark start of TSPEC chunk
|
||||
*/
|
||||
enum iwl_tx_flags {
|
||||
TX_CMD_FLG_PROT_REQUIRE = BIT(0),
|
||||
TX_CMD_FLG_ACK = BIT(3),
|
||||
TX_CMD_FLG_STA_RATE = BIT(4),
|
||||
TX_CMD_FLG_BA = BIT(5),
|
||||
TX_CMD_FLG_BAR = BIT(6),
|
||||
TX_CMD_FLG_TXOP_PROT = BIT(7),
|
||||
TX_CMD_FLG_VHT_NDPA = BIT(8),
|
||||
TX_CMD_FLG_HT_NDPA = BIT(9),
|
||||
TX_CMD_FLG_CSI_FDBK2HOST = BIT(10),
|
||||
TX_CMD_FLG_BT_DIS = BIT(12),
|
||||
TX_CMD_FLG_SEQ_CTL = BIT(13),
|
||||
TX_CMD_FLG_MORE_FRAG = BIT(14),
|
||||
TX_CMD_FLG_NEXT_FRAME = BIT(15),
|
||||
TX_CMD_FLG_TSF = BIT(16),
|
||||
TX_CMD_FLG_CALIB = BIT(17),
|
||||
TX_CMD_FLG_KEEP_SEQ_CTL = BIT(18),
|
||||
TX_CMD_FLG_AGG_START = BIT(19),
|
||||
TX_CMD_FLG_MH_PAD = BIT(20),
|
||||
TX_CMD_FLG_RESP_TO_DRV = BIT(21),
|
||||
TX_CMD_FLG_CCMP_AGG = BIT(22),
|
||||
TX_CMD_FLG_TKIP_MIC_DONE = BIT(23),
|
||||
TX_CMD_FLG_CTS_ONLY = BIT(24),
|
||||
TX_CMD_FLG_DUR = BIT(25),
|
||||
TX_CMD_FLG_FW_DROP = BIT(26),
|
||||
TX_CMD_FLG_EXEC_PAPD = BIT(27),
|
||||
TX_CMD_FLG_PAPD_TYPE = BIT(28),
|
||||
TX_CMD_FLG_HCCA_CHUNK = BIT(31)
|
||||
}; /* TX_FLAGS_BITS_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* TX command security control
|
||||
*/
|
||||
#define TX_CMD_SEC_WEP 0x01
|
||||
#define TX_CMD_SEC_CCM 0x02
|
||||
#define TX_CMD_SEC_TKIP 0x03
|
||||
#define TX_CMD_SEC_WEP_KEY_IDX_POS 6
|
||||
#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0
|
||||
#define TX_CMD_SEC_KEY128 0x08
|
||||
|
||||
/* TODO: how does these values are OK with only 16 bit variable??? */
|
||||
/*
|
||||
* TX command next frame info
|
||||
*
|
||||
* bits 0:2 - security control (TX_CMD_SEC_*)
|
||||
* bit 3 - immediate ACK required
|
||||
* bit 4 - rate is taken from STA table
|
||||
* bit 5 - frame belongs to BA stream
|
||||
* bit 6 - immediate BA response expected
|
||||
* bit 7 - unused
|
||||
* bits 8:15 - Station ID
|
||||
* bits 16:31 - rate
|
||||
*/
|
||||
#define TX_CMD_NEXT_FRAME_ACK_MSK (0x8)
|
||||
#define TX_CMD_NEXT_FRAME_STA_RATE_MSK (0x10)
|
||||
#define TX_CMD_NEXT_FRAME_BA_MSK (0x20)
|
||||
#define TX_CMD_NEXT_FRAME_IMM_BA_RSP_MSK (0x40)
|
||||
#define TX_CMD_NEXT_FRAME_FLAGS_MSK (0xf8)
|
||||
#define TX_CMD_NEXT_FRAME_STA_ID_MSK (0xff00)
|
||||
#define TX_CMD_NEXT_FRAME_STA_ID_POS (8)
|
||||
#define TX_CMD_NEXT_FRAME_RATE_MSK (0xffff0000)
|
||||
#define TX_CMD_NEXT_FRAME_RATE_POS (16)
|
||||
|
||||
/*
|
||||
* TX command Frame life time in us - to be written in pm_frame_timeout
|
||||
*/
|
||||
#define TX_CMD_LIFE_TIME_INFINITE 0xFFFFFFFF
|
||||
#define TX_CMD_LIFE_TIME_DEFAULT 2000000 /* 2000 ms*/
|
||||
#define TX_CMD_LIFE_TIME_PROBE_RESP 40000 /* 40 ms */
|
||||
#define TX_CMD_LIFE_TIME_EXPIRED_FRAME 0
|
||||
|
||||
/*
|
||||
* TID for non QoS frames - to be written in tid_tspec
|
||||
*/
|
||||
#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT
|
||||
|
||||
/*
|
||||
* Limits on the retransmissions - to be written in {data,rts}_retry_limit
|
||||
*/
|
||||
#define IWL_DEFAULT_TX_RETRY 15
|
||||
#define IWL_MGMT_DFAULT_RETRY_LIMIT 3
|
||||
#define IWL_RTS_DFAULT_RETRY_LIMIT 60
|
||||
#define IWL_BAR_DFAULT_RETRY_LIMIT 60
|
||||
#define IWL_LOW_RETRY_LIMIT 7
|
||||
|
||||
/* TODO: complete documentation for try_cnt and btkill_cnt */
|
||||
/**
|
||||
* struct iwl_tx_cmd - TX command struct to FW
|
||||
* ( TX_CMD = 0x1c )
|
||||
* @len: in bytes of the payload, see below for details
|
||||
* @next_frame_len: same as len, but for next frame (0 if not applicable)
|
||||
* Used for fragmentation and bursting, but not in 11n aggregation.
|
||||
* @tx_flags: combination of TX_CMD_FLG_*
|
||||
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
|
||||
* cleared. Combination of RATE_MCS_*
|
||||
* @sta_id: index of destination station in FW station table
|
||||
* @sec_ctl: security control, TX_CMD_SEC_*
|
||||
* @initial_rate_index: index into the the rate table for initial TX attempt.
|
||||
* Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.
|
||||
* @key: security key
|
||||
* @next_frame_flags: TX_CMD_SEC_* and TX_CMD_NEXT_FRAME_*
|
||||
* @life_time: frame life time (usecs??)
|
||||
* @dram_lsb_ptr: Physical address of scratch area in the command (try_cnt +
|
||||
* btkill_cnd + reserved), first 32 bits. "0" disables usage.
|
||||
* @dram_msb_ptr: upper bits of the scratch physical address
|
||||
* @rts_retry_limit: max attempts for RTS
|
||||
* @data_retry_limit: max attempts to send the data packet
|
||||
* @tid_spec: TID/tspec
|
||||
* @pm_frame_timeout: PM TX frame timeout
|
||||
* @driver_txop: duration od EDCA TXOP, in 32-usec units. Set this if not
|
||||
* specified by HCCA protocol
|
||||
*
|
||||
* The byte count (both len and next_frame_len) includes MAC header
|
||||
* (24/26/30/32 bytes)
|
||||
* + 2 bytes pad if 26/30 header size
|
||||
* + 8 byte IV for CCM or TKIP (not used for WEP)
|
||||
* + Data payload
|
||||
* + 8-byte MIC (not used for CCM/WEP)
|
||||
* It does not include post-MAC padding, i.e.,
|
||||
* MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.
|
||||
* Range of len: 14-2342 bytes.
|
||||
*
|
||||
* After the struct fields the MAC header is placed, plus any padding,
|
||||
* and then the actial payload.
|
||||
*/
|
||||
struct iwl_tx_cmd {
|
||||
__le16 len;
|
||||
__le16 next_frame_len;
|
||||
__le32 tx_flags;
|
||||
/* DRAM_SCRATCH_API_U_VER_1 */
|
||||
u8 try_cnt;
|
||||
u8 btkill_cnt;
|
||||
__le16 reserved;
|
||||
__le32 rate_n_flags;
|
||||
u8 sta_id;
|
||||
u8 sec_ctl;
|
||||
u8 initial_rate_index;
|
||||
u8 reserved2;
|
||||
u8 key[16];
|
||||
__le16 next_frame_flags;
|
||||
__le16 reserved3;
|
||||
__le32 life_time;
|
||||
__le32 dram_lsb_ptr;
|
||||
u8 dram_msb_ptr;
|
||||
u8 rts_retry_limit;
|
||||
u8 data_retry_limit;
|
||||
u8 tid_tspec;
|
||||
__le16 pm_frame_timeout;
|
||||
__le16 driver_txop;
|
||||
u8 payload[0];
|
||||
struct ieee80211_hdr hdr[0];
|
||||
} __packed; /* TX_CMD_API_S_VER_3 */
|
||||
|
||||
/*
|
||||
* TX response related data
|
||||
*/
|
||||
|
||||
/*
|
||||
* enum iwl_tx_status - status that is returned by the fw after attempts to Tx
|
||||
* @TX_STATUS_SUCCESS:
|
||||
* @TX_STATUS_DIRECT_DONE:
|
||||
* @TX_STATUS_POSTPONE_DELAY:
|
||||
* @TX_STATUS_POSTPONE_FEW_BYTES:
|
||||
* @TX_STATUS_POSTPONE_BT_PRIO:
|
||||
* @TX_STATUS_POSTPONE_QUIET_PERIOD:
|
||||
* @TX_STATUS_POSTPONE_CALC_TTAK:
|
||||
* @TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
|
||||
* @TX_STATUS_FAIL_SHORT_LIMIT:
|
||||
* @TX_STATUS_FAIL_LONG_LIMIT:
|
||||
* @TX_STATUS_FAIL_UNDERRUN:
|
||||
* @TX_STATUS_FAIL_DRAIN_FLOW:
|
||||
* @TX_STATUS_FAIL_RFKILL_FLUSH:
|
||||
* @TX_STATUS_FAIL_LIFE_EXPIRE:
|
||||
* @TX_STATUS_FAIL_DEST_PS:
|
||||
* @TX_STATUS_FAIL_HOST_ABORTED:
|
||||
* @TX_STATUS_FAIL_BT_RETRY:
|
||||
* @TX_STATUS_FAIL_STA_INVALID:
|
||||
* @TX_TATUS_FAIL_FRAG_DROPPED:
|
||||
* @TX_STATUS_FAIL_TID_DISABLE:
|
||||
* @TX_STATUS_FAIL_FIFO_FLUSHED:
|
||||
* @TX_STATUS_FAIL_SMALL_CF_POLL:
|
||||
* @TX_STATUS_FAIL_FW_DROP:
|
||||
* @TX_STATUS_FAIL_STA_COLOR_MISMATCH: mismatch between color of Tx cmd and
|
||||
* STA table
|
||||
* @TX_FRAME_STATUS_INTERNAL_ABORT:
|
||||
* @TX_MODE_MSK:
|
||||
* @TX_MODE_NO_BURST:
|
||||
* @TX_MODE_IN_BURST_SEQ:
|
||||
* @TX_MODE_FIRST_IN_BURST:
|
||||
* @TX_QUEUE_NUM_MSK:
|
||||
*
|
||||
* Valid only if frame_count =1
|
||||
* TODO: complete documentation
|
||||
*/
|
||||
enum iwl_tx_status {
|
||||
TX_STATUS_MSK = 0x000000ff,
|
||||
TX_STATUS_SUCCESS = 0x01,
|
||||
TX_STATUS_DIRECT_DONE = 0x02,
|
||||
/* postpone TX */
|
||||
TX_STATUS_POSTPONE_DELAY = 0x40,
|
||||
TX_STATUS_POSTPONE_FEW_BYTES = 0x41,
|
||||
TX_STATUS_POSTPONE_BT_PRIO = 0x42,
|
||||
TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43,
|
||||
TX_STATUS_POSTPONE_CALC_TTAK = 0x44,
|
||||
/* abort TX */
|
||||
TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81,
|
||||
TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
|
||||
TX_STATUS_FAIL_LONG_LIMIT = 0x83,
|
||||
TX_STATUS_FAIL_UNDERRUN = 0x84,
|
||||
TX_STATUS_FAIL_DRAIN_FLOW = 0x85,
|
||||
TX_STATUS_FAIL_RFKILL_FLUSH = 0x86,
|
||||
TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
|
||||
TX_STATUS_FAIL_DEST_PS = 0x88,
|
||||
TX_STATUS_FAIL_HOST_ABORTED = 0x89,
|
||||
TX_STATUS_FAIL_BT_RETRY = 0x8a,
|
||||
TX_STATUS_FAIL_STA_INVALID = 0x8b,
|
||||
TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
|
||||
TX_STATUS_FAIL_TID_DISABLE = 0x8d,
|
||||
TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
|
||||
TX_STATUS_FAIL_SMALL_CF_POLL = 0x8f,
|
||||
TX_STATUS_FAIL_FW_DROP = 0x90,
|
||||
TX_STATUS_FAIL_STA_COLOR_MISMATCH = 0x91,
|
||||
TX_STATUS_INTERNAL_ABORT = 0x92,
|
||||
TX_MODE_MSK = 0x00000f00,
|
||||
TX_MODE_NO_BURST = 0x00000000,
|
||||
TX_MODE_IN_BURST_SEQ = 0x00000100,
|
||||
TX_MODE_FIRST_IN_BURST = 0x00000200,
|
||||
TX_QUEUE_NUM_MSK = 0x0001f000,
|
||||
TX_NARROW_BW_MSK = 0x00060000,
|
||||
TX_NARROW_BW_1DIV2 = 0x00020000,
|
||||
TX_NARROW_BW_1DIV4 = 0x00040000,
|
||||
TX_NARROW_BW_1DIV8 = 0x00060000,
|
||||
};
|
||||
|
||||
/*
|
||||
* enum iwl_tx_agg_status - TX aggregation status
|
||||
* @AGG_TX_STATE_STATUS_MSK:
|
||||
* @AGG_TX_STATE_TRANSMITTED:
|
||||
* @AGG_TX_STATE_UNDERRUN:
|
||||
* @AGG_TX_STATE_BT_PRIO:
|
||||
* @AGG_TX_STATE_FEW_BYTES:
|
||||
* @AGG_TX_STATE_ABORT:
|
||||
* @AGG_TX_STATE_LAST_SENT_TTL:
|
||||
* @AGG_TX_STATE_LAST_SENT_TRY_CNT:
|
||||
* @AGG_TX_STATE_LAST_SENT_BT_KILL:
|
||||
* @AGG_TX_STATE_SCD_QUERY:
|
||||
* @AGG_TX_STATE_TEST_BAD_CRC32:
|
||||
* @AGG_TX_STATE_RESPONSE:
|
||||
* @AGG_TX_STATE_DUMP_TX:
|
||||
* @AGG_TX_STATE_DELAY_TX:
|
||||
* @AGG_TX_STATE_TRY_CNT_MSK: Retry count for 1st frame in aggregation (retries
|
||||
* occur if tx failed for this frame when it was a member of a previous
|
||||
* aggregation block). If rate scaling is used, retry count indicates the
|
||||
* rate table entry used for all frames in the new agg.
|
||||
*@ AGG_TX_STATE_SEQ_NUM_MSK: Command ID and sequence number of Tx command for
|
||||
* this frame
|
||||
*
|
||||
* TODO: complete documentation
|
||||
*/
|
||||
enum iwl_tx_agg_status {
|
||||
AGG_TX_STATE_STATUS_MSK = 0x00fff,
|
||||
AGG_TX_STATE_TRANSMITTED = 0x000,
|
||||
AGG_TX_STATE_UNDERRUN = 0x001,
|
||||
AGG_TX_STATE_BT_PRIO = 0x002,
|
||||
AGG_TX_STATE_FEW_BYTES = 0x004,
|
||||
AGG_TX_STATE_ABORT = 0x008,
|
||||
AGG_TX_STATE_LAST_SENT_TTL = 0x010,
|
||||
AGG_TX_STATE_LAST_SENT_TRY_CNT = 0x020,
|
||||
AGG_TX_STATE_LAST_SENT_BT_KILL = 0x040,
|
||||
AGG_TX_STATE_SCD_QUERY = 0x080,
|
||||
AGG_TX_STATE_TEST_BAD_CRC32 = 0x0100,
|
||||
AGG_TX_STATE_RESPONSE = 0x1ff,
|
||||
AGG_TX_STATE_DUMP_TX = 0x200,
|
||||
AGG_TX_STATE_DELAY_TX = 0x400,
|
||||
AGG_TX_STATE_TRY_CNT_POS = 12,
|
||||
AGG_TX_STATE_TRY_CNT_MSK = 0xf << AGG_TX_STATE_TRY_CNT_POS,
|
||||
};
|
||||
|
||||
#define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL| \
|
||||
AGG_TX_STATE_LAST_SENT_TRY_CNT| \
|
||||
AGG_TX_STATE_LAST_SENT_BT_KILL)
|
||||
|
||||
/*
|
||||
* The mask below describes a status where we are absolutely sure that the MPDU
|
||||
* wasn't sent. For BA/Underrun we cannot be that sure. All we know that we've
|
||||
* written the bytes to the TXE, but we know nothing about what the DSP did.
|
||||
*/
|
||||
#define AGG_TX_STAT_FRAME_NOT_SENT (AGG_TX_STATE_FEW_BYTES | \
|
||||
AGG_TX_STATE_ABORT | \
|
||||
AGG_TX_STATE_SCD_QUERY)
|
||||
|
||||
/*
|
||||
* REPLY_TX = 0x1c (response)
|
||||
*
|
||||
* This response may be in one of two slightly different formats, indicated
|
||||
* by the frame_count field:
|
||||
*
|
||||
* 1) No aggregation (frame_count == 1). This reports Tx results for a single
|
||||
* frame. Multiple attempts, at various bit rates, may have been made for
|
||||
* this frame.
|
||||
*
|
||||
* 2) Aggregation (frame_count > 1). This reports Tx results for two or more
|
||||
* frames that used block-acknowledge. All frames were transmitted at
|
||||
* same rate. Rate scaling may have been used if first frame in this new
|
||||
* agg block failed in previous agg block(s).
|
||||
*
|
||||
* Note that, for aggregation, ACK (block-ack) status is not delivered
|
||||
* here; block-ack has not been received by the time the device records
|
||||
* this status.
|
||||
* This status relates to reasons the tx might have been blocked or aborted
|
||||
* within the device, rather than whether it was received successfully by
|
||||
* the destination station.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct agg_tx_status - per packet TX aggregation status
|
||||
* @status: enum iwl_tx_agg_status
|
||||
* @sequence: Sequence # for this frame's Tx cmd (not SSN!)
|
||||
*/
|
||||
struct agg_tx_status {
|
||||
__le16 status;
|
||||
__le16 sequence;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* definitions for initial rate index field
|
||||
* bits [3:0] initial rate index
|
||||
* bits [6:4] rate table color, used for the initial rate
|
||||
* bit-7 invalid rate indication
|
||||
*/
|
||||
#define TX_RES_INIT_RATE_INDEX_MSK 0x0f
|
||||
#define TX_RES_RATE_TABLE_COLOR_MSK 0x70
|
||||
#define TX_RES_INV_RATE_INDEX_MSK 0x80
|
||||
|
||||
#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
|
||||
#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tx_resp - notifies that fw is TXing a packet
|
||||
* ( REPLY_TX = 0x1c )
|
||||
* @frame_count: 1 no aggregation, >1 aggregation
|
||||
* @bt_kill_count: num of times blocked by bluetooth (unused for agg)
|
||||
* @failure_rts: num of failures due to unsuccessful RTS
|
||||
* @failure_frame: num failures due to no ACK (unused for agg)
|
||||
* @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the
|
||||
* Tx of all the batch. RATE_MCS_*
|
||||
* @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.
|
||||
* for agg: RTS + CTS + aggregation tx time + block-ack time.
|
||||
* in usec.
|
||||
* @pa_status: tx power info
|
||||
* @pa_integ_res_a: tx power info
|
||||
* @pa_integ_res_b: tx power info
|
||||
* @pa_integ_res_c: tx power info
|
||||
* @measurement_req_id: tx power info
|
||||
* @tfd_info: TFD information set by the FH
|
||||
* @seq_ctl: sequence control from the Tx cmd
|
||||
* @byte_cnt: byte count from the Tx cmd
|
||||
* @tlc_info: TLC rate info
|
||||
* @ra_tid: bits [3:0] = ra, bits [7:4] = tid
|
||||
* @frame_ctrl: frame control
|
||||
* @status: for non-agg: frame status TX_STATUS_*
|
||||
* for agg: status of 1st frame, AGG_TX_STATE_*; other frame status fields
|
||||
* follow this one, up to frame_count.
|
||||
*
|
||||
* After the array of statuses comes the SSN of the SCD. Look at
|
||||
* %iwl_mvm_get_scd_ssn for more details.
|
||||
*/
|
||||
struct iwl_mvm_tx_resp {
|
||||
u8 frame_count;
|
||||
u8 bt_kill_count;
|
||||
u8 failure_rts;
|
||||
u8 failure_frame;
|
||||
__le32 initial_rate;
|
||||
__le16 wireless_media_time;
|
||||
|
||||
u8 pa_status;
|
||||
u8 pa_integ_res_a[3];
|
||||
u8 pa_integ_res_b[3];
|
||||
u8 pa_integ_res_c[3];
|
||||
__le16 measurement_req_id;
|
||||
__le16 reserved;
|
||||
|
||||
__le32 tfd_info;
|
||||
__le16 seq_ctl;
|
||||
__le16 byte_cnt;
|
||||
u8 tlc_info;
|
||||
u8 ra_tid;
|
||||
__le16 frame_ctrl;
|
||||
|
||||
struct agg_tx_status status;
|
||||
} __packed; /* TX_RSP_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_ba_notif - notifies about reception of BA
|
||||
* ( BA_NOTIF = 0xc5 )
|
||||
* @sta_addr_lo32: lower 32 bits of the MAC address
|
||||
* @sta_addr_hi16: upper 16 bits of the MAC address
|
||||
* @sta_id: Index of recipient (BA-sending) station in fw's station table
|
||||
* @tid: tid of the session
|
||||
* @seq_ctl:
|
||||
* @bitmap: the bitmap of the BA notification as seen in the air
|
||||
* @scd_flow: the tx queue this BA relates to
|
||||
* @scd_ssn: the index of the last contiguously sent packet
|
||||
* @txed: number of Txed frames in this batch
|
||||
* @txed_2_done: number of Acked frames in this batch
|
||||
*/
|
||||
struct iwl_mvm_ba_notif {
|
||||
__le32 sta_addr_lo32;
|
||||
__le16 sta_addr_hi16;
|
||||
__le16 reserved;
|
||||
|
||||
u8 sta_id;
|
||||
u8 tid;
|
||||
__le16 seq_ctl;
|
||||
__le64 bitmap;
|
||||
__le16 scd_flow;
|
||||
__le16 scd_ssn;
|
||||
u8 txed;
|
||||
u8 txed_2_done;
|
||||
__le16 reserved1;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_mac_beacon_cmd - beacon template command
|
||||
* @tx: the tx commands associated with the beacon frame
|
||||
* @template_id: currently equal to the mac context id of the coresponding
|
||||
* mac.
|
||||
* @tim_idx: the offset of the tim IE in the beacon
|
||||
* @tim_size: the length of the tim IE
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd {
|
||||
struct iwl_tx_cmd tx;
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
struct ieee80211_hdr frame[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_dump_control - dump (flush) control flags
|
||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
||||
* and the TFD queues are empty.
|
||||
*/
|
||||
enum iwl_dump_control {
|
||||
DUMP_TX_FIFO_FLUSH = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_tx_path_flush_cmd -- queue/FIFO flush command
|
||||
* @queues_ctl: bitmap of queues to flush
|
||||
* @flush_ctl: control flags
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_tx_path_flush_cmd {
|
||||
__le32 queues_ctl;
|
||||
__le16 flush_ctl;
|
||||
__le16 reserved;
|
||||
} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* iwl_mvm_get_scd_ssn - returns the SSN of the SCD
|
||||
* @tx_resp: the Tx response from the fw (agg or non-agg)
|
||||
*
|
||||
* When the fw sends an AMPDU, it fetches the MPDUs one after the other. Since
|
||||
* it can't know that everything will go well until the end of the AMPDU, it
|
||||
* can't know in advance the number of MPDUs that will be sent in the current
|
||||
* batch. This is why it writes the agg Tx response while it fetches the MPDUs.
|
||||
* Hence, it can't know in advance what the SSN of the SCD will be at the end
|
||||
* of the batch. This is why the SSN of the SCD is written at the end of the
|
||||
* whole struct at a variable offset. This function knows how to cope with the
|
||||
* variable offset and returns the SSN of the SCD.
|
||||
*/
|
||||
static inline u32 iwl_mvm_get_scd_ssn(struct iwl_mvm_tx_resp *tx_resp)
|
||||
{
|
||||
return le32_to_cpup((__le32 *)&tx_resp->status +
|
||||
tx_resp->frame_count) & 0xfff;
|
||||
}
|
||||
|
||||
#endif /* __fw_api_tx_h__ */
|
|
@ -0,0 +1,949 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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 __fw_api_h__
|
||||
#define __fw_api_h__
|
||||
|
||||
#include "fw-api-rs.h"
|
||||
#include "fw-api-tx.h"
|
||||
#include "fw-api-sta.h"
|
||||
#include "fw-api-mac.h"
|
||||
#include "fw-api-power.h"
|
||||
#include "fw-api-d3.h"
|
||||
|
||||
/* queue and FIFO numbers by usage */
|
||||
enum {
|
||||
IWL_MVM_OFFCHANNEL_QUEUE = 8,
|
||||
IWL_MVM_CMD_QUEUE = 9,
|
||||
IWL_MVM_AUX_QUEUE = 15,
|
||||
IWL_MVM_FIRST_AGG_QUEUE = 16,
|
||||
IWL_MVM_NUM_QUEUES = 20,
|
||||
IWL_MVM_LAST_AGG_QUEUE = IWL_MVM_NUM_QUEUES - 1,
|
||||
IWL_MVM_CMD_FIFO = 7
|
||||
};
|
||||
|
||||
#define IWL_MVM_STATION_COUNT 16
|
||||
|
||||
/* commands */
|
||||
enum {
|
||||
MVM_ALIVE = 0x1,
|
||||
REPLY_ERROR = 0x2,
|
||||
|
||||
INIT_COMPLETE_NOTIF = 0x4,
|
||||
|
||||
/* PHY context commands */
|
||||
PHY_CONTEXT_CMD = 0x8,
|
||||
DBG_CFG = 0x9,
|
||||
|
||||
/* station table */
|
||||
ADD_STA = 0x18,
|
||||
REMOVE_STA = 0x19,
|
||||
|
||||
/* TX */
|
||||
TX_CMD = 0x1c,
|
||||
TXPATH_FLUSH = 0x1e,
|
||||
MGMT_MCAST_KEY = 0x1f,
|
||||
|
||||
/* global key */
|
||||
WEP_KEY = 0x20,
|
||||
|
||||
/* MAC and Binding commands */
|
||||
MAC_CONTEXT_CMD = 0x28,
|
||||
TIME_EVENT_CMD = 0x29, /* both CMD and response */
|
||||
TIME_EVENT_NOTIFICATION = 0x2a,
|
||||
BINDING_CONTEXT_CMD = 0x2b,
|
||||
TIME_QUOTA_CMD = 0x2c,
|
||||
|
||||
LQ_CMD = 0x4e,
|
||||
|
||||
/* Calibration */
|
||||
TEMPERATURE_NOTIFICATION = 0x62,
|
||||
CALIBRATION_CFG_CMD = 0x65,
|
||||
CALIBRATION_RES_NOTIFICATION = 0x66,
|
||||
CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
|
||||
RADIO_VERSION_NOTIFICATION = 0x68,
|
||||
|
||||
/* Scan offload */
|
||||
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
|
||||
SCAN_OFFLOAD_ABORT_CMD = 0x52,
|
||||
SCAN_OFFLOAD_COMPLETE = 0x6D,
|
||||
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
|
||||
SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
|
||||
|
||||
/* Phy */
|
||||
PHY_CONFIGURATION_CMD = 0x6a,
|
||||
CALIB_RES_NOTIF_PHY_DB = 0x6b,
|
||||
/* PHY_DB_CMD = 0x6c, */
|
||||
|
||||
/* Power */
|
||||
POWER_TABLE_CMD = 0x77,
|
||||
|
||||
/* Scanning */
|
||||
SCAN_REQUEST_CMD = 0x80,
|
||||
SCAN_ABORT_CMD = 0x81,
|
||||
SCAN_START_NOTIFICATION = 0x82,
|
||||
SCAN_RESULTS_NOTIFICATION = 0x83,
|
||||
SCAN_COMPLETE_NOTIFICATION = 0x84,
|
||||
|
||||
/* NVM */
|
||||
NVM_ACCESS_CMD = 0x88,
|
||||
|
||||
SET_CALIB_DEFAULT_CMD = 0x8e,
|
||||
|
||||
BEACON_TEMPLATE_CMD = 0x91,
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||
STATISTICS_NOTIFICATION = 0x9d,
|
||||
|
||||
/* RF-KILL commands and notifications */
|
||||
CARD_STATE_CMD = 0xa0,
|
||||
CARD_STATE_NOTIFICATION = 0xa1,
|
||||
|
||||
REPLY_RX_PHY_CMD = 0xc0,
|
||||
REPLY_RX_MPDU_CMD = 0xc1,
|
||||
BA_NOTIF = 0xc5,
|
||||
|
||||
REPLY_DEBUG_CMD = 0xf0,
|
||||
DEBUG_LOG_MSG = 0xf7,
|
||||
|
||||
/* D3 commands/notifications */
|
||||
D3_CONFIG_CMD = 0xd3,
|
||||
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
|
||||
OFFLOADS_QUERY_CMD = 0xd5,
|
||||
REMOTE_WAKE_CONFIG_CMD = 0xd6,
|
||||
|
||||
/* for WoWLAN in particular */
|
||||
WOWLAN_PATTERNS = 0xe0,
|
||||
WOWLAN_CONFIGURATION = 0xe1,
|
||||
WOWLAN_TSC_RSC_PARAM = 0xe2,
|
||||
WOWLAN_TKIP_PARAM = 0xe3,
|
||||
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
|
||||
WOWLAN_GET_STATUSES = 0xe5,
|
||||
WOWLAN_TX_POWER_PER_DB = 0xe6,
|
||||
|
||||
/* and for NetDetect */
|
||||
NET_DETECT_CONFIG_CMD = 0x54,
|
||||
NET_DETECT_PROFILES_QUERY_CMD = 0x56,
|
||||
NET_DETECT_PROFILES_CMD = 0x57,
|
||||
NET_DETECT_HOTSPOTS_CMD = 0x58,
|
||||
NET_DETECT_HOTSPOTS_QUERY_CMD = 0x59,
|
||||
|
||||
REPLY_MAX = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cmd_response - generic response struct for most commands
|
||||
* @status: status of the command asked, changes for each one
|
||||
*/
|
||||
struct iwl_cmd_response {
|
||||
__le32 status;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_tx_ant_cfg_cmd
|
||||
* @valid: valid antenna configuration
|
||||
*/
|
||||
struct iwl_tx_ant_cfg_cmd {
|
||||
__le32 valid;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Calibration control struct.
|
||||
* Sent as part of the phy configuration command.
|
||||
* @flow_trigger: bitmap for which calibrations to perform according to
|
||||
* flow triggers.
|
||||
* @event_trigger: bitmap for which calibrations to perform according to
|
||||
* event triggers.
|
||||
*/
|
||||
struct iwl_calib_ctrl {
|
||||
__le32 flow_trigger;
|
||||
__le32 event_trigger;
|
||||
} __packed;
|
||||
|
||||
/* This enum defines the bitmap of various calibrations to enable in both
|
||||
* init ucode and runtime ucode through CALIBRATION_CFG_CMD.
|
||||
*/
|
||||
enum iwl_calib_cfg {
|
||||
IWL_CALIB_CFG_XTAL_IDX = BIT(0),
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX = BIT(1),
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX = BIT(2),
|
||||
IWL_CALIB_CFG_PAPD_IDX = BIT(3),
|
||||
IWL_CALIB_CFG_TX_PWR_IDX = BIT(4),
|
||||
IWL_CALIB_CFG_DC_IDX = BIT(5),
|
||||
IWL_CALIB_CFG_BB_FILTER_IDX = BIT(6),
|
||||
IWL_CALIB_CFG_LO_LEAKAGE_IDX = BIT(7),
|
||||
IWL_CALIB_CFG_TX_IQ_IDX = BIT(8),
|
||||
IWL_CALIB_CFG_TX_IQ_SKEW_IDX = BIT(9),
|
||||
IWL_CALIB_CFG_RX_IQ_IDX = BIT(10),
|
||||
IWL_CALIB_CFG_RX_IQ_SKEW_IDX = BIT(11),
|
||||
IWL_CALIB_CFG_SENSITIVITY_IDX = BIT(12),
|
||||
IWL_CALIB_CFG_CHAIN_NOISE_IDX = BIT(13),
|
||||
IWL_CALIB_CFG_DISCONNECTED_ANT_IDX = BIT(14),
|
||||
IWL_CALIB_CFG_ANT_COUPLING_IDX = BIT(15),
|
||||
IWL_CALIB_CFG_DAC_IDX = BIT(16),
|
||||
IWL_CALIB_CFG_ABS_IDX = BIT(17),
|
||||
IWL_CALIB_CFG_AGC_IDX = BIT(18),
|
||||
};
|
||||
|
||||
/*
|
||||
* Phy configuration command.
|
||||
*/
|
||||
struct iwl_phy_cfg_cmd {
|
||||
__le32 phy_cfg;
|
||||
struct iwl_calib_ctrl calib_control;
|
||||
} __packed;
|
||||
|
||||
#define PHY_CFG_RADIO_TYPE (BIT(0) | BIT(1))
|
||||
#define PHY_CFG_RADIO_STEP (BIT(2) | BIT(3))
|
||||
#define PHY_CFG_RADIO_DASH (BIT(4) | BIT(5))
|
||||
#define PHY_CFG_PRODUCT_NUMBER (BIT(6) | BIT(7))
|
||||
#define PHY_CFG_TX_CHAIN_A BIT(8)
|
||||
#define PHY_CFG_TX_CHAIN_B BIT(9)
|
||||
#define PHY_CFG_TX_CHAIN_C BIT(10)
|
||||
#define PHY_CFG_RX_CHAIN_A BIT(12)
|
||||
#define PHY_CFG_RX_CHAIN_B BIT(13)
|
||||
#define PHY_CFG_RX_CHAIN_C BIT(14)
|
||||
|
||||
|
||||
/* Target of the NVM_ACCESS_CMD */
|
||||
enum {
|
||||
NVM_ACCESS_TARGET_CACHE = 0,
|
||||
NVM_ACCESS_TARGET_OTP = 1,
|
||||
NVM_ACCESS_TARGET_EEPROM = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM.
|
||||
* @op_code: 0 - read, 1 - write.
|
||||
* @target: NVM_ACCESS_TARGET_*. should be 0 for read.
|
||||
* @cache_refresh: 0 - None, 1- NVM.
|
||||
* @offset: offset in the nvm data.
|
||||
* @length: of the chunk.
|
||||
* @data: empty on read, the NVM chunk on write
|
||||
*/
|
||||
struct iwl_nvm_access_cmd_ver1 {
|
||||
u8 op_code;
|
||||
u8 target;
|
||||
u8 cache_refresh;
|
||||
u8 reserved;
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD
|
||||
* @offset: the offset in the nvm data
|
||||
* @length: of the chunk
|
||||
* @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write
|
||||
*/
|
||||
struct iwl_nvm_access_resp_ver1 {
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */
|
||||
|
||||
/* Section types for NVM_ACCESS_CMD version 2 */
|
||||
enum {
|
||||
NVM_SECTION_TYPE_HW = 0,
|
||||
NVM_SECTION_TYPE_SW,
|
||||
NVM_SECTION_TYPE_PAPD,
|
||||
NVM_SECTION_TYPE_BT,
|
||||
NVM_SECTION_TYPE_CALIBRATION,
|
||||
NVM_SECTION_TYPE_PRODUCTION,
|
||||
NVM_SECTION_TYPE_POST_FCS_CALIB,
|
||||
NVM_NUM_OF_SECTIONS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_cmd_ver2 - Request the device to send an NVM section
|
||||
* @op_code: 0 - read, 1 - write
|
||||
* @target: NVM_ACCESS_TARGET_*
|
||||
* @type: NVM_SECTION_TYPE_*
|
||||
* @offset: offset in bytes into the section
|
||||
* @length: in bytes, to read/write
|
||||
* @data: if write operation, the data to write. On read its empty
|
||||
*/
|
||||
struct iwl_nvm_access_cmd_ver2 {
|
||||
u8 op_code;
|
||||
u8 target;
|
||||
__le16 type;
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_resp_ver2 - response to NVM_ACCESS_CMD
|
||||
* @offset: offset in bytes into the section
|
||||
* @length: in bytes, either how much was written or read
|
||||
* @type: NVM_SECTION_TYPE_*
|
||||
* @status: 0 for success, fail otherwise
|
||||
* @data: if read operation, the data returned. Empty on write.
|
||||
*/
|
||||
struct iwl_nvm_access_resp_ver2 {
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
__le16 type;
|
||||
__le16 status;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_2 */
|
||||
|
||||
/* MVM_ALIVE 0x1 */
|
||||
|
||||
/* alive response is_valid values */
|
||||
#define ALIVE_RESP_UCODE_OK BIT(0)
|
||||
#define ALIVE_RESP_RFKILL BIT(1)
|
||||
|
||||
/* alive response ver_type values */
|
||||
enum {
|
||||
FW_TYPE_HW = 0,
|
||||
FW_TYPE_PROT = 1,
|
||||
FW_TYPE_AP = 2,
|
||||
FW_TYPE_WOWLAN = 3,
|
||||
FW_TYPE_TIMING = 4,
|
||||
FW_TYPE_WIPAN = 5
|
||||
};
|
||||
|
||||
/* alive response ver_subtype values */
|
||||
enum {
|
||||
FW_SUBTYPE_FULL_FEATURE = 0,
|
||||
FW_SUBTYPE_BOOTSRAP = 1, /* Not valid */
|
||||
FW_SUBTYPE_REDUCED = 2,
|
||||
FW_SUBTYPE_ALIVE_ONLY = 3,
|
||||
FW_SUBTYPE_WOWLAN = 4,
|
||||
FW_SUBTYPE_AP_SUBTYPE = 5,
|
||||
FW_SUBTYPE_WIPAN = 6,
|
||||
FW_SUBTYPE_INITIALIZE = 9
|
||||
};
|
||||
|
||||
#define IWL_ALIVE_STATUS_ERR 0xDEAD
|
||||
#define IWL_ALIVE_STATUS_OK 0xCAFE
|
||||
|
||||
#define IWL_ALIVE_FLG_RFKILL BIT(0)
|
||||
|
||||
struct mvm_alive_resp {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
u8 ucode_minor;
|
||||
u8 ucode_major;
|
||||
__le16 id;
|
||||
u8 api_minor;
|
||||
u8 api_major;
|
||||
u8 ver_subtype;
|
||||
u8 ver_type;
|
||||
u8 mac;
|
||||
u8 opt;
|
||||
__le16 reserved2;
|
||||
__le32 timestamp;
|
||||
__le32 error_event_table_ptr; /* SRAM address for error log */
|
||||
__le32 log_event_table_ptr; /* SRAM address for event log */
|
||||
__le32 cpu_register_ptr;
|
||||
__le32 dbgm_config_ptr;
|
||||
__le32 alive_counter_ptr;
|
||||
__le32 scd_base_ptr; /* SRAM address for SCD */
|
||||
} __packed; /* ALIVE_RES_API_S_VER_1 */
|
||||
|
||||
/* Error response/notification */
|
||||
enum {
|
||||
FW_ERR_UNKNOWN_CMD = 0x0,
|
||||
FW_ERR_INVALID_CMD_PARAM = 0x1,
|
||||
FW_ERR_SERVICE = 0x2,
|
||||
FW_ERR_ARC_MEMORY = 0x3,
|
||||
FW_ERR_ARC_CODE = 0x4,
|
||||
FW_ERR_WATCH_DOG = 0x5,
|
||||
FW_ERR_WEP_GRP_KEY_INDX = 0x10,
|
||||
FW_ERR_WEP_KEY_SIZE = 0x11,
|
||||
FW_ERR_OBSOLETE_FUNC = 0x12,
|
||||
FW_ERR_UNEXPECTED = 0xFE,
|
||||
FW_ERR_FATAL = 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_error_resp - FW error indication
|
||||
* ( REPLY_ERROR = 0x2 )
|
||||
* @error_type: one of FW_ERR_*
|
||||
* @cmd_id: the command ID for which the error occured
|
||||
* @bad_cmd_seq_num: sequence number of the erroneous command
|
||||
* @error_service: which service created the error, applicable only if
|
||||
* error_type = 2, otherwise 0
|
||||
* @timestamp: TSF in usecs.
|
||||
*/
|
||||
struct iwl_error_resp {
|
||||
__le32 error_type;
|
||||
u8 cmd_id;
|
||||
u8 reserved1;
|
||||
__le16 bad_cmd_seq_num;
|
||||
__le32 error_service;
|
||||
__le64 timestamp;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Common PHY, MAC and Bindings definitions */
|
||||
|
||||
#define MAX_MACS_IN_BINDING (3)
|
||||
#define MAX_BINDINGS (4)
|
||||
#define AUX_BINDING_INDEX (3)
|
||||
#define MAX_PHYS (4)
|
||||
|
||||
/* Used to extract ID and color from the context dword */
|
||||
#define FW_CTXT_ID_POS (0)
|
||||
#define FW_CTXT_ID_MSK (0xff << FW_CTXT_ID_POS)
|
||||
#define FW_CTXT_COLOR_POS (8)
|
||||
#define FW_CTXT_COLOR_MSK (0xff << FW_CTXT_COLOR_POS)
|
||||
#define FW_CTXT_INVALID (0xffffffff)
|
||||
|
||||
#define FW_CMD_ID_AND_COLOR(_id, _color) ((_id << FW_CTXT_ID_POS) |\
|
||||
(_color << FW_CTXT_COLOR_POS))
|
||||
|
||||
/* Possible actions on PHYs, MACs and Bindings */
|
||||
enum {
|
||||
FW_CTXT_ACTION_STUB = 0,
|
||||
FW_CTXT_ACTION_ADD,
|
||||
FW_CTXT_ACTION_MODIFY,
|
||||
FW_CTXT_ACTION_REMOVE,
|
||||
FW_CTXT_ACTION_NUM
|
||||
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
|
||||
|
||||
/* Time Events */
|
||||
|
||||
/* Time Event types, according to MAC type */
|
||||
enum iwl_time_event_type {
|
||||
/* BSS Station Events */
|
||||
TE_BSS_STA_AGGRESSIVE_ASSOC,
|
||||
TE_BSS_STA_ASSOC,
|
||||
TE_BSS_EAP_DHCP_PROT,
|
||||
TE_BSS_QUIET_PERIOD,
|
||||
|
||||
/* P2P Device Events */
|
||||
TE_P2P_DEVICE_DISCOVERABLE,
|
||||
TE_P2P_DEVICE_LISTEN,
|
||||
TE_P2P_DEVICE_ACTION_SCAN,
|
||||
TE_P2P_DEVICE_FULL_SCAN,
|
||||
|
||||
/* P2P Client Events */
|
||||
TE_P2P_CLIENT_AGGRESSIVE_ASSOC,
|
||||
TE_P2P_CLIENT_ASSOC,
|
||||
TE_P2P_CLIENT_QUIET_PERIOD,
|
||||
|
||||
/* P2P GO Events */
|
||||
TE_P2P_GO_ASSOC_PROT,
|
||||
TE_P2P_GO_REPETITIVE_NOA,
|
||||
TE_P2P_GO_CT_WINDOW,
|
||||
|
||||
/* WiDi Sync Events */
|
||||
TE_WIDI_TX_SYNC,
|
||||
|
||||
TE_MAX
|
||||
}; /* MAC_EVENT_TYPE_API_E_VER_1 */
|
||||
|
||||
/* Time Event dependencies: none, on another TE, or in a specific time */
|
||||
enum {
|
||||
TE_INDEPENDENT = 0,
|
||||
TE_DEP_OTHER = 1,
|
||||
TE_DEP_TSF = 2,
|
||||
TE_EVENT_SOCIOPATHIC = 4,
|
||||
}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
|
||||
|
||||
/* When to send Time Event notifications and to whom (internal = FW) */
|
||||
enum {
|
||||
TE_NOTIF_NONE = 0,
|
||||
TE_NOTIF_HOST_START = 0x1,
|
||||
TE_NOTIF_HOST_END = 0x2,
|
||||
TE_NOTIF_INTERNAL_START = 0x4,
|
||||
TE_NOTIF_INTERNAL_END = 0x8
|
||||
}; /* MAC_EVENT_ACTION_API_E_VER_1 */
|
||||
|
||||
/*
|
||||
* @TE_FRAG_NONE: fragmentation of the time event is NOT allowed.
|
||||
* @TE_FRAG_SINGLE: fragmentation of the time event is allowed, but only
|
||||
* the first fragment is scheduled.
|
||||
* @TE_FRAG_DUAL: fragmentation of the time event is allowed, but only
|
||||
* the first 2 fragments are scheduled.
|
||||
* @TE_FRAG_ENDLESS: fragmentation of the time event is allowed, and any number
|
||||
* of fragments are valid.
|
||||
*
|
||||
* Other than the constant defined above, specifying a fragmentation value 'x'
|
||||
* means that the event can be fragmented but only the first 'x' will be
|
||||
* scheduled.
|
||||
*/
|
||||
enum {
|
||||
TE_FRAG_NONE = 0,
|
||||
TE_FRAG_SINGLE = 1,
|
||||
TE_FRAG_DUAL = 2,
|
||||
TE_FRAG_ENDLESS = 0xffffffff
|
||||
};
|
||||
|
||||
/* Repeat the time event endlessly (until removed) */
|
||||
#define TE_REPEAT_ENDLESS (0xffffffff)
|
||||
/* If a Time Event has bounded repetitions, this is the maximal value */
|
||||
#define TE_REPEAT_MAX_MSK (0x0fffffff)
|
||||
/* If a Time Event can be fragmented, this is the max number of fragments */
|
||||
#define TE_FRAG_MAX_MSK (0x0fffffff)
|
||||
|
||||
/**
|
||||
* struct iwl_time_event_cmd - configuring Time Events
|
||||
* ( TIME_EVENT_CMD = 0x29 )
|
||||
* @id_and_color: ID and color of the relevant MAC
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @id: this field has two meanings, depending on the action:
|
||||
* If the action is ADD, then it means the type of event to add.
|
||||
* For all other actions it is the unique event ID assigned when the
|
||||
* event was added by the FW.
|
||||
* @apply_time: When to start the Time Event (in GP2)
|
||||
* @max_delay: maximum delay to event's start (apply time), in TU
|
||||
* @depends_on: the unique ID of the event we depend on (if any)
|
||||
* @interval: interval between repetitions, in TU
|
||||
* @interval_reciprocal: 2^32 / interval
|
||||
* @duration: duration of event in TU
|
||||
* @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
|
||||
* @dep_policy: one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
|
||||
* @is_present: 0 or 1, are we present or absent during the Time Event
|
||||
* @max_frags: maximal number of fragments the Time Event can be divided to
|
||||
* @notify: notifications using TE_NOTIF_* (whom to notify when)
|
||||
*/
|
||||
struct iwl_time_event_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
__le32 id;
|
||||
/* MAC_TIME_EVENT_DATA_API_S_VER_1 */
|
||||
__le32 apply_time;
|
||||
__le32 max_delay;
|
||||
__le32 dep_policy;
|
||||
__le32 depends_on;
|
||||
__le32 is_present;
|
||||
__le32 max_frags;
|
||||
__le32 interval;
|
||||
__le32 interval_reciprocal;
|
||||
__le32 duration;
|
||||
__le32 repeat;
|
||||
__le32 notify;
|
||||
} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_event_resp - response structure to iwl_time_event_cmd
|
||||
* @status: bit 0 indicates success, all others specify errors
|
||||
* @id: the Time Event type
|
||||
* @unique_id: the unique ID assigned (in ADD) or given (others) to the TE
|
||||
* @id_and_color: ID and color of the relevant MAC
|
||||
*/
|
||||
struct iwl_time_event_resp {
|
||||
__le32 status;
|
||||
__le32 id;
|
||||
__le32 unique_id;
|
||||
__le32 id_and_color;
|
||||
} __packed; /* MAC_TIME_EVENT_RSP_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_event_notif - notifications of time event start/stop
|
||||
* ( TIME_EVENT_NOTIFICATION = 0x2a )
|
||||
* @timestamp: action timestamp in GP2
|
||||
* @session_id: session's unique id
|
||||
* @unique_id: unique id of the Time Event itself
|
||||
* @id_and_color: ID and color of the relevant MAC
|
||||
* @action: one of TE_NOTIF_START or TE_NOTIF_END
|
||||
* @status: true if scheduled, false otherwise (not executed)
|
||||
*/
|
||||
struct iwl_time_event_notif {
|
||||
__le32 timestamp;
|
||||
__le32 session_id;
|
||||
__le32 unique_id;
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
__le32 status;
|
||||
} __packed; /* MAC_TIME_EVENT_NTFY_API_S_VER_1 */
|
||||
|
||||
|
||||
/* Bindings and Time Quota */
|
||||
|
||||
/**
|
||||
* struct iwl_binding_cmd - configuring bindings
|
||||
* ( BINDING_CONTEXT_CMD = 0x2b )
|
||||
* @id_and_color: ID and color of the relevant Binding
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @macs: array of MAC id and colors which belong to the binding
|
||||
* @phy: PHY id and color which belongs to the binding
|
||||
*/
|
||||
struct iwl_binding_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* BINDING_DATA_API_S_VER_1 */
|
||||
__le32 macs[MAX_MACS_IN_BINDING];
|
||||
__le32 phy;
|
||||
} __packed; /* BINDING_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_quota_data - configuration of time quota per binding
|
||||
* @id_and_color: ID and color of the relevant Binding
|
||||
* @quota: absolute time quota in TU. The scheduler will try to divide the
|
||||
* remainig quota (after Time Events) according to this quota.
|
||||
* @max_duration: max uninterrupted context duration in TU
|
||||
*/
|
||||
struct iwl_time_quota_data {
|
||||
__le32 id_and_color;
|
||||
__le32 quota;
|
||||
__le32 max_duration;
|
||||
} __packed; /* TIME_QUOTA_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_quota_cmd - configuration of time quota between bindings
|
||||
* ( TIME_QUOTA_CMD = 0x2c )
|
||||
* @quotas: allocations per binding
|
||||
*/
|
||||
struct iwl_time_quota_cmd {
|
||||
struct iwl_time_quota_data quotas[MAX_BINDINGS];
|
||||
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
|
||||
|
||||
|
||||
/* PHY context */
|
||||
|
||||
/* Supported bands */
|
||||
#define PHY_BAND_5 (0)
|
||||
#define PHY_BAND_24 (1)
|
||||
|
||||
/* Supported channel width, vary if there is VHT support */
|
||||
#define PHY_VHT_CHANNEL_MODE20 (0x0)
|
||||
#define PHY_VHT_CHANNEL_MODE40 (0x1)
|
||||
#define PHY_VHT_CHANNEL_MODE80 (0x2)
|
||||
#define PHY_VHT_CHANNEL_MODE160 (0x3)
|
||||
|
||||
/*
|
||||
* Control channel position:
|
||||
* For legacy set bit means upper channel, otherwise lower.
|
||||
* For VHT - bit-2 marks if the control is lower/upper relative to center-freq
|
||||
* bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
|
||||
* center_freq
|
||||
* |
|
||||
* 40Mhz |_______|_______|
|
||||
* 80Mhz |_______|_______|_______|_______|
|
||||
* 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|
|
||||
* code 011 010 001 000 | 100 101 110 111
|
||||
*/
|
||||
#define PHY_VHT_CTRL_POS_1_BELOW (0x0)
|
||||
#define PHY_VHT_CTRL_POS_2_BELOW (0x1)
|
||||
#define PHY_VHT_CTRL_POS_3_BELOW (0x2)
|
||||
#define PHY_VHT_CTRL_POS_4_BELOW (0x3)
|
||||
#define PHY_VHT_CTRL_POS_1_ABOVE (0x4)
|
||||
#define PHY_VHT_CTRL_POS_2_ABOVE (0x5)
|
||||
#define PHY_VHT_CTRL_POS_3_ABOVE (0x6)
|
||||
#define PHY_VHT_CTRL_POS_4_ABOVE (0x7)
|
||||
|
||||
/*
|
||||
* @band: PHY_BAND_*
|
||||
* @channel: channel number
|
||||
* @width: PHY_[VHT|LEGACY]_CHANNEL_*
|
||||
* @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*
|
||||
*/
|
||||
struct iwl_fw_channel_info {
|
||||
u8 band;
|
||||
u8 channel;
|
||||
u8 width;
|
||||
u8 ctrl_pos;
|
||||
} __packed;
|
||||
|
||||
#define PHY_RX_CHAIN_DRIVER_FORCE_POS (0)
|
||||
#define PHY_RX_CHAIN_DRIVER_FORCE_MSK \
|
||||
(0x1 << PHY_RX_CHAIN_DRIVER_FORCE_POS)
|
||||
#define PHY_RX_CHAIN_VALID_POS (1)
|
||||
#define PHY_RX_CHAIN_VALID_MSK \
|
||||
(0x7 << PHY_RX_CHAIN_VALID_POS)
|
||||
#define PHY_RX_CHAIN_FORCE_SEL_POS (4)
|
||||
#define PHY_RX_CHAIN_FORCE_SEL_MSK \
|
||||
(0x7 << PHY_RX_CHAIN_FORCE_SEL_POS)
|
||||
#define PHY_RX_CHAIN_FORCE_MIMO_SEL_POS (7)
|
||||
#define PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK \
|
||||
(0x7 << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS)
|
||||
#define PHY_RX_CHAIN_CNT_POS (10)
|
||||
#define PHY_RX_CHAIN_CNT_MSK \
|
||||
(0x3 << PHY_RX_CHAIN_CNT_POS)
|
||||
#define PHY_RX_CHAIN_MIMO_CNT_POS (12)
|
||||
#define PHY_RX_CHAIN_MIMO_CNT_MSK \
|
||||
(0x3 << PHY_RX_CHAIN_MIMO_CNT_POS)
|
||||
#define PHY_RX_CHAIN_MIMO_FORCE_POS (14)
|
||||
#define PHY_RX_CHAIN_MIMO_FORCE_MSK \
|
||||
(0x1 << PHY_RX_CHAIN_MIMO_FORCE_POS)
|
||||
|
||||
/* TODO: fix the value, make it depend on firmware at runtime? */
|
||||
#define NUM_PHY_CTX 3
|
||||
|
||||
/* TODO: complete missing documentation */
|
||||
/**
|
||||
* struct iwl_phy_context_cmd - config of the PHY context
|
||||
* ( PHY_CONTEXT_CMD = 0x8 )
|
||||
* @id_and_color: ID and color of the relevant Binding
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @apply_time: 0 means immediate apply and context switch.
|
||||
* other value means apply new params after X usecs
|
||||
* @tx_param_color: ???
|
||||
* @channel_info:
|
||||
* @txchain_info: ???
|
||||
* @rxchain_info: ???
|
||||
* @acquisition_data: ???
|
||||
* @dsp_cfg_flags: set to 0
|
||||
*/
|
||||
struct iwl_phy_context_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* PHY_CONTEXT_DATA_API_S_VER_1 */
|
||||
__le32 apply_time;
|
||||
__le32 tx_param_color;
|
||||
struct iwl_fw_channel_info ci;
|
||||
__le32 txchain_info;
|
||||
__le32 rxchain_info;
|
||||
__le32 acquisition_data;
|
||||
__le32 dsp_cfg_flags;
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
|
||||
|
||||
#define IWL_RX_INFO_PHY_CNT 8
|
||||
#define IWL_RX_INFO_AGC_IDX 1
|
||||
#define IWL_RX_INFO_RSSI_AB_IDX 2
|
||||
#define IWL_RX_INFO_RSSI_C_IDX 3
|
||||
#define IWL_OFDM_AGC_DB_MSK 0xfe00
|
||||
#define IWL_OFDM_AGC_DB_POS 9
|
||||
#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
|
||||
#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
|
||||
#define IWL_OFDM_RSSI_A_POS 0
|
||||
#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
|
||||
#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
|
||||
#define IWL_OFDM_RSSI_B_POS 16
|
||||
#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
|
||||
#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
|
||||
#define IWL_OFDM_RSSI_C_POS 0
|
||||
|
||||
/**
|
||||
* struct iwl_rx_phy_info - phy info
|
||||
* (REPLY_RX_PHY_CMD = 0xc0)
|
||||
* @non_cfg_phy_cnt: non configurable DSP phy data byte count
|
||||
* @cfg_phy_cnt: configurable DSP phy data byte count
|
||||
* @stat_id: configurable DSP phy data set ID
|
||||
* @reserved1:
|
||||
* @system_timestamp: GP2 at on air rise
|
||||
* @timestamp: TSF at on air rise
|
||||
* @beacon_time_stamp: beacon at on-air rise
|
||||
* @phy_flags: general phy flags: band, modulation, ...
|
||||
* @channel: channel number
|
||||
* @non_cfg_phy_buf: for various implementations of non_cfg_phy
|
||||
* @rate_n_flags: RATE_MCS_*
|
||||
* @byte_count: frame's byte-count
|
||||
* @frame_time: frame's time on the air, based on byte count and frame rate
|
||||
* calculation
|
||||
*
|
||||
* Before each Rx, the device sends this data. It contains PHY information
|
||||
* about the reception of the packet.
|
||||
*/
|
||||
struct iwl_rx_phy_info {
|
||||
u8 non_cfg_phy_cnt;
|
||||
u8 cfg_phy_cnt;
|
||||
u8 stat_id;
|
||||
u8 reserved1;
|
||||
__le32 system_timestamp;
|
||||
__le64 timestamp;
|
||||
__le32 beacon_time_stamp;
|
||||
__le16 phy_flags;
|
||||
__le16 channel;
|
||||
__le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
|
||||
__le32 rate_n_flags;
|
||||
__le32 byte_count;
|
||||
__le16 reserved2;
|
||||
__le16 frame_time;
|
||||
} __packed;
|
||||
|
||||
struct iwl_rx_mpdu_res_start {
|
||||
__le16 byte_count;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
|
||||
* @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band
|
||||
* @RX_RES_PHY_FLAGS_MOD_CCK:
|
||||
* @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short
|
||||
* @RX_RES_PHY_FLAGS_NARROW_BAND:
|
||||
* @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received
|
||||
* @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU
|
||||
* @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame
|
||||
* @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble
|
||||
* @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame
|
||||
*/
|
||||
enum iwl_rx_phy_flags {
|
||||
RX_RES_PHY_FLAGS_BAND_24 = BIT(0),
|
||||
RX_RES_PHY_FLAGS_MOD_CCK = BIT(1),
|
||||
RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2),
|
||||
RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3),
|
||||
RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4),
|
||||
RX_RES_PHY_FLAGS_ANTENNA_POS = 4,
|
||||
RX_RES_PHY_FLAGS_AGG = BIT(7),
|
||||
RX_RES_PHY_FLAGS_OFDM_HT = BIT(8),
|
||||
RX_RES_PHY_FLAGS_OFDM_GF = BIT(9),
|
||||
RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_rx_status - written by fw for each Rx packet
|
||||
* @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine
|
||||
* @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
|
||||
* @RX_MPDU_RES_STATUS_SRC_STA_FOUND:
|
||||
* @RX_MPDU_RES_STATUS_KEY_VALID:
|
||||
* @RX_MPDU_RES_STATUS_KEY_PARAM_OK:
|
||||
* @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
|
||||
* @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
|
||||
* in the driver.
|
||||
* @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine
|
||||
* @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or
|
||||
* alg = CCM only. Checks replay attack for 11w frames. Relevant only if
|
||||
* %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.
|
||||
* @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted
|
||||
* @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
|
||||
* @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
|
||||
* @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP
|
||||
* @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC
|
||||
* @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
|
||||
* @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
|
||||
* @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
|
||||
* @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:
|
||||
* @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:
|
||||
* @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:
|
||||
* @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
|
||||
* @RX_MPDU_RES_STATUS_HASH_INDEX_MSK:
|
||||
* @RX_MPDU_RES_STATUS_STA_ID_MSK:
|
||||
* @RX_MPDU_RES_STATUS_RRF_KILL:
|
||||
* @RX_MPDU_RES_STATUS_FILTERING_MSK:
|
||||
* @RX_MPDU_RES_STATUS2_FILTERING_MSK:
|
||||
*/
|
||||
enum iwl_mvm_rx_status {
|
||||
RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
|
||||
RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1),
|
||||
RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2),
|
||||
RX_MPDU_RES_STATUS_KEY_VALID = BIT(3),
|
||||
RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4),
|
||||
RX_MPDU_RES_STATUS_ICV_OK = BIT(5),
|
||||
RX_MPDU_RES_STATUS_MIC_OK = BIT(6),
|
||||
RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
|
||||
RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7),
|
||||
RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8),
|
||||
RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8),
|
||||
RX_MPDU_RES_STATUS_DEC_DONE = BIT(11),
|
||||
RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12),
|
||||
RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13),
|
||||
RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14),
|
||||
RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15),
|
||||
RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
|
||||
RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000),
|
||||
RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
|
||||
RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
|
||||
RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_radio_version_notif - information on the radio version
|
||||
* ( RADIO_VERSION_NOTIFICATION = 0x68 )
|
||||
* @radio_flavor:
|
||||
* @radio_step:
|
||||
* @radio_dash:
|
||||
*/
|
||||
struct iwl_radio_version_notif {
|
||||
__le32 radio_flavor;
|
||||
__le32 radio_step;
|
||||
__le32 radio_dash;
|
||||
} __packed; /* RADIO_VERSION_NOTOFICATION_S_VER_1 */
|
||||
|
||||
enum iwl_card_state_flags {
|
||||
CARD_ENABLED = 0x00,
|
||||
HW_CARD_DISABLED = 0x01,
|
||||
SW_CARD_DISABLED = 0x02,
|
||||
CT_KILL_CARD_DISABLED = 0x04,
|
||||
HALT_CARD_DISABLED = 0x08,
|
||||
CARD_DISABLED_MSK = 0x0f,
|
||||
CARD_IS_RX_ON = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_radio_version_notif - information on the radio version
|
||||
* ( CARD_STATE_NOTIFICATION = 0xa1 )
|
||||
* @flags: %iwl_card_state_flags
|
||||
*/
|
||||
struct iwl_card_state_notif {
|
||||
__le32 flags;
|
||||
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_set_calib_default_cmd - set default value for calibration.
|
||||
* ( SET_CALIB_DEFAULT_CMD = 0x8e )
|
||||
* @calib_index: the calibration to set value for
|
||||
* @length: of data
|
||||
* @data: the value to set for the calibration result
|
||||
*/
|
||||
struct iwl_set_calib_default_cmd {
|
||||
__le16 calib_index;
|
||||
__le16 length;
|
||||
u8 data[0];
|
||||
} __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */
|
||||
|
||||
#endif /* __fw_api_h__ */
|
|
@ -0,0 +1,644 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-fw.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
|
||||
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
#include "mvm.h"
|
||||
#include "iwl-phy-db.h"
|
||||
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT HZ
|
||||
#define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
|
||||
|
||||
#define UCODE_VALID_OK cpu_to_le32(0x1)
|
||||
|
||||
/* Default calibration values for WkP - set to INIT image w/o running */
|
||||
static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
|
||||
0x00, 0x18, 0x00 };
|
||||
static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7f, 0x7f };
|
||||
static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
|
||||
0x00 };
|
||||
static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
|
||||
static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
|
||||
|
||||
struct iwl_calib_default_data {
|
||||
u16 size;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
|
||||
|
||||
static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
|
||||
[5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
|
||||
[6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
|
||||
[7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
|
||||
[8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
|
||||
[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
|
||||
[10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
|
||||
[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
|
||||
};
|
||||
|
||||
struct iwl_mvm_alive_data {
|
||||
bool valid;
|
||||
u32 scd_base_addr;
|
||||
};
|
||||
|
||||
static inline const struct fw_img *
|
||||
iwl_get_ucode_image(struct iwl_mvm *mvm, enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
if (ucode_type >= IWL_UCODE_TYPE_MAX)
|
||||
return NULL;
|
||||
|
||||
return &mvm->fw->img[ucode_type];
|
||||
}
|
||||
|
||||
static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
|
||||
{
|
||||
struct iwl_tx_ant_cfg_cmd tx_ant_cmd = {
|
||||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
};
|
||||
|
||||
IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
|
||||
sizeof(tx_ant_cmd), &tx_ant_cmd);
|
||||
}
|
||||
|
||||
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(notif_wait, struct iwl_mvm, notif_wait);
|
||||
struct iwl_mvm_alive_data *alive_data = data;
|
||||
struct mvm_alive_resp *palive;
|
||||
|
||||
palive = (void *)pkt->data;
|
||||
|
||||
mvm->error_event_table = le32_to_cpu(palive->error_event_table_ptr);
|
||||
mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
|
||||
|
||||
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
|
||||
IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
|
||||
le16_to_cpu(palive->status), palive->ver_type,
|
||||
palive->ver_subtype);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_phy_db *phy_db = data;
|
||||
|
||||
if (pkt->hdr.cmd != CALIB_RES_NOTIF_PHY_DB) {
|
||||
WARN_ON(pkt->hdr.cmd != INIT_COMPLETE_NOTIF);
|
||||
return true;
|
||||
}
|
||||
|
||||
WARN_ON(iwl_phy_db_set_section(phy_db, pkt, GFP_ATOMIC));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
struct iwl_notification_wait alive_wait;
|
||||
struct iwl_mvm_alive_data alive_data;
|
||||
const struct fw_img *fw;
|
||||
int ret, i;
|
||||
enum iwl_ucode_type old_type = mvm->cur_ucode;
|
||||
static const u8 alive_cmd[] = { MVM_ALIVE };
|
||||
|
||||
mvm->cur_ucode = ucode_type;
|
||||
fw = iwl_get_ucode_image(mvm, ucode_type);
|
||||
|
||||
mvm->ucode_loaded = false;
|
||||
|
||||
if (!fw)
|
||||
return -EINVAL;
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
|
||||
alive_cmd, ARRAY_SIZE(alive_cmd),
|
||||
iwl_alive_fn, &alive_data);
|
||||
|
||||
ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
|
||||
if (ret) {
|
||||
mvm->cur_ucode = old_type;
|
||||
iwl_remove_notification(&mvm->notif_wait, &alive_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some things may run in the background now, but we
|
||||
* just wait for the ALIVE notification here.
|
||||
*/
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
|
||||
MVM_UCODE_ALIVE_TIMEOUT);
|
||||
if (ret) {
|
||||
mvm->cur_ucode = old_type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!alive_data.valid) {
|
||||
IWL_ERR(mvm, "Loaded ucode is not valid!\n");
|
||||
mvm->cur_ucode = old_type;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
|
||||
|
||||
/*
|
||||
* Note: all the queues are enabled as part of the interface
|
||||
* initialization, but in firmware restart scenarios they
|
||||
* could be stopped, so wake them up. In firmware restart,
|
||||
* mac80211 will have the queues stopped as well until the
|
||||
* reconfiguration completes. During normal startup, they
|
||||
* will be empty.
|
||||
*/
|
||||
|
||||
for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
|
||||
if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE)
|
||||
mvm->queue_to_mac80211[i] = i;
|
||||
else
|
||||
mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
|
||||
atomic_set(&mvm->queue_stop_count[i], 0);
|
||||
}
|
||||
|
||||
mvm->transport_queue_stop = 0;
|
||||
|
||||
mvm->ucode_loaded = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define IWL_HW_REV_ID_RAINBOW 0x2
|
||||
#define IWL_PROJ_TYPE_LHP 0x5
|
||||
|
||||
static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_nvm_data *data = mvm->nvm_data;
|
||||
/* Temp calls to static definitions, will be changed to CSR calls */
|
||||
u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
|
||||
u8 project_type = IWL_PROJ_TYPE_LHP;
|
||||
|
||||
return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
|
||||
(hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
|
||||
(data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
|
||||
}
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_phy_cfg_cmd phy_cfg_cmd;
|
||||
enum iwl_ucode_type ucode_type = mvm->cur_ucode;
|
||||
|
||||
/* Set parameters */
|
||||
phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
|
||||
phy_cfg_cmd.calib_control.event_trigger =
|
||||
mvm->fw->default_calib[ucode_type].event_trigger;
|
||||
phy_cfg_cmd.calib_control.flow_trigger =
|
||||
mvm->fw->default_calib[ucode_type].flow_trigger;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
|
||||
phy_cfg_cmd.phy_cfg);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC,
|
||||
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
|
||||
}
|
||||
|
||||
/* Starting with the new PHY DB implementation - New calibs are enabled */
|
||||
/* Value - 0x405e7 */
|
||||
#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_BB_FILTER_IDX |\
|
||||
IWL_CALIB_CFG_LO_LEAKAGE_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_RX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_AGC_IDX)
|
||||
|
||||
#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0
|
||||
|
||||
/* Value 0x41567 */
|
||||
#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_BB_FILTER_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_RX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_SENSITIVITY_IDX |\
|
||||
IWL_CALIB_CFG_AGC_IDX)
|
||||
|
||||
#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_TX_PWR_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_SENSITIVITY_IDX)
|
||||
|
||||
/*
|
||||
* Sets the calibrations trigger values that will be sent to the FW for runtime
|
||||
* and init calibrations.
|
||||
* The ones given in the FW TLV are not correct.
|
||||
*/
|
||||
static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_tlv_calib_ctrl default_calib;
|
||||
|
||||
/*
|
||||
* WkP FW TLV calib bits are wrong, overwrite them.
|
||||
* This defines the dynamic calibrations which are implemented in the
|
||||
* uCode both for init(flow) calculation and event driven calibs.
|
||||
*/
|
||||
|
||||
/* Init Image */
|
||||
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
|
||||
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
|
||||
|
||||
if (default_calib.event_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the event calib for INIT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
|
||||
default_calib.event_trigger);
|
||||
if (default_calib.flow_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
|
||||
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
|
||||
IWL_ERR(mvm,
|
||||
"Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
|
||||
default_calib.event_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
/* Run time image */
|
||||
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
|
||||
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
|
||||
|
||||
if (default_calib.event_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the event calib for RT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
|
||||
default_calib.event_trigger);
|
||||
if (default_calib.flow_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the flow calib for RT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
|
||||
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
|
||||
IWL_ERR(mvm,
|
||||
"Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
|
||||
default_calib.event_trigger,
|
||||
default_calib.flow_trigger);
|
||||
}
|
||||
|
||||
static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_raw[16]; /* holds the variable size commands */
|
||||
struct iwl_set_calib_default_cmd *cmd =
|
||||
(struct iwl_set_calib_default_cmd *)cmd_raw;
|
||||
int ret, i;
|
||||
|
||||
/* Setting default values for calibrations we don't run */
|
||||
for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
|
||||
u16 cmd_len;
|
||||
|
||||
if (wkp_calib_default_data[i].size == 0)
|
||||
continue;
|
||||
|
||||
memset(cmd_raw, 0, sizeof(cmd_raw));
|
||||
cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
|
||||
cmd->calib_index = cpu_to_le16(i);
|
||||
cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
|
||||
if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
|
||||
"Need to enlarge cmd_raw to %d\n", cmd_len))
|
||||
break;
|
||||
memcpy(cmd->data, wkp_calib_default_data[i].data,
|
||||
wkp_calib_default_data[i].size);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
|
||||
sizeof(*cmd) +
|
||||
wkp_calib_default_data[i].size,
|
||||
cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
{
|
||||
struct iwl_notification_wait calib_wait;
|
||||
static const u8 init_complete[] = {
|
||||
INIT_COMPLETE_NOTIF,
|
||||
CALIB_RES_NOTIF_PHY_DB
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (mvm->init_ucode_run)
|
||||
return 0;
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
&calib_wait,
|
||||
init_complete,
|
||||
ARRAY_SIZE(init_complete),
|
||||
iwl_wait_phy_db_entry,
|
||||
mvm->phy_db);
|
||||
|
||||
/* Will also start the device */
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_INIT);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start INIT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (read_nvm) {
|
||||
/* Read nvm */
|
||||
ret = iwl_nvm_init(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
|
||||
WARN_ON(ret);
|
||||
|
||||
/* Override the calibrations from TLV and the const of fw */
|
||||
iwl_set_default_calib_trigger(mvm);
|
||||
|
||||
/* WkP doesn't have all calibrations, need to set default values */
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
ret = iwl_set_default_calibrations(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send phy configurations command to init uCode
|
||||
* to start the 16.0 uCode init image internal calibrations.
|
||||
*/
|
||||
ret = iwl_send_phy_cfg_cmd(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run INIT calibrations: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some things may run in the background now, but we
|
||||
* just wait for the calibration complete notification.
|
||||
*/
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
|
||||
MVM_UCODE_CALIB_TIMEOUT);
|
||||
if (!ret)
|
||||
mvm->init_ucode_run = true;
|
||||
goto out;
|
||||
|
||||
error:
|
||||
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
|
||||
out:
|
||||
if (!iwlmvm_mod_params.init_dbg) {
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
} else if (!mvm->nvm_data) {
|
||||
/* we want to debug INIT and we have no NVM - fake */
|
||||
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
|
||||
sizeof(struct ieee80211_channel) +
|
||||
sizeof(struct ieee80211_rate),
|
||||
GFP_KERNEL);
|
||||
if (!mvm->nvm_data)
|
||||
return -ENOMEM;
|
||||
mvm->nvm_data->valid_rx_ant = 1;
|
||||
mvm->nvm_data->valid_tx_ant = 1;
|
||||
mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
|
||||
mvm->nvm_data->bands[0].n_channels = 1;
|
||||
mvm->nvm_data->bands[0].n_bitrates = 1;
|
||||
mvm->nvm_data->bands[0].bitrates =
|
||||
(void *)mvm->nvm_data->channels + 1;
|
||||
mvm->nvm_data->bands[0].bitrates->hw_value = 10;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
||||
|
||||
int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
ret = iwl_trans_start_hw(mvm->trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If we were in RFKILL during module loading, load init ucode now */
|
||||
if (!mvm->init_ucode_run) {
|
||||
ret = iwl_run_init_mvm_ucode(mvm, false);
|
||||
if (ret && !iwlmvm_mod_params.init_dbg) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Send phy db control command and then phy db calibration*/
|
||||
ret = iwl_send_phy_db_data(mvm->phy_db);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_send_phy_cfg_cmd(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* init the fw <-> mac80211 STA mapping */
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
|
||||
|
||||
/* Add auxiliary station for scanning */
|
||||
ret = iwl_mvm_add_aux_sta(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
|
||||
return 0;
|
||||
error:
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
ret = iwl_trans_start_hw(mvm->trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_WOWLAN);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start WoWLAN firmware: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Send phy db control command and then phy db calibration*/
|
||||
ret = iwl_send_phy_db_data(mvm->phy_db);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_send_phy_cfg_cmd(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* init the fw <-> mac80211 STA mapping */
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
|
||||
|
||||
/* Add auxiliary station for scanning */
|
||||
ret = iwl_mvm_add_aux_sta(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
|
||||
u32 flags = le32_to_cpu(card_state_notif->flags);
|
||||
|
||||
IWL_DEBUG_RF_KILL(mvm, "Card state received: HW:%s SW:%s CT:%s\n",
|
||||
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
|
||||
(flags & SW_CARD_DISABLED) ? "Kill" : "On",
|
||||
(flags & CT_KILL_CARD_DISABLED) ?
|
||||
"Reached" : "Not reached");
|
||||
|
||||
if (flags & CARD_DISABLED_MSK)
|
||||
iwl_write32(mvm->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_radio_version_notif *radio_version = (void *)pkt->data;
|
||||
|
||||
/* TODO: what to do with that? */
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"Radio version: flavor: 0x%08x, step 0x%08x, dash 0x%08x\n",
|
||||
le32_to_cpu(radio_version->radio_flavor),
|
||||
le32_to_cpu(radio_version->radio_step),
|
||||
le32_to_cpu(radio_version->radio_dash));
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/leds.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
|
||||
/* Set led register on */
|
||||
static void iwl_mvm_led_enable(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_write32(mvm->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON);
|
||||
}
|
||||
|
||||
/* Set led register off */
|
||||
static void iwl_mvm_led_disable(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_write32(mvm->trans, CSR_LED_REG, CSR_LED_REG_TURN_OFF);
|
||||
}
|
||||
|
||||
static void iwl_led_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(led_cdev, struct iwl_mvm, led);
|
||||
if (brightness > 0)
|
||||
iwl_mvm_led_enable(mvm);
|
||||
else
|
||||
iwl_mvm_led_disable(mvm);
|
||||
}
|
||||
|
||||
int iwl_mvm_leds_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
int mode = iwlwifi_mod_params.led_mode;
|
||||
int ret;
|
||||
|
||||
switch (mode) {
|
||||
case IWL_LED_DEFAULT:
|
||||
case IWL_LED_RF_STATE:
|
||||
mode = IWL_LED_RF_STATE;
|
||||
break;
|
||||
case IWL_LED_DISABLE:
|
||||
IWL_INFO(mvm, "Led disabled\n");
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
|
||||
wiphy_name(mvm->hw->wiphy));
|
||||
mvm->led.brightness_set = iwl_led_brightness_set;
|
||||
mvm->led.max_brightness = 1;
|
||||
|
||||
if (mode == IWL_LED_RF_STATE)
|
||||
mvm->led.default_trigger =
|
||||
ieee80211_get_radio_led_name(mvm->hw);
|
||||
|
||||
ret = led_classdev_register(mvm->trans->dev, &mvm->led);
|
||||
if (ret) {
|
||||
kfree(mvm->led.name);
|
||||
IWL_INFO(mvm, "Failed to enable led\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
|
||||
{
|
||||
if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE)
|
||||
return;
|
||||
|
||||
led_classdev_unregister(&mvm->led);
|
||||
kfree(mvm->led.name);
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче