提交 f5237f27 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
...@@ -47,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus); ...@@ -47,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus);
/* driver_chipcommon.c */ /* driver_chipcommon.c */
#ifdef CONFIG_BCMA_DRIVER_MIPS #ifdef CONFIG_BCMA_DRIVER_MIPS
void bcma_chipco_serial_init(struct bcma_drv_cc *cc); void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
extern struct platform_device bcma_pflash_dev;
#endif /* CONFIG_BCMA_DRIVER_MIPS */ #endif /* CONFIG_BCMA_DRIVER_MIPS */
/* driver_chipcommon_pmu.c */ /* driver_chipcommon_pmu.c */
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
* Licensed under the GNU/GPL. See COPYING for details. * Licensed under the GNU/GPL. See COPYING for details.
*/ */
#include "bcma_private.h"
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
#include "bcma_private.h"
struct platform_device bcma_nflash_dev = { struct platform_device bcma_nflash_dev = {
.name = "bcma_nflash", .name = "bcma_nflash",
.num_resources = 0, .num_resources = 0,
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
* Licensed under the GNU/GPL. See COPYING for details. * Licensed under the GNU/GPL. See COPYING for details.
*/ */
#include "bcma_private.h"
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
#include "bcma_private.h"
static struct resource bcma_sflash_resource = { static struct resource bcma_sflash_resource = {
.name = "bcma_sflash", .name = "bcma_sflash",
.start = BCMA_SOC_FLASH2, .start = BCMA_SOC_FLASH2,
......
...@@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) ...@@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); 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) int bcma_gpio_init(struct bcma_drv_cc *cc)
{ {
struct gpio_chip *chip = &cc->gpio; struct gpio_chip *chip = &cc->gpio;
...@@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) ...@@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->set = bcma_gpio_set_value; chip->set = bcma_gpio_set_value;
chip->direction_input = bcma_gpio_direction_input; chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output; chip->direction_output = bcma_gpio_direction_output;
chip->to_irq = bcma_gpio_to_irq;
chip->ngpio = 16; chip->ngpio = 16;
/* There is just one SoC in one device and its GPIO addresses should be /* 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 * deterministic to address them more easily. The other buses could get
......
...@@ -14,11 +14,33 @@ ...@@ -14,11 +14,33 @@
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/time.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 */ /* The 47162a0 hangs when reading MIPS DMP registers registers */
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) 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) ...@@ -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_bus *bus = mcore->core->bus;
struct bcma_drv_cc *cc = &bus->drv_cc; struct bcma_drv_cc *cc = &bus->drv_cc;
struct bcma_pflash *pflash = &cc->pflash;
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
case BCMA_CC_FLASHT_STSER: case BCMA_CC_FLASHT_STSER:
...@@ -220,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) ...@@ -220,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
break; break;
case BCMA_CC_FLASHT_PARA: case BCMA_CC_FLASHT_PARA:
bcma_debug(bus, "Found parallel flash\n"); bcma_debug(bus, "Found parallel flash\n");
cc->pflash.present = true; pflash->present = true;
cc->pflash.window = BCMA_SOC_FLASH2; pflash->window = BCMA_SOC_FLASH2;
cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; pflash->window_size = BCMA_SOC_FLASH2_SZ;
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
BCMA_CC_FLASH_CFG_DS) == 0) BCMA_CC_FLASH_CFG_DS) == 0)
cc->pflash.buswidth = 1; pflash->buswidth = 1;
else 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; break;
default: default:
bcma_err(bus, "Flash type not supported\n"); bcma_err(bus, "Flash type not supported\n");
......
...@@ -149,6 +149,14 @@ static int bcma_register_cores(struct bcma_bus *bus) ...@@ -149,6 +149,14 @@ static int bcma_register_cores(struct bcma_bus *bus)
dev_id++; 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 #ifdef CONFIG_BCMA_SFLASH
if (bus->drv_cc.sflash.present) { if (bus->drv_cc.sflash.present) {
err = platform_device_register(&bcma_sflash_dev); err = platform_device_register(&bcma_sflash_dev);
......
...@@ -58,6 +58,7 @@ config ATH9K_DEBUGFS ...@@ -58,6 +58,7 @@ config ATH9K_DEBUGFS
bool "Atheros ath9k debugging" bool "Atheros ath9k debugging"
depends on ATH9K depends on ATH9K
select MAC80211_DEBUGFS select MAC80211_DEBUGFS
select RELAY
---help--- ---help---
Say Y, if you need access to ath9k's statistics for Say Y, if you need access to ath9k's statistics for
interrupts, rate control, etc. interrupts, rate control, etc.
......
...@@ -319,6 +319,8 @@ struct ath_rx { ...@@ -319,6 +319,8 @@ struct ath_rx {
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
struct sk_buff *frag; struct sk_buff *frag;
u32 ampdu_ref;
}; };
int ath_startrecv(struct ath_softc *sc); int ath_startrecv(struct ath_softc *sc);
...@@ -754,6 +756,7 @@ struct ath_softc { ...@@ -754,6 +756,7 @@ struct ath_softc {
/* relay(fs) channel for spectral scan */ /* relay(fs) channel for spectral scan */
struct rchan *rfs_chan_spec_scan; struct rchan *rfs_chan_spec_scan;
enum spectral_mode spectral_mode; enum spectral_mode spectral_mode;
struct ath_spec_scan spec_config;
int scanning; int scanning;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -863,31 +866,31 @@ static inline u8 spectral_bitmap_weight(u8 *bins) ...@@ -863,31 +866,31 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
* interface. * interface.
*/ */
enum ath_fft_sample_type { enum ath_fft_sample_type {
ATH_FFT_SAMPLE_HT20 = 0, ATH_FFT_SAMPLE_HT20 = 1,
}; };
struct fft_sample_tlv { struct fft_sample_tlv {
u8 type; /* see ath_fft_sample */ u8 type; /* see ath_fft_sample */
u16 length; __be16 length;
/* type dependent data follows */ /* type dependent data follows */
} __packed; } __packed;
struct fft_sample_ht20 { struct fft_sample_ht20 {
struct fft_sample_tlv tlv; struct fft_sample_tlv tlv;
u8 __alignment; u8 max_exp;
u16 freq; __be16 freq;
s8 rssi; s8 rssi;
s8 noise; s8 noise;
u16 max_magnitude; __be16 max_magnitude;
u8 max_index; u8 max_index;
u8 bitmap_weight; u8 bitmap_weight;
u64 tsf; __be64 tsf;
u16 data[SPECTRAL_HT20_NUM_BINS]; u8 data[SPECTRAL_HT20_NUM_BINS];
} __packed; } __packed;
void ath9k_tasklet(unsigned long data); void ath9k_tasklet(unsigned long data);
......
...@@ -895,6 +895,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, ...@@ -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-Bytes-All", rx_bytes_all);
RXS_ERR("RX-Beacons", rx_beacons); RXS_ERR("RX-Beacons", rx_beacons);
RXS_ERR("RX-Frags", rx_frags); RXS_ERR("RX-Frags", rx_frags);
RXS_ERR("RX-Spectral", rx_spectral);
if (len > size) if (len > size)
len = size; len = size;
...@@ -1035,6 +1036,182 @@ static const struct file_operations fops_spec_scan_ctl = { ...@@ -1035,6 +1036,182 @@ static const struct file_operations fops_spec_scan_ctl = {
.llseek = default_llseek, .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, static struct dentry *create_buf_file_handler(const char *filename,
struct dentry *parent, struct dentry *parent,
umode_t mode, umode_t mode,
...@@ -1059,11 +1236,13 @@ static int remove_buf_file_handler(struct dentry *dentry) ...@@ -1059,11 +1236,13 @@ static int remove_buf_file_handler(struct dentry *dentry)
void ath_debug_send_fft_sample(struct ath_softc *sc, void ath_debug_send_fft_sample(struct ath_softc *sc,
struct fft_sample_tlv *fft_sample_tlv) struct fft_sample_tlv *fft_sample_tlv)
{ {
int length;
if (!sc->rfs_chan_spec_scan) if (!sc->rfs_chan_spec_scan)
return; return;
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length = __be16_to_cpu(fft_sample_tlv->length) +
fft_sample_tlv->length + sizeof(*fft_sample_tlv)); sizeof(*fft_sample_tlv);
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
} }
static struct rchan_callbacks rfs_spec_scan_cb = { static struct rchan_callbacks rfs_spec_scan_cb = {
...@@ -1893,6 +2072,16 @@ int ath9k_init_debug(struct ath_hw *ah) ...@@ -1893,6 +2072,16 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, sc->debug.debugfs_phy, sc,
&fops_spec_scan_ctl); &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 #ifdef CONFIG_ATH9K_MAC_DEBUG
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
......
...@@ -219,6 +219,7 @@ struct ath_tx_stats { ...@@ -219,6 +219,7 @@ struct ath_tx_stats {
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received. * @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
* @rx_beacons: No. of beacons received. * @rx_beacons: No. of beacons received.
* @rx_frags: No. of rx-fragements received. * @rx_frags: No. of rx-fragements received.
* @rx_spectral: No of spectral packets received.
*/ */
struct ath_rx_stats { struct ath_rx_stats {
u32 rx_pkts_all; u32 rx_pkts_all;
...@@ -237,6 +238,7 @@ struct ath_rx_stats { ...@@ -237,6 +238,7 @@ struct ath_rx_stats {
u32 rx_too_many_frags_err; u32 rx_too_many_frags_err;
u32 rx_beacons; u32 rx_beacons;
u32 rx_frags; u32 rx_frags;
u32 rx_spectral;
}; };
struct ath_stats { struct ath_stats {
......
...@@ -497,6 +497,13 @@ static void ath9k_init_misc(struct ath_softc *sc) ...@@ -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) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; 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, static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
...@@ -915,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ...@@ -915,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
ath9k_eeprom_release(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); relay_close(sc->rfs_chan_spec_scan);
sc->rfs_chan_spec_scan = NULL; sc->rfs_chan_spec_scan = NULL;
} }
......
...@@ -605,13 +605,13 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, ...@@ -605,13 +605,13 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
* reported, then decryption and MIC errors are irrelevant, * reported, then decryption and MIC errors are irrelevant,
* the frame is going to be dropped either way * the frame is going to be dropped either way
*/ */
if (ads.ds_rxstatus8 & AR_CRCErr) if (ads.ds_rxstatus8 & AR_PHYErr) {
rs->rs_status |= ATH9K_RXERR_CRC;
else if (ads.ds_rxstatus8 & AR_PHYErr) {
rs->rs_status |= ATH9K_RXERR_PHY; rs->rs_status |= ATH9K_RXERR_PHY;
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
rs->rs_phyerr = phyerr; 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; rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr) else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC; rs->rs_status |= ATH9K_RXERR_MIC;
......
...@@ -1099,45 +1099,34 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw, ...@@ -1099,45 +1099,34 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_spec_scan param;
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
ath_err(common, "spectrum analyzer not implemented on this hardware\n"); ath_err(common, "spectrum analyzer not implemented on this hardware\n");
return -1; 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) { switch (spectral_mode) {
case SPECTRAL_DISABLED: case SPECTRAL_DISABLED:
param.enabled = 0; sc->spec_config.enabled = 0;
break; break;
case SPECTRAL_BACKGROUND: case SPECTRAL_BACKGROUND:
/* send endless samples. /* send endless samples.
* TODO: is this really useful for "background"? * TODO: is this really useful for "background"?
*/ */
param.endless = 1; sc->spec_config.endless = 1;
sc->spec_config.enabled = 1;
break; break;
case SPECTRAL_CHANSCAN: case SPECTRAL_CHANSCAN:
break;
case SPECTRAL_MANUAL: case SPECTRAL_MANUAL:
sc->spec_config.endless = 0;
sc->spec_config.enabled = 1;
break; break;
default: default:
return -1; return -1;
} }
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ath9k_hw_ops(ah)->spectral_scan_config(ah, &param); ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
sc->spectral_mode = spectral_mode; sc->spectral_mode = spectral_mode;
......
...@@ -474,8 +474,6 @@ void ath_mci_cleanup(struct ath_softc *sc) ...@@ -474,8 +474,6 @@ void ath_mci_cleanup(struct ath_softc *sc)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = 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); ar9003_mci_cleanup(ah);
......
...@@ -1016,18 +1016,20 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, ...@@ -1016,18 +1016,20 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
rxs->flag &= ~RX_FLAG_DECRYPTED; rxs->flag &= ~RX_FLAG_DECRYPTED;
} }
#ifdef CONFIG_ATH9K_DEBUGFS
static s8 fix_rssi_inv_only(u8 rssi_val) static s8 fix_rssi_inv_only(u8 rssi_val)
{ {
if (rssi_val == 128) if (rssi_val == 128)
rssi_val = 0; rssi_val = 0;
return (s8) rssi_val; return (s8) rssi_val;
} }
#endif
/* returns 1 if this was a spectral frame, even if not handled. */
static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf) struct ath_rx_status *rs, u64 tsf)
{ {
#ifdef CONFIG_ATH_DEBUG #ifdef CONFIG_ATH9K_DEBUGFS
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
u8 bins[SPECTRAL_HT20_NUM_BINS]; u8 bins[SPECTRAL_HT20_NUM_BINS];
u8 *vdata = (u8 *)hdr; u8 *vdata = (u8 *)hdr;
...@@ -1035,7 +1037,8 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *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_radar_info *radar_info;
struct ath_ht20_mag_info *mag_info; struct ath_ht20_mag_info *mag_info;
int len = rs->rs_datalen; 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 /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT * 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, ...@@ -1044,7 +1047,14 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) 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. /* Variation in the data length is possible and will be fixed later.
* Note that we only support HT20 for now. * 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, ...@@ -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) || if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
(len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1)) (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
return; return 1;
/* 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;
fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; 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.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
fft_sample.noise = ah->noise; fft_sample.noise = ah->noise;
...@@ -1093,7 +1097,7 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, ...@@ -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); memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
break; break;
default: default:
return; return 1;
} }
/* DC value (value in the middle) is the blind spot of the spectral /* 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, ...@@ -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 data is at the end of the frame, in front of radar_info */
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
/* Apply exponent and grab further auxiliary information. */ /* copy raw bins without scaling them */
for (i = 0; i < SPECTRAL_HT20_NUM_BINS; i++) memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
fft_sample.data[i] = bins[i] << mag_info->max_exp; 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.max_index = spectral_max_index(mag_info->all_bins);
fft_sample.bitmap_weight = spectral_bitmap_weight(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); ath_debug_send_fft_sample(sc, &fft_sample.tlv);
return 1;
#else
return 0;
#endif #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) int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{ {
struct ath_buf *bf; struct ath_buf *bf;
...@@ -1202,8 +1228,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1202,8 +1228,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
rxs->mactime += 0x100000000ULL; rxs->mactime += 0x100000000ULL;
if ((rs.rs_status & ATH9K_RXERR_PHY)) if (rs.rs_status & ATH9K_RXERR_PHY) {
ath_process_fft(sc, hdr, &rs, rxs->mactime); 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, retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
rxs, &decrypt_error); rxs, &decrypt_error);
...@@ -1320,6 +1350,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -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) if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs); ath_ant_comb_scan(sc, &rs);
ath9k_apply_ampdu_details(sc, &rs, rxs);
ieee80211_rx(hw, skb); ieee80211_rx(hw, skb);
requeue_drop_frag: requeue_drop_frag:
......
...@@ -204,7 +204,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, ...@@ -204,7 +204,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
break; break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/* FW don't support scan after connection attempt */ /* FW don't support scan after connection attempt */
...@@ -228,8 +227,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, ...@@ -228,8 +227,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
} }
/* 0-based channel indexes */ /* 0-based channel indexes */
cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, wil_dbg_misc(wil, "Scan for ch %d : %d MHz\n", ch,
request->channels[i]->center_freq); request->channels[i]->center_freq);
} }
return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + 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, ...@@ -425,8 +424,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
return -EINVAL; return -EINVAL;
} }
wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
channel->center_freq, info->privacy ? "secure" : "open"); channel->center_freq, info->privacy ? "secure" : "open");
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
info->ssid, info->ssid_len); info->ssid, info->ssid_len);
......
...@@ -38,7 +38,9 @@ ...@@ -38,7 +38,9 @@
#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE #define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) 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 | \ #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
BIT_DMA_PSEUDO_CAUSE_TX | \ BIT_DMA_PSEUDO_CAUSE_TX | \
...@@ -50,7 +52,6 @@ ...@@ -50,7 +52,6 @@
static inline void wil_icr_clear(u32 x, void __iomem *addr) static inline void wil_icr_clear(u32 x, void __iomem *addr)
{ {
} }
#else /* defined(CONFIG_WIL6210_ISR_COR) */ #else /* defined(CONFIG_WIL6210_ISR_COR) */
/* configure to Write-1-to-Clear mode */ /* configure to Write-1-to-Clear mode */
...@@ -94,7 +95,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil) ...@@ -94,7 +95,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
static void wil6210_mask_irq_pseudo(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 + iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
...@@ -125,7 +126,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) ...@@ -125,7 +126,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
static void wil6210_unmask_irq_pseudo(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); set_bit(wil_status_irqen, &wil->status);
...@@ -135,7 +136,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) ...@@ -135,7 +136,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
void wil6210_disable_irq(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_tx(wil);
wil6210_mask_irq_rx(wil); wil6210_mask_irq_rx(wil);
...@@ -145,7 +146,7 @@ void wil6210_disable_irq(struct wil6210_priv *wil) ...@@ -145,7 +146,7 @@ void wil6210_disable_irq(struct wil6210_priv *wil)
void wil6210_enable_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) + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
offsetof(struct RGF_ICR, ICC)); offsetof(struct RGF_ICR, ICC));
...@@ -167,7 +168,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) ...@@ -167,7 +168,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
HOSTADDR(RGF_DMA_EP_RX_ICR) + HOSTADDR(RGF_DMA_EP_RX_ICR) +
offsetof(struct RGF_ICR, 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) { if (!isr) {
wil_err(wil, "spurious IRQ: RX\n"); wil_err(wil, "spurious IRQ: RX\n");
...@@ -177,7 +178,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) ...@@ -177,7 +178,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
wil6210_mask_irq_rx(wil); wil6210_mask_irq_rx(wil);
if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { 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; isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
wil_rx_handle(wil); wil_rx_handle(wil);
} }
...@@ -197,7 +198,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) ...@@ -197,7 +198,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
HOSTADDR(RGF_DMA_EP_TX_ICR) + HOSTADDR(RGF_DMA_EP_TX_ICR) +
offsetof(struct RGF_ICR, 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) { if (!isr) {
wil_err(wil, "spurious IRQ: TX\n"); wil_err(wil, "spurious IRQ: TX\n");
...@@ -208,13 +209,13 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) ...@@ -208,13 +209,13 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
uint i; uint i;
wil_dbg_IRQ(wil, "TX done\n"); wil_dbg_irq(wil, "TX done\n");
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
for (i = 0; i < 24; i++) { for (i = 0; i < 24; i++) {
u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i);
if (isr & mask) { if (isr & mask) {
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); wil_tx_complete(wil, i);
} }
} }
...@@ -228,6 +229,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) ...@@ -228,6 +229,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
return IRQ_HANDLED; 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) static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
{ {
struct wil6210_priv *wil = cookie; struct wil6210_priv *wil = cookie;
...@@ -235,7 +247,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) ...@@ -235,7 +247,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
HOSTADDR(RGF_DMA_EP_MISC_ICR) + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
offsetof(struct RGF_ICR, 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) { if (!isr) {
wil_err(wil, "spurious IRQ: MISC\n"); wil_err(wil, "spurious IRQ: MISC\n");
...@@ -244,8 +256,15 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) ...@@ -244,8 +256,15 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
wil6210_mask_irq_misc(wil); 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) { 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 * Actual FW ready indicated by the
* WMI_FW_READY_EVENTID * WMI_FW_READY_EVENTID
...@@ -268,10 +287,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) ...@@ -268,10 +287,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
struct wil6210_priv *wil = cookie; struct wil6210_priv *wil = cookie;
u32 isr = wil->isr_misc; 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) { if (isr & ISR_MISC_MBOX_EVT) {
wil_dbg_IRQ(wil, "MBOX event\n"); wil_dbg_irq(wil, "MBOX event\n");
wmi_recv_cmd(wil); wmi_recv_cmd(wil);
isr &= ~ISR_MISC_MBOX_EVT; isr &= ~ISR_MISC_MBOX_EVT;
} }
...@@ -293,7 +312,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie) ...@@ -293,7 +312,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
{ {
struct wil6210_priv *wil = cookie; struct wil6210_priv *wil = cookie;
wil_dbg_IRQ(wil, "Thread IRQ\n"); wil_dbg_irq(wil, "Thread IRQ\n");
/* Discover real IRQ cause */ /* Discover real IRQ cause */
if (wil->isr_misc) if (wil->isr_misc)
wil6210_irq_misc_thread(irq, cookie); wil6210_irq_misc_thread(irq, cookie);
...@@ -370,6 +389,8 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie) ...@@ -370,6 +389,8 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
if (wil6210_debug_irq_mask(wil, pseudo_cause)) if (wil6210_debug_irq_mask(wil, pseudo_cause))
return IRQ_NONE; return IRQ_NONE;
wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause);
wil6210_mask_irq_pseudo(wil); wil6210_mask_irq_pseudo(wil);
/* Discover real IRQ cause /* Discover real IRQ cause
...@@ -401,8 +422,6 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie) ...@@ -401,8 +422,6 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
if (rc != IRQ_WAKE_THREAD) if (rc != IRQ_WAKE_THREAD)
wil6210_unmask_irq_pseudo(wil); wil6210_unmask_irq_pseudo(wil);
wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause);
return rc; return rc;
} }
......
...@@ -64,7 +64,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) ...@@ -64,7 +64,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
struct net_device *ndev = wil_to_ndev(wil); struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev; struct wireless_dev *wdev = wil->wdev;
wil_dbg(wil, "%s()\n", __func__); wil_dbg_misc(wil, "%s()\n", __func__);
wil_link_off(wil); wil_link_off(wil);
clear_bit(wil_status_fwconnected, &wil->status); clear_bit(wil_status_fwconnected, &wil->status);
...@@ -80,11 +80,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) ...@@ -80,11 +80,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
GFP_KERNEL); GFP_KERNEL);
break; break;
default: default:
; break;
} }
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++)
wil_vring_fini_tx(wil, i); wil_vring_fini_tx(wil, i);
clear_bit(wil_status_dontscan, &wil->status);
} }
static void wil_disconnect_worker(struct work_struct *work) static void wil_disconnect_worker(struct work_struct *work)
...@@ -99,7 +101,7 @@ static void wil_connect_timer_fn(ulong x) ...@@ -99,7 +101,7 @@ static void wil_connect_timer_fn(ulong x)
{ {
struct wil6210_priv *wil = (void *)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 /* reschedule to thread context - disconnect won't
* run from atomic context * run from atomic context
...@@ -107,9 +109,18 @@ static void wil_connect_timer_fn(ulong x) ...@@ -107,9 +109,18 @@ static void wil_connect_timer_fn(ulong x)
schedule_work(&wil->disconnect_worker); 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) 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->mutex);
mutex_init(&wil->wmi_mutex); mutex_init(&wil->wmi_mutex);
...@@ -136,11 +147,7 @@ int wil_priv_init(struct wil6210_priv *wil) ...@@ -136,11 +147,7 @@ int wil_priv_init(struct wil6210_priv *wil)
return -EAGAIN; return -EAGAIN;
} }
/* make shadow copy of registers that should not change on run time */ wil_cache_mbox_regs(wil);
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);
return 0; return 0;
} }
...@@ -162,7 +169,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) ...@@ -162,7 +169,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
static void wil_target_reset(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 */ /* register write */
#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a))
...@@ -202,7 +209,7 @@ static void wil_target_reset(struct wil6210_priv *wil) ...@@ -202,7 +209,7 @@ static void wil_target_reset(struct wil6210_priv *wil)
msleep(2000); msleep(2000);
wil_dbg(wil, "Reset completed\n"); wil_dbg_misc(wil, "Reset completed\n");
#undef W #undef W
#undef S #undef S
...@@ -225,8 +232,8 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil) ...@@ -225,8 +232,8 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
wil_err(wil, "Firmware not ready\n"); wil_err(wil, "Firmware not ready\n");
return -ETIME; return -ETIME;
} else { } else {
wil_dbg(wil, "FW ready after %d ms\n", wil_dbg_misc(wil, "FW ready after %d ms\n",
jiffies_to_msecs(to-left)); jiffies_to_msecs(to-left));
} }
return 0; return 0;
} }
...@@ -243,13 +250,13 @@ int wil_reset(struct wil6210_priv *wil) ...@@ -243,13 +250,13 @@ int wil_reset(struct wil6210_priv *wil)
cancel_work_sync(&wil->disconnect_worker); cancel_work_sync(&wil->disconnect_worker);
wil6210_disconnect(wil, NULL); wil6210_disconnect(wil, NULL);
wil6210_disable_irq(wil);
wil->status = 0;
wmi_event_flush(wil); wmi_event_flush(wil);
flush_workqueue(wil->wmi_wq);
flush_workqueue(wil->wmi_wq_conn); flush_workqueue(wil->wmi_wq_conn);
flush_workqueue(wil->wmi_wq);
wil6210_disable_irq(wil);
wil->status = 0;
/* TODO: put MAC in reset */ /* TODO: put MAC in reset */
wil_target_reset(wil); wil_target_reset(wil);
...@@ -258,11 +265,7 @@ int wil_reset(struct wil6210_priv *wil) ...@@ -258,11 +265,7 @@ int wil_reset(struct wil6210_priv *wil)
wil->pending_connect_cid = -1; wil->pending_connect_cid = -1;
INIT_COMPLETION(wil->wmi_ready); INIT_COMPLETION(wil->wmi_ready);
/* make shadow copy of registers that should not change on run time */ wil_cache_mbox_regs(wil);
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);
/* TODO: release MAC reset */ /* TODO: release MAC reset */
wil6210_enable_irq(wil); wil6210_enable_irq(wil);
...@@ -278,7 +281,7 @@ void wil_link_on(struct wil6210_priv *wil) ...@@ -278,7 +281,7 @@ void wil_link_on(struct wil6210_priv *wil)
{ {
struct net_device *ndev = wil_to_ndev(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_carrier_on(ndev);
netif_tx_wake_all_queues(ndev); netif_tx_wake_all_queues(ndev);
...@@ -288,7 +291,7 @@ void wil_link_off(struct wil6210_priv *wil) ...@@ -288,7 +291,7 @@ void wil_link_off(struct wil6210_priv *wil)
{ {
struct net_device *ndev = wil_to_ndev(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_tx_stop_all_queues(ndev);
netif_carrier_off(ndev); netif_carrier_off(ndev);
...@@ -311,27 +314,27 @@ static int __wil_up(struct wil6210_priv *wil) ...@@ -311,27 +314,27 @@ static int __wil_up(struct wil6210_priv *wil)
wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC);
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
wil_dbg(wil, "type: STATION\n"); wil_dbg_misc(wil, "type: STATION\n");
bi = 0; bi = 0;
ndev->type = ARPHRD_ETHER; ndev->type = ARPHRD_ETHER;
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
wil_dbg(wil, "type: AP\n"); wil_dbg_misc(wil, "type: AP\n");
bi = 100; bi = 100;
ndev->type = ARPHRD_ETHER; ndev->type = ARPHRD_ETHER;
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
wil_dbg(wil, "type: P2P_CLIENT\n"); wil_dbg_misc(wil, "type: P2P_CLIENT\n");
bi = 0; bi = 0;
ndev->type = ARPHRD_ETHER; ndev->type = ARPHRD_ETHER;
break; break;
case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_P2P_GO:
wil_dbg(wil, "type: P2P_GO\n"); wil_dbg_misc(wil, "type: P2P_GO\n");
bi = 100; bi = 100;
ndev->type = ARPHRD_ETHER; ndev->type = ARPHRD_ETHER;
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
wil_dbg(wil, "type: Monitor\n"); wil_dbg_misc(wil, "type: Monitor\n");
bi = 0; bi = 0;
ndev->type = ARPHRD_IEEE80211_RADIOTAP; ndev->type = ARPHRD_IEEE80211_RADIOTAP;
/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
...@@ -354,7 +357,7 @@ static int __wil_up(struct wil6210_priv *wil) ...@@ -354,7 +357,7 @@ static int __wil_up(struct wil6210_priv *wil)
wmi_set_channel(wil, channel->hw_value); wmi_set_channel(wil, channel->hw_value);
break; break;
default: default:
; break;
} }
/* MAC address - pre-requisite for other commands */ /* MAC address - pre-requisite for other commands */
......
...@@ -35,37 +35,12 @@ static int wil_stop(struct net_device *ndev) ...@@ -35,37 +35,12 @@ static int wil_stop(struct net_device *ndev)
return wil_down(wil); 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 = { static const struct net_device_ops wil_netdev_ops = {
.ndo_open = wil_open, .ndo_open = wil_open,
.ndo_stop = wil_stop, .ndo_stop = wil_stop,
.ndo_start_xmit = wil_start_xmit, .ndo_start_xmit = wil_start_xmit,
.ndo_select_queue = wil_select_queue, .ndo_set_mac_address = eth_mac_addr,
.ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_validate_addr = eth_validate_addr,
}; };
void *wil_if_alloc(struct device *dev, void __iomem *csr) void *wil_if_alloc(struct device *dev, void __iomem *csr)
...@@ -97,7 +72,7 @@ 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; ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); 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) { if (!ndev) {
dev_err(dev, "alloc_netdev_mqs failed\n"); dev_err(dev, "alloc_netdev_mqs failed\n");
rc = -ENOMEM; rc = -ENOMEM;
......
...@@ -53,7 +53,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) ...@@ -53,7 +53,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
} }
wil->n_msi = use_msi; wil->n_msi = use_msi;
if (wil->n_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); rc = pci_enable_msi_block(pdev, wil->n_msi);
if (rc && (wil->n_msi == 3)) { if (rc && (wil->n_msi == 3)) {
wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); 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) ...@@ -65,7 +65,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
wil->n_msi = 0; wil->n_msi = 0;
} }
} else { } 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); rc = wil6210_init_irq(wil, pdev->irq);
......
...@@ -100,8 +100,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) ...@@ -100,8 +100,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
d->dma.status = TX_DMA_STATUS_DU; d->dma.status = TX_DMA_STATUS_DU;
} }
wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
vring->va, (unsigned long long)vring->pa, vring->ctx); vring->va, (unsigned long long)vring->pa, vring->ctx);
return 0; return 0;
} }
...@@ -353,8 +353,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, ...@@ -353,8 +353,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
wil_rx_add_radiotap_header(wil, skb, d); wil_rx_add_radiotap_header(wil, skb, d);
wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); 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_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
(const void *)d, sizeof(*d), false); (const void *)d, sizeof(*d), false);
wil_vring_advance_head(vring, 1); wil_vring_advance_head(vring, 1);
...@@ -369,7 +369,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, ...@@ -369,7 +369,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
*/ */
ftype = wil_rxdesc_ftype(d) << 2; ftype = wil_rxdesc_ftype(d) << 2;
if (ftype != IEEE80211_FTYPE_DATA) { 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 */ /* TODO: process it */
kfree_skb(skb); kfree_skb(skb);
return NULL; return NULL;
...@@ -430,6 +430,8 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) ...@@ -430,6 +430,8 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
int rc; int rc;
unsigned int len = skb->len; unsigned int len = skb->len;
skb_orphan(skb);
if (in_interrupt()) if (in_interrupt())
rc = netif_rx(skb); rc = netif_rx(skb);
else else
...@@ -459,13 +461,11 @@ void wil_rx_handle(struct wil6210_priv *wil) ...@@ -459,13 +461,11 @@ void wil_rx_handle(struct wil6210_priv *wil)
wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
return; return;
} }
wil_dbg_TXRX(wil, "%s()\n", __func__); wil_dbg_txrx(wil, "%s()\n", __func__);
while (NULL != (skb = wil_vring_reap_rx(wil, v))) { 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->data, skb_headlen(skb), false);
skb_orphan(skb);
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
skb->dev = ndev; skb->dev = ndev;
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
...@@ -484,53 +484,18 @@ void wil_rx_handle(struct wil6210_priv *wil) ...@@ -484,53 +484,18 @@ void wil_rx_handle(struct wil6210_priv *wil)
int wil_rx_init(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; struct vring *vring = &wil->vring_rx;
int rc; 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; vring->size = WIL6210_RX_RING_SIZE;
rc = wil_vring_alloc(wil, vring); rc = wil_vring_alloc(wil, vring);
if (rc) if (rc)
return rc; return rc;
cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); rc = wmi_rx_chain_add(wil, vring);
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);
if (rc) if (rc)
goto err_free; 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); rc = wil_rx_refill(wil, vring->size);
if (rc) if (rc)
goto err_free; goto err_free;
...@@ -546,25 +511,8 @@ void wil_rx_fini(struct wil6210_priv *wil) ...@@ -546,25 +511,8 @@ void wil_rx_fini(struct wil6210_priv *wil)
{ {
struct vring *vring = &wil->vring_rx; struct vring *vring = &wil->vring_rx;
if (vring->va) { 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);
wil_vring_free(wil, vring, 0); wil_vring_free(wil, vring, 0);
}
} }
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, 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, ...@@ -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) { if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
wil_err(wil, "Tx config failed, status 0x%02x\n", wil_err(wil, "Tx config failed, status 0x%02x\n",
reply.cmd.status); reply.cmd.status);
rc = -EINVAL;
goto out_free; goto out_free;
} }
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); 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, ...@@ -689,7 +638,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
uint i = swhead; uint i = swhead;
dma_addr_t pa; dma_addr_t pa;
wil_dbg_TXRX(wil, "%s()\n", __func__); wil_dbg_txrx(wil, "%s()\n", __func__);
if (avail < vring->size/8) if (avail < vring->size/8)
netif_tx_stop_all_queues(wil_to_ndev(wil)); 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, ...@@ -706,9 +655,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
pa = dma_map_single(dev, skb->data, pa = dma_map_single(dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE); 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); 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); skb->data, skb_headlen(skb), false);
if (unlikely(dma_mapping_error(dev, pa))) if (unlikely(dma_mapping_error(dev, pa)))
...@@ -737,12 +686,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, ...@@ -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 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_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); (const void *)d, sizeof(*d), false);
/* advance swhead */ /* advance swhead */
wil_vring_advance_head(vring, nr_frags + 1); 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)); iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
/* hold reference to skb /* hold reference to skb
* to prevent skb release before accounting * to prevent skb release before accounting
...@@ -775,7 +724,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -775,7 +724,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct vring *vring; struct vring *vring;
int rc; int rc;
wil_dbg_TXRX(wil, "%s()\n", __func__); wil_dbg_txrx(wil, "%s()\n", __func__);
if (!test_bit(wil_status_fwready, &wil->status)) { if (!test_bit(wil_status_fwready, &wil->status)) {
wil_err(wil, "FW not ready\n"); wil_err(wil, "FW not ready\n");
goto drop; goto drop;
...@@ -802,15 +751,13 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -802,15 +751,13 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
} }
switch (rc) { switch (rc) {
case 0: case 0:
ndev->stats.tx_packets++; /* statistics will be updated on the tx_complete */
ndev->stats.tx_bytes += skb->len;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
case -ENOMEM: case -ENOMEM:
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
default: default:
; /* goto drop; */ break; /* goto drop; */
break;
} }
drop: drop:
netif_tx_stop_all_queues(ndev); netif_tx_stop_all_queues(ndev);
...@@ -827,6 +774,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *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) 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 device *dev = wil_to_dev(wil);
struct vring *vring = &wil->vring_tx[ringid]; struct vring *vring = &wil->vring_tx[ringid];
...@@ -835,7 +783,7 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) ...@@ -835,7 +783,7 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
return; 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)) { while (!wil_vring_is_empty(vring)) {
volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; 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) ...@@ -844,16 +792,23 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
if (!(d->dma.status & TX_DMA_STATUS_DU)) if (!(d->dma.status & TX_DMA_STATUS_DU))
break; break;
wil_dbg_TXRX(wil, wil_dbg_txrx(wil,
"Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
vring->swtail, d->dma.length, d->dma.status, vring->swtail, d->dma.length, d->dma.status,
d->dma.error); 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); (const void *)d, sizeof(*d), false);
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
skb = vring->ctx[vring->swtail]; skb = vring->ctx[vring->swtail];
if (skb) { 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); dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
vring->ctx[vring->swtail] = NULL; vring->ctx[vring->swtail] = NULL;
......
...@@ -36,8 +36,6 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) ...@@ -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_MEM_SIZE (2*1024*1024UL)
#define WIL6210_TX_QUEUES (4)
#define WIL6210_RX_RING_SIZE (128) #define WIL6210_RX_RING_SIZE (128)
#define WIL6210_TX_RING_SIZE (128) #define WIL6210_TX_RING_SIZE (128)
#define WIL6210_MAX_TX_RINGS (24) #define WIL6210_MAX_TX_RINGS (24)
...@@ -101,8 +99,7 @@ struct RGF_ICR { ...@@ -101,8 +99,7 @@ struct RGF_ICR {
#define RGF_DMA_EP_MISC_ICR (0x881bec) /* 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_RX_HTRSH BIT(0)
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) #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_INT(n) BIT(28+n) /* n = [0..3] */
#define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29)
/* Interrupt moderation control */ /* Interrupt moderation control */
#define RGF_DMA_ITR_CNT_TRSH (0x881c5c) #define RGF_DMA_ITR_CNT_TRSH (0x881c5c)
...@@ -121,8 +118,9 @@ struct RGF_ICR { ...@@ -121,8 +118,9 @@ struct RGF_ICR {
#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 #define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2
/* ISR register bits */ /* ISR register bits */
#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 #define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT(0)
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 #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 */ /* Hardware definitions end */
...@@ -272,17 +270,18 @@ struct wil6210_priv { ...@@ -272,17 +270,18 @@ struct wil6210_priv {
#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) #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_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_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_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_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) \ groupsize, buf, len, ascii) \
wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
prefix_type, rowsize, \ prefix_type, rowsize, \
groupsize, buf, len, ascii) 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) \ groupsize, buf, len, ascii) \
wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
prefix_type, rowsize, \ prefix_type, rowsize, \
...@@ -328,6 +327,7 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, ...@@ -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); const void *mac_addr, int key_len, const void *key);
int wmi_echo(struct wil6210_priv *wil); 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_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); int wil6210_init_irq(struct wil6210_priv *wil, int irq);
void wil6210_fini_irq(struct wil6210_priv *wil, int irq); void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
......
...@@ -18,8 +18,10 @@ ...@@ -18,8 +18,10 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include "wil6210.h" #include "wil6210.h"
#include "txrx.h"
#include "wmi.h" #include "wmi.h"
/** /**
...@@ -186,7 +188,6 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) ...@@ -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", wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
(int)(sizeof(cmd) + len), r->entry_size); (int)(sizeof(cmd) + len), r->entry_size);
return -ERANGE; return -ERANGE;
} }
might_sleep(); might_sleep();
...@@ -213,7 +214,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) ...@@ -213,7 +214,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
} }
/* next head */ /* next head */
next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); 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 */ /* wait till FW finish with previous command */
for (retry = 5; retry > 0; retry--) { for (retry = 5; retry > 0; retry--) {
r->tail = ioread32(wil->csr + HOST_MBOX + 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) ...@@ -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); cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
/* set command */ /* set command */
wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
sizeof(cmd), true); 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); len, true);
wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); 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) ...@@ -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; struct wmi_ready_event *evt = d;
u32 ver = le32_to_cpu(evt->sw_version); 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)) { if (!is_valid_ether_addr(ndev->dev_addr)) {
memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); 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) ...@@ -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, static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
int len) 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); set_bit(wil_status_fwready, &wil->status);
/* reuse wmi_ready for the firmware ready indication */ /* 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) ...@@ -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); u32 d_len = le32_to_cpu(data->info.len);
u16 d_status = le16_to_cpu(data->info.status); 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); 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)); 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); data->info.qid, data->info.mid, data->info.cid);
if (!channel) { if (!channel) {
...@@ -329,13 +330,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) ...@@ -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; const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
u.beacon.variable); 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, bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
tsf, cap, bi, ie_buf, ie_len, tsf, cap, bi, ie_buf, ie_len,
signal, GFP_KERNEL); signal, GFP_KERNEL);
if (bss) { if (bss) {
wil_dbg_WMI(wil, "Added BSS %pM\n", wil_dbg_wmi(wil, "Added BSS %pM\n",
rx_mgmt_frame->bssid); rx_mgmt_frame->bssid);
cfg80211_put_bss(bss); cfg80211_put_bss(bss);
} else { } else {
...@@ -351,7 +352,7 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, ...@@ -351,7 +352,7 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
struct wmi_scan_complete_event *data = d; struct wmi_scan_complete_event *data = d;
bool aborted = (data->status != 0); 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); cfg80211_scan_done(wil->scan_request, aborted);
wil->scan_request = NULL; wil->scan_request = NULL;
} else { } else {
...@@ -386,9 +387,9 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) ...@@ -386,9 +387,9 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
return; return;
} }
ch = evt->channel + 1; 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); 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); evt->assoc_info, len - sizeof(*evt), true);
/* figure out IE's */ /* figure out IE's */
...@@ -450,14 +451,13 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, ...@@ -450,14 +451,13 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
{ {
struct wmi_disconnect_event *evt = d; 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->bssid,
evt->protocol_reason_status, evt->disconnect_reason); evt->protocol_reason_status, evt->disconnect_reason);
wil->sinfo_gen++; wil->sinfo_gen++;
wil6210_disconnect(wil, evt->bssid); 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) 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) ...@@ -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.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_rx_sector = le16_to_cpu(evt->other_rx_sector);
wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_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" "BF status 0x%08x SNR 0x%08x\n"
"Tx Tpt %d goodput %d Rx goodput %d\n" "Tx Tpt %d goodput %d Rx goodput %d\n"
"Sectors(rx:tx) my %d:%d peer %d:%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, ...@@ -501,7 +501,7 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
struct sk_buff *skb; struct sk_buff *skb;
struct ethhdr *eth; 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); evt->src_mac);
if (eapol_len > 196) { /* TODO: revisit size limit */ if (eapol_len > 196) { /* TODO: revisit size limit */
...@@ -599,15 +599,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil) ...@@ -599,15 +599,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
iowrite32(0, wil->csr + HOSTADDR(r->tail) + iowrite32(0, wil->csr + HOSTADDR(r->tail) +
offsetof(struct wil6210_mbox_ring_desc, sync)); offsetof(struct wil6210_mbox_ring_desc, sync));
/* indicate */ /* 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), le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
hdr.flags); hdr.flags);
if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
(len >= sizeof(struct wil6210_mbox_hdr_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); 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); &evt->event.hdr, sizeof(hdr) + len, true);
/* advance tail */ /* advance tail */
...@@ -623,7 +623,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) ...@@ -623,7 +623,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
{ {
int q = queue_work(wil->wmi_wq, int q = queue_work(wil->wmi_wq,
&wil->wmi_event_worker); &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, ...@@ -650,7 +650,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
cmdid, reply_id, to_msec); cmdid, reply_id, to_msec);
rc = -ETIME; rc = -ETIME;
} else { } else {
wil_dbg_WMI(wil, wil_dbg_wmi(wil,
"wmi_call(0x%04x->0x%04x) completed in %d msec\n", "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
cmdid, reply_id, cmdid, reply_id,
to_msec - jiffies_to_msecs(remain)); to_msec - jiffies_to_msecs(remain));
...@@ -680,7 +680,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) ...@@ -680,7 +680,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
memcpy(cmd.mac, addr, ETH_ALEN); 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)); 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) ...@@ -778,7 +778,7 @@ int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
skb_set_mac_header(skb, 0); skb_set_mac_header(skb, 0);
eth = eth_hdr(skb); 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++) { for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0)
goto found_dest; goto found_dest;
...@@ -853,11 +853,60 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) ...@@ -853,11 +853,60 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
return rc; 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) void wmi_event_flush(struct wil6210_priv *wil)
{ {
struct pending_wmi_event *evt, *t; 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_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
list_del(&evt->list); list_del(&evt->list);
...@@ -899,7 +948,7 @@ static void wmi_event_handle(struct wil6210_priv *wil, ...@@ -899,7 +948,7 @@ static void wmi_event_handle(struct wil6210_priv *wil,
wmi_evt_call_handler(wil, id, evt_data, wmi_evt_call_handler(wil, id, evt_data,
len - sizeof(*wmi)); 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); complete(&wil->wmi_ready);
return; return;
} }
...@@ -964,7 +1013,7 @@ void wmi_connect_worker(struct work_struct *work) ...@@ -964,7 +1013,7 @@ void wmi_connect_worker(struct work_struct *work)
return; 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); wil->pending_connect_cid);
rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
......
...@@ -542,9 +542,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, ...@@ -542,9 +542,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ARP_FILTER) { if (changed & BSS_CHANGED_ARP_FILTER) {
/* Hardware ARP filter address list or state changed */ /* Hardware ARP filter address list or state changed */
brcms_err(core, "%s: arp filtering: enabled %s, count %d" brcms_err(core, "%s: arp filtering: %d addresses"
" (implement)\n", __func__, info->arp_filter_enabled ? " (implement)\n", __func__, info->arp_addr_cnt);
"true" : "false", info->arp_addr_cnt);
} }
if (changed & BSS_CHANGED_QOS) { if (changed & BSS_CHANGED_QOS) {
......
...@@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority) ...@@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
struct list_head *element; struct list_head *element;
struct il_rx_buf *rxb; struct il_rx_buf *rxb;
struct page *page; struct page *page;
dma_addr_t page_dma;
unsigned long flags; unsigned long flags;
gfp_t gfp_mask = priority; gfp_t gfp_mask = priority;
while (1) { while (1) {
spin_lock_irqsave(&rxq->lock, flags); spin_lock_irqsave(&rxq->lock, flags);
if (list_empty(&rxq->rx_used)) { if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
return; return;
...@@ -1035,26 +1035,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority) ...@@ -1035,26 +1035,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
break; break;
} }
/* Get physical address of RB/SKB */
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); spin_lock_irqsave(&rxq->lock, flags);
if (list_empty(&rxq->rx_used)) { if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags); 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); __free_pages(page, il->hw_params.rx_page_order);
return; return;
} }
element = rxq->rx_used.next; element = rxq->rx_used.next;
rxb = list_entry(element, struct il_rx_buf, list); rxb = list_entry(element, struct il_rx_buf, list);
list_del(element); list_del(element);
spin_unlock_irqrestore(&rxq->lock, flags);
rxb->page = page; rxb->page = page;
/* Get physical address of RB/SKB */ rxb->page_dma = page_dma;
rxb->page_dma =
pci_map_page(il->pci_dev, page, 0,
PAGE_SIZE << il->hw_params.rx_page_order,
PCI_DMA_FROMDEVICE);
spin_lock_irqsave(&rxq->lock, flags);
list_add_tail(&rxb->list, &rxq->rx_free); list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++; rxq->free_count++;
il->alloc_rxb_page++; il->alloc_rxb_page++;
...@@ -1284,8 +1292,15 @@ il3945_rx_handle(struct il_priv *il) ...@@ -1284,8 +1292,15 @@ il3945_rx_handle(struct il_priv *il)
pci_map_page(il->pci_dev, rxb->page, 0, pci_map_page(il->pci_dev, rxb->page, 0,
PAGE_SIZE << il->hw_params. PAGE_SIZE << il->hw_params.
rx_page_order, PCI_DMA_FROMDEVICE); rx_page_order, PCI_DMA_FROMDEVICE);
list_add_tail(&rxb->list, &rxq->rx_free); if (unlikely(pci_dma_mapping_error(il->pci_dev,
rxq->free_count++; 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 } else
list_add_tail(&rxb->list, &rxq->rx_used); list_add_tail(&rxb->list, &rxq->rx_used);
......
...@@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority) ...@@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
struct list_head *element; struct list_head *element;
struct il_rx_buf *rxb; struct il_rx_buf *rxb;
struct page *page; struct page *page;
dma_addr_t page_dma;
unsigned long flags; unsigned long flags;
gfp_t gfp_mask = priority; gfp_t gfp_mask = priority;
...@@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority) ...@@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
return; 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); spin_lock_irqsave(&rxq->lock, flags);
if (list_empty(&rxq->rx_used)) { if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags); 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); __free_pages(page, il->hw_params.rx_page_order);
return; return;
} }
element = rxq->rx_used.next; element = rxq->rx_used.next;
rxb = list_entry(element, struct il_rx_buf, list); rxb = list_entry(element, struct il_rx_buf, list);
list_del(element); list_del(element);
spin_unlock_irqrestore(&rxq->lock, flags);
BUG_ON(rxb->page); 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 = page;
rxb->page_dma = page_dma;
list_add_tail(&rxb->list, &rxq->rx_free); list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++; rxq->free_count++;
il->alloc_rxb_page++; il->alloc_rxb_page++;
...@@ -725,6 +728,16 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) ...@@ -725,6 +728,16 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
if (rate_n_flags & RATE_MCS_SGI_MSK) if (rate_n_flags & RATE_MCS_SGI_MSK)
rx_status.flag |= RX_FLAG_SHORT_GI; 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, il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
&rx_status); &rx_status);
} }
...@@ -736,6 +749,7 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) ...@@ -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); struct il_rx_pkt *pkt = rxb_addr(rxb);
il->_4965.last_phy_res_valid = true; il->_4965.last_phy_res_valid = true;
il->_4965.ampdu_ref++;
memcpy(&il->_4965.last_phy_res, pkt->u.raw, memcpy(&il->_4965.last_phy_res, pkt->u.raw,
sizeof(struct il_rx_phy_res)); sizeof(struct il_rx_phy_res));
} }
...@@ -4281,8 +4295,16 @@ il4965_rx_handle(struct il_priv *il) ...@@ -4281,8 +4295,16 @@ il4965_rx_handle(struct il_priv *il)
pci_map_page(il->pci_dev, rxb->page, 0, pci_map_page(il->pci_dev, rxb->page, 0,
PAGE_SIZE << il->hw_params. PAGE_SIZE << il->hw_params.
rx_page_order, PCI_DMA_FROMDEVICE); 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 } else
list_add_tail(&rxb->list, &rxq->rx_used); 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) ...@@ -6573,9 +6595,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) if (err)
goto out_free_eeprom; goto out_free_eeprom;
if (err)
goto out_free_eeprom;
/* extract MAC Address */ /* extract MAC Address */
il4965_eeprom_get_mac(il, il->addresses[0].addr); il4965_eeprom_get_mac(il, il->addresses[0].addr);
D_INFO("MAC address: %pM\n", il->addresses[0].addr); D_INFO("MAC address: %pM\n", il->addresses[0].addr);
......
...@@ -1748,7 +1748,6 @@ static void ...@@ -1748,7 +1748,6 @@ static void
il4965_post_associate(struct il_priv *il) il4965_post_associate(struct il_priv *il)
{ {
struct ieee80211_vif *vif = il->vif; struct ieee80211_vif *vif = il->vif;
struct ieee80211_conf *conf = NULL;
int ret = 0; int ret = 0;
if (!vif || !il->is_open) if (!vif || !il->is_open)
...@@ -1759,8 +1758,6 @@ il4965_post_associate(struct il_priv *il) ...@@ -1759,8 +1758,6 @@ il4965_post_associate(struct il_priv *il)
il_scan_cancel_timeout(il, 200); il_scan_cancel_timeout(il, 200);
conf = &il->hw->conf;
il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
il_commit_rxon(il); il_commit_rxon(il);
......
...@@ -1134,8 +1134,9 @@ struct il_wep_cmd { ...@@ -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_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_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_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_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_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
......
...@@ -1356,6 +1356,7 @@ struct il_priv { ...@@ -1356,6 +1356,7 @@ struct il_priv {
struct { struct {
struct il_rx_phy_res last_phy_res; struct il_rx_phy_res last_phy_res;
bool last_phy_res_valid; bool last_phy_res_valid;
u32 ampdu_ref;
struct completion firmware_loading_complete; struct completion firmware_loading_complete;
......
...@@ -43,8 +43,20 @@ config IWLWIFI ...@@ -43,8 +43,20 @@ config IWLWIFI
module will be called iwlwifi. module will be called iwlwifi.
config IWLDVM config IWLDVM
tristate "Intel Wireless WiFi" tristate "Intel Wireless WiFi DVM Firmware support"
depends on IWLWIFI 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" menu "Debugging Options"
depends on IWLWIFI depends on IWLWIFI
......
...@@ -5,8 +5,10 @@ iwlwifi-objs += iwl-drv.o ...@@ -5,8 +5,10 @@ iwlwifi-objs += iwl-drv.o
iwlwifi-objs += iwl-debug.o iwlwifi-objs += iwl-debug.o
iwlwifi-objs += iwl-notif-wait.o iwlwifi-objs += iwl-notif-wait.o
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.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/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/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_TRACING) += iwl-devtrace.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
...@@ -15,5 +17,6 @@ ccflags-y += -D__CHECK_ENDIAN__ -I$(src) ...@@ -15,5 +17,6 @@ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
obj-$(CONFIG_IWLDVM) += dvm/ obj-$(CONFIG_IWLDVM) += dvm/
obj-$(CONFIG_IWLMVM) += mvm/
CFLAGS_iwl-devtrace.o := -I$(src) CFLAGS_iwl-devtrace.o := -I$(src)
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
...@@ -459,14 +459,12 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) ...@@ -459,14 +459,12 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
base = priv->device_pointers.error_event_table; base = priv->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) { 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, &flags)) {
if (iwl_trans_grab_nic_access(priv->trans, true)) {
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base); iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); 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; ret = 0;
} }
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
if (ret == 0) { if (ret == 0) {
...@@ -1154,6 +1152,7 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) ...@@ -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, static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_rssi_event rssi_event) enum ieee80211_rssi_event rssi_event)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * 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, ...@@ -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)); ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
/* Make sure device is powered up for SRAM reads */ /* 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, &reg_flags))
if (!iwl_trans_grab_nic_access(priv->trans, false)) {
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
return; return;
}
/* Set starting address; reads will auto-increment */ /* Set starting address; reads will auto-increment */
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr); 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, ...@@ -388,8 +385,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
} }
} }
/* Allow device to power down */ /* Allow device to power down */
iwl_trans_release_nic_access(priv->trans); iwl_trans_release_nic_access(priv->trans, &reg_flags);
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
} }
static void iwl_continuous_event_trace(struct iwl_priv *priv) 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, ...@@ -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); ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
/* Make sure device is powered up for SRAM reads */ /* 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, &reg_flags))
if (!iwl_trans_grab_nic_access(trans, false)) return pos;
goto out_unlock;
/* Set starting address; reads will auto-increment */ /* Set starting address; reads will auto-increment */
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); 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, ...@@ -1757,9 +1752,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
} }
/* Allow device to power down */ /* Allow device to power down */
iwl_trans_release_nic_access(trans); iwl_trans_release_nic_access(trans, &reg_flags);
out_unlock:
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
return pos; return pos;
} }
...@@ -1991,13 +1984,13 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode) ...@@ -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); struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
/* SKU Control */ /* SKU Control */
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, 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_DASH |
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP, CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
(CSR_HW_REV_STEP(priv->trans->hw_rev) << (CSR_HW_REV_STEP(priv->trans->hw_rev) <<
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) | CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
(CSR_HW_REV_DASH(priv->trans->hw_rev) << (CSR_HW_REV_DASH(priv->trans->hw_rev) <<
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH)); CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
/* write radio config values to register */ /* write radio config values to register */
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) { 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) ...@@ -2009,10 +2002,11 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
priv->nvm_data->radio_cfg_dash << priv->nvm_data->radio_cfg_dash <<
CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, 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_TYPE |
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH,
reg_val);
IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
priv->nvm_data->radio_cfg_type, priv->nvm_data->radio_cfg_type,
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * 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, ...@@ -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. * BT traffic, as they would just be disrupted by BT.
*/ */
if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) { if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) {
IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n", IWL_DEBUG_COEX(priv,
priv->bt_traffic_load); "BT traffic (%d), no aggregation allowed\n",
priv->bt_traffic_load);
return ret; return ret;
} }
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portionhelp of the ieee80211 subsystem header files. * as portionhelp of the ieee80211 subsystem header files.
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
...@@ -185,10 +185,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) ...@@ -185,10 +185,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
priv->thermal_throttle.ct_kill_toggle = true; priv->thermal_throttle.ct_kill_toggle = true;
} }
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); 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, &flags))
if (iwl_trans_grab_nic_access(priv->trans, false)) iwl_trans_release_nic_access(priv->trans, &flags);
iwl_trans_release_nic_access(priv->trans);
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
/* Reschedule the ct_kill timer to occur in /* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a * CT_KILL_EXIT_DURATION seconds to ensure we get a
......
/****************************************************************************** /******************************************************************************
* *
* 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 * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -83,6 +83,7 @@ enum iwl_device_family { ...@@ -83,6 +83,7 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_6030, IWL_DEVICE_FAMILY_6030,
IWL_DEVICE_FAMILY_6050, IWL_DEVICE_FAMILY_6050,
IWL_DEVICE_FAMILY_6150, IWL_DEVICE_FAMILY_6150,
IWL_DEVICE_FAMILY_7000,
}; };
/* /*
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
/****************************************************************************** /******************************************************************************
* *
* 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. * Portions of this file are derived from the ipw3945 project.
* *
...@@ -116,6 +116,7 @@ do { \ ...@@ -116,6 +116,7 @@ do { \
#define IWL_DL_HCMD 0x00000004 #define IWL_DL_HCMD 0x00000004
#define IWL_DL_STATE 0x00000008 #define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */ /* 0x000000F0 - 0x00000010 */
#define IWL_DL_TE 0x00000020
#define IWL_DL_EEPROM 0x00000040 #define IWL_DL_EEPROM 0x00000040
#define IWL_DL_RADIO 0x00000080 #define IWL_DL_RADIO 0x00000080
/* 0x00000F00 - 0x00000100 */ /* 0x00000F00 - 0x00000100 */
...@@ -156,6 +157,7 @@ do { \ ...@@ -156,6 +157,7 @@ do { \
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) #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_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_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_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_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
/****************************************************************************** /******************************************************************************
* *
* 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 * 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 * under the terms of version 2 of the GNU General Public License as
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -139,8 +139,10 @@ struct iwl_drv { ...@@ -139,8 +139,10 @@ struct iwl_drv {
#endif #endif
}; };
#define DVM_OP_MODE 0 enum {
#define MVM_OP_MODE 1 DVM_OP_MODE = 0,
MVM_OP_MODE = 1,
};
/* Protects the table contents, i.e. the ops pointer & drv list */ /* Protects the table contents, i.e. the ops pointer & drv list */
static struct mutex iwlwifi_opmode_table_mtx; static struct mutex iwlwifi_opmode_table_mtx;
...@@ -149,8 +151,8 @@ static struct iwlwifi_opmode_table { ...@@ -149,8 +151,8 @@ static struct iwlwifi_opmode_table {
const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */ const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */
struct list_head drv; /* list of devices using this op_mode */ struct list_head drv; /* list of devices using this op_mode */
} iwlwifi_opmode_table[] = { /* ops set when driver is initialized */ } iwlwifi_opmode_table[] = { /* ops set when driver is initialized */
{ .name = "iwldvm", .ops = NULL }, [DVM_OP_MODE] = { .name = "iwldvm", .ops = NULL },
{ .name = "iwlmvm", .ops = NULL }, [MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
}; };
/* /*
...@@ -268,7 +270,7 @@ struct fw_sec_parsing { ...@@ -268,7 +270,7 @@ struct fw_sec_parsing {
*/ */
struct iwl_tlv_calib_data { struct iwl_tlv_calib_data {
__le32 ucode_type; __le32 ucode_type;
__le64 calib; struct iwl_tlv_calib_ctrl calib;
} __packed; } __packed;
struct iwl_firmware_pieces { struct iwl_firmware_pieces {
...@@ -358,7 +360,11 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data) ...@@ -358,7 +360,11 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
ucode_type); ucode_type);
return -EINVAL; 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; return 0;
} }
...@@ -959,7 +965,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -959,7 +965,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
release_firmware(ucode_raw); release_firmware(ucode_raw);
mutex_lock(&iwlwifi_opmode_table_mtx); 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 */ /* add this device to the list of devices using this op_mode */
list_add_tail(&drv->list, &op->drv); list_add_tail(&drv->list, &op->drv);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
/* for all modules */ /* for all modules */
#define DRV_NAME "iwlwifi" #define DRV_NAME "iwlwifi"
#define IWLWIFI_VERSION "in-tree:" #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>" #define DRV_AUTHOR "<ilw@linux.intel.com>"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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, ...@@ -703,9 +703,9 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
return n_channels; return n_channels;
} }
static int iwl_init_sband_channels(struct iwl_nvm_data *data, int iwl_init_sband_channels(struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband, struct ieee80211_supported_band *sband,
int n_channels, enum ieee80211_band band) int n_channels, enum ieee80211_band band)
{ {
struct ieee80211_channel *chan = &data->channels[0]; struct ieee80211_channel *chan = &data->channels[0];
int n = 0, idx = 0; int n = 0, idx = 0;
...@@ -728,10 +728,10 @@ static int iwl_init_sband_channels(struct iwl_nvm_data *data, ...@@ -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_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info, struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band) enum ieee80211_band band)
{ {
int max_bit_rate = 0; int max_bit_rate = 0;
u8 rx_chains; u8 rx_chains;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) ...@@ -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, int iwl_nvm_check_version(struct iwl_nvm_data *data,
struct iwl_trans *trans); 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__ */ #endif /* __iwl_eeprom_parse_h__ */
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) ...@@ -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 * 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_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) #define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -139,6 +139,19 @@ struct fw_img { ...@@ -139,6 +139,19 @@ struct fw_img {
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) #define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) #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 * struct iwl_fw - variables associated with the firmware
* *
...@@ -153,6 +166,7 @@ struct fw_img { ...@@ -153,6 +166,7 @@ struct fw_img {
* @inst_evtlog_ptr: event log offset for runtime ucode. * @inst_evtlog_ptr: event log offset for runtime ucode.
* @inst_evtlog_size: event log size for runtime ucode. * @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset for runtime ucode. * @inst_errlog_ptr: error log offfset for runtime ucode.
* @mvm_fw: indicates this is MVM firmware
*/ */
struct iwl_fw { struct iwl_fw {
u32 ucode_ver; u32 ucode_ver;
...@@ -168,7 +182,7 @@ struct iwl_fw { ...@@ -168,7 +182,7 @@ struct iwl_fw {
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_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; u32 phy_config;
bool mvm_fw; bool mvm_fw;
......
/****************************************************************************** /******************************************************************************
* *
* 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. * Portions of this file are derived from the ipw3945 project.
* *
...@@ -35,54 +35,6 @@ ...@@ -35,54 +35,6 @@
#define IWL_POLL_INTERVAL 10 /* microseconds */ #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, int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout) u32 bits, u32 mask, int timeout)
{ {
...@@ -103,13 +55,10 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) ...@@ -103,13 +55,10 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
{ {
u32 value = 0x5a5a5a5a; u32 value = 0x5a5a5a5a;
unsigned long flags; unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
spin_lock_irqsave(&trans->reg_lock, flags);
if (iwl_trans_grab_nic_access(trans, false)) {
value = iwl_read32(trans, reg); 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; return value;
} }
...@@ -119,12 +68,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) ...@@ -119,12 +68,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
iwl_write32(trans, reg, value); 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); EXPORT_SYMBOL_GPL(iwl_write_direct32);
...@@ -162,12 +109,10 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) ...@@ -162,12 +109,10 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
unsigned long flags; unsigned long flags;
u32 val = 0x5a5a5a5a; u32 val = 0x5a5a5a5a;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
val = __iwl_read_prph(trans, ofs); 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; return val;
} }
EXPORT_SYMBOL_GPL(iwl_read_prph); EXPORT_SYMBOL_GPL(iwl_read_prph);
...@@ -176,12 +121,10 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) ...@@ -176,12 +121,10 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
__iwl_write_prph(trans, ofs, val); __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); EXPORT_SYMBOL_GPL(iwl_write_prph);
...@@ -189,13 +132,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) ...@@ -189,13 +132,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
__iwl_write_prph(trans, ofs, __iwl_write_prph(trans, ofs,
__iwl_read_prph(trans, ofs) | mask); __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); EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
...@@ -204,13 +145,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, ...@@ -204,13 +145,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
__iwl_write_prph(trans, ofs, __iwl_write_prph(trans, ofs,
(__iwl_read_prph(trans, ofs) & mask) | bits); (__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); 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) ...@@ -219,12 +158,10 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
unsigned long flags; unsigned long flags;
u32 val; u32 val;
spin_lock_irqsave(&trans->reg_lock, flags); if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, false)) {
val = __iwl_read_prph(trans, ofs); val = __iwl_read_prph(trans, ofs);
__iwl_write_prph(trans, ofs, (val & ~mask)); __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); EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
/****************************************************************************** /******************************************************************************
* *
* 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. * 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) ...@@ -51,12 +51,15 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
return val; return val;
} }
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); static inline 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); iwl_trans_set_bits_mask(trans, reg, mask, mask);
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 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, int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout); u32 bits, u32 mask, int timeout);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
/******************************************************************************
*
* 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);
/******************************************************************************
*
* 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 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -63,6 +63,8 @@ ...@@ -63,6 +63,8 @@
#ifndef __iwl_op_mode_h__ #ifndef __iwl_op_mode_h__
#define __iwl_op_mode_h__ #define __iwl_op_mode_h__
#include <linux/debugfs.h>
struct iwl_op_mode; struct iwl_op_mode;
struct iwl_trans; struct iwl_trans;
struct sk_buff; struct sk_buff;
......
/******************************************************************************
*
* 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);
/******************************************************************************
*
* 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 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -97,6 +97,9 @@ ...@@ -97,6 +97,9 @@
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
/* Device system time */
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
/** /**
* Tx Scheduler * Tx Scheduler
* *
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) ...@@ -466,9 +466,7 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size)
/* Hard-coded periphery absolute address */ /* Hard-coded periphery absolute address */
if (IWL_ABS_PRPH_START <= addr && if (IWL_ABS_PRPH_START <= addr &&
addr < IWL_ABS_PRPH_START + PRPH_END) { addr < IWL_ABS_PRPH_START + PRPH_END) {
spin_lock_irqsave(&trans->reg_lock, flags); if (!iwl_trans_grab_nic_access(trans, false, &flags)) {
if (!iwl_trans_grab_nic_access(trans, false)) {
spin_unlock_irqrestore(&trans->reg_lock, flags);
return -EIO; return -EIO;
} }
iwl_write32(trans, HBUS_TARG_PRPH_RADDR, 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) ...@@ -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) for (i = 0; i < size; i += 4)
*(u32 *)(tst->mem.addr + i) = *(u32 *)(tst->mem.addr + i) =
iwl_read32(trans, HBUS_TARG_PRPH_RDAT); iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
iwl_trans_release_nic_access(trans); iwl_trans_release_nic_access(trans, &flags);
spin_unlock_irqrestore(&trans->reg_lock, flags);
} else { /* target memory (SRAM) */ } else { /* target memory (SRAM) */
iwl_trans_read_mem(trans, addr, tst->mem.addr, iwl_trans_read_mem(trans, addr, tst->mem.addr,
tst->mem.size / 4); tst->mem.size / 4);
...@@ -506,19 +503,13 @@ static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr, ...@@ -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 */ /* Periphery writes can be 1-3 bytes long, or DWORDs */
if (size < 4) { if (size < 4) {
memcpy(&val, buf, size); memcpy(&val, buf, size);
spin_lock_irqsave(&trans->reg_lock, flags); if (!iwl_trans_grab_nic_access(trans, false, &flags))
if (!iwl_trans_grab_nic_access(trans, false)) {
spin_unlock_irqrestore(&trans->reg_lock, flags);
return -EIO; return -EIO;
}
iwl_write32(trans, HBUS_TARG_PRPH_WADDR, iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
(addr & 0x0000FFFF) | (addr & 0x0000FFFF) |
((size - 1) << 24)); ((size - 1) << 24));
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
iwl_trans_release_nic_access(trans); iwl_trans_release_nic_access(trans, &flags);
/* needed after consecutive writes w/o read */
mmiowb();
spin_unlock_irqrestore(&trans->reg_lock, flags);
} else { } else {
if (size % 4) if (size % 4)
return -EINVAL; return -EINVAL;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -193,11 +193,11 @@ struct iwl_rx_packet { ...@@ -193,11 +193,11 @@ struct iwl_rx_packet {
* @CMD_ON_DEMAND: This command is sent by the test mode pipe. * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
*/ */
enum CMD_MODE { enum CMD_MODE {
CMD_SYNC = 0, CMD_SYNC = 0,
CMD_ASYNC = BIT(0), CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1), CMD_WANT_SKB = BIT(1),
CMD_WANT_HCMD = BIT(2), CMD_WANT_HCMD = BIT(2),
CMD_ON_DEMAND = BIT(3), CMD_ON_DEMAND = BIT(3),
}; };
#define DEF_CMD_PAYLOAD_SIZE 320 #define DEF_CMD_PAYLOAD_SIZE 320
...@@ -274,6 +274,7 @@ struct iwl_rx_cmd_buffer { ...@@ -274,6 +274,7 @@ struct iwl_rx_cmd_buffer {
struct page *_page; struct page *_page;
int _offset; int _offset;
bool _page_stolen; bool _page_stolen;
u32 _rx_page_order;
unsigned int truesize; unsigned int truesize;
}; };
...@@ -294,6 +295,11 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) ...@@ -294,6 +295,11 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
return r->_page; 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 MAX_NO_RECLAIM_CMDS 6
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
...@@ -410,8 +416,12 @@ struct iwl_trans; ...@@ -410,8 +416,12 @@ struct iwl_trans;
* the op_mode. May be called several times before start_fw, can't be * the op_mode. May be called several times before start_fw, can't be
* called after that. * called after that.
* @set_pmi: set the power pmi state * @set_pmi: set the power pmi state
* @grab_nic_access: wake the NIC to be able to access non-HBUS regs * @grab_nic_access: wake the NIC to be able to access non-HBUS regs.
* @release_nic_access: let the NIC go to sleep * 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 { struct iwl_trans_ops {
...@@ -454,8 +464,12 @@ struct iwl_trans_ops { ...@@ -454,8 +464,12 @@ struct iwl_trans_ops {
void (*configure)(struct iwl_trans *trans, void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg); const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state); void (*set_pmi)(struct iwl_trans *trans, bool state);
bool (*grab_nic_access)(struct iwl_trans *trans, bool silent); bool (*grab_nic_access)(struct iwl_trans *trans, bool silent,
void (*release_nic_access)(struct iwl_trans *trans); 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 { ...@@ -475,7 +489,6 @@ enum iwl_trans_state {
* @ops - pointer to iwl_trans_ops * @ops - pointer to iwl_trans_ops
* @op_mode - pointer to the op_mode * @op_mode - pointer to the op_mode
* @cfg - pointer to the configuration * @cfg - pointer to the configuration
* @reg_lock - protect hw register access
* @dev - pointer to struct device * that represents the device * @dev - pointer to struct device * that represents the device
* @hw_id: a u32 with the ID of the device / subdevice. * @hw_id: a u32 with the ID of the device / subdevice.
* Set during transport allocation. * Set during transport allocation.
...@@ -496,7 +509,6 @@ struct iwl_trans { ...@@ -496,7 +509,6 @@ struct iwl_trans {
struct iwl_op_mode *op_mode; struct iwl_op_mode *op_mode;
const struct iwl_cfg *cfg; const struct iwl_cfg *cfg;
enum iwl_trans_state state; enum iwl_trans_state state;
spinlock_t reg_lock;
struct device *dev; struct device *dev;
u32 hw_rev; u32 hw_rev;
...@@ -756,14 +768,20 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) ...@@ -756,14 +768,20 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
trans->ops->set_pmi(trans, 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, \ __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) 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); __release(nic_access);
} }
......
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)/../
/******************************************************************************
*
* 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);
}
此差异已折叠。
/******************************************************************************
*
* 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;
}
此差异已折叠。
此差异已折叠。
/******************************************************************************
*
* 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
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册