mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 17:21:49 +00:00
Merge remote-tracking branch 'wireless-next/master' into HEAD
This commit is contained in:
commit
78f42aee88
@ -309,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] = {
|
||||
.gpio_wp = 63,
|
||||
.deferred = true,
|
||||
},
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
{
|
||||
.name = "wl1271",
|
||||
.mmc = 2,
|
||||
@ -450,7 +450,7 @@ static struct regulator_init_data omap3evm_vio = {
|
||||
.consumer_supplies = omap3evm_vio_supply,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
|
||||
#define OMAP3EVM_WLAN_PMENA_GPIO (150)
|
||||
#define OMAP3EVM_WLAN_IRQ_GPIO (149)
|
||||
@ -563,7 +563,7 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = {
|
||||
OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
|
||||
OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
@ -601,7 +601,7 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = {
|
||||
OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
@ -637,7 +637,7 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
|
||||
|
||||
static void __init omap3_evm_wl12xx_init(void)
|
||||
{
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
int ret;
|
||||
|
||||
/* WL12xx WLAN Init */
|
||||
|
@ -47,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus);
|
||||
/* driver_chipcommon.c */
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
extern struct platform_device bcma_pflash_dev;
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
/* driver_chipcommon_pmu.c */
|
||||
|
@ -5,11 +5,11 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
struct platform_device bcma_nflash_dev = {
|
||||
.name = "bcma_nflash",
|
||||
.num_resources = 0,
|
||||
|
@ -5,11 +5,11 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SOC_FLASH2,
|
||||
|
@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
||||
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
|
||||
}
|
||||
|
||||
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
||||
|
||||
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
return bcma_core_irq(cc->core);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct gpio_chip *chip = &cc->gpio;
|
||||
@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
chip->ngpio = 16;
|
||||
/* There is just one SoC in one device and its GPIO addresses should be
|
||||
* deterministic to address them more easily. The other buses could get
|
||||
|
@ -14,11 +14,33 @@
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
static const char *part_probes[] = { "bcm47xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data bcma_pflash_data = {
|
||||
.part_probe_types = part_probes,
|
||||
};
|
||||
|
||||
static struct resource bcma_pflash_resource = {
|
||||
.name = "bcma_pflash",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device bcma_pflash_dev = {
|
||||
.name = "physmap-flash",
|
||||
.dev = {
|
||||
.platform_data = &bcma_pflash_data,
|
||||
},
|
||||
.resource = &bcma_pflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
{
|
||||
@ -211,6 +233,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
struct bcma_drv_cc *cc = &bus->drv_cc;
|
||||
struct bcma_pflash *pflash = &cc->pflash;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
@ -220,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
cc->pflash.present = true;
|
||||
cc->pflash.window = BCMA_SOC_FLASH2;
|
||||
cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
|
||||
pflash->present = true;
|
||||
pflash->window = BCMA_SOC_FLASH2;
|
||||
pflash->window_size = BCMA_SOC_FLASH2_SZ;
|
||||
|
||||
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
|
||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
cc->pflash.buswidth = 1;
|
||||
pflash->buswidth = 1;
|
||||
else
|
||||
cc->pflash.buswidth = 2;
|
||||
pflash->buswidth = 2;
|
||||
|
||||
bcma_pflash_data.width = pflash->buswidth;
|
||||
bcma_pflash_resource.start = pflash->window;
|
||||
bcma_pflash_resource.end = pflash->window + pflash->window_size;
|
||||
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Flash type not supported\n");
|
||||
|
@ -149,6 +149,14 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
||||
dev_id++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
if (bus->drv_cc.pflash.present) {
|
||||
err = platform_device_register(&bcma_pflash_dev);
|
||||
if (err)
|
||||
bcma_err(bus, "Error registering parallel flash\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
if (bus->drv_cc.sflash.present) {
|
||||
err = platform_device_register(&bcma_sflash_dev);
|
||||
|
@ -1613,6 +1613,10 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
ah->ah_cal_mask |= AR5K_CALIBRATION_NF;
|
||||
|
||||
ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
|
||||
if (WARN_ON(ee_mode < 0)) {
|
||||
ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF;
|
||||
return;
|
||||
}
|
||||
|
||||
/* completed NF calibration, test threshold */
|
||||
nf = ath5k_hw_read_measured_noise_floor(ah);
|
||||
|
@ -985,6 +985,8 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
||||
return;
|
||||
|
||||
ee_mode = ath5k_eeprom_mode_from_channel(channel);
|
||||
if (WARN_ON(ee_mode < 0))
|
||||
return;
|
||||
|
||||
/* Adjust power delta for channel 14 */
|
||||
if (channel->center_freq == 2484)
|
||||
|
@ -58,6 +58,7 @@ config ATH9K_DEBUGFS
|
||||
bool "Atheros ath9k debugging"
|
||||
depends on ATH9K
|
||||
select MAC80211_DEBUGFS
|
||||
select RELAY
|
||||
---help---
|
||||
Say Y, if you need access to ath9k's statistics for
|
||||
interrupts, rate control, etc.
|
||||
|
@ -319,6 +319,8 @@ struct ath_rx {
|
||||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
|
||||
struct sk_buff *frag;
|
||||
|
||||
u32 ampdu_ref;
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
@ -754,6 +756,7 @@ struct ath_softc {
|
||||
/* relay(fs) channel for spectral scan */
|
||||
struct rchan *rfs_chan_spec_scan;
|
||||
enum spectral_mode spectral_mode;
|
||||
struct ath_spec_scan spec_config;
|
||||
int scanning;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -863,31 +866,31 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
|
||||
* interface.
|
||||
*/
|
||||
enum ath_fft_sample_type {
|
||||
ATH_FFT_SAMPLE_HT20 = 0,
|
||||
ATH_FFT_SAMPLE_HT20 = 1,
|
||||
};
|
||||
|
||||
struct fft_sample_tlv {
|
||||
u8 type; /* see ath_fft_sample */
|
||||
u16 length;
|
||||
__be16 length;
|
||||
/* type dependent data follows */
|
||||
} __packed;
|
||||
|
||||
struct fft_sample_ht20 {
|
||||
struct fft_sample_tlv tlv;
|
||||
|
||||
u8 __alignment;
|
||||
u8 max_exp;
|
||||
|
||||
u16 freq;
|
||||
__be16 freq;
|
||||
s8 rssi;
|
||||
s8 noise;
|
||||
|
||||
u16 max_magnitude;
|
||||
__be16 max_magnitude;
|
||||
u8 max_index;
|
||||
u8 bitmap_weight;
|
||||
|
||||
u64 tsf;
|
||||
__be64 tsf;
|
||||
|
||||
u16 data[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 data[SPECTRAL_HT20_NUM_BINS];
|
||||
} __packed;
|
||||
|
||||
void ath9k_tasklet(unsigned long data);
|
||||
|
@ -895,6 +895,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||
RXS_ERR("RX-Bytes-All", rx_bytes_all);
|
||||
RXS_ERR("RX-Beacons", rx_beacons);
|
||||
RXS_ERR("RX-Frags", rx_frags);
|
||||
RXS_ERR("RX-Spectral", rx_spectral);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
@ -1035,6 +1036,182 @@ static const struct file_operations fops_spec_scan_ctl = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_short_repeat(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_short_repeat(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.short_repeat = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_short_repeat = {
|
||||
.read = read_file_spectral_short_repeat,
|
||||
.write = write_file_spectral_short_repeat,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_count(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.count);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_count(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.count = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_count = {
|
||||
.read = read_file_spectral_count,
|
||||
.write = write_file_spectral_count,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_period(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.period);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_period(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.period = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_period = {
|
||||
.read = read_file_spectral_period,
|
||||
.write = write_file_spectral_period,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spectral_fft_period(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spectral_fft_period(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val < 0 || val > 15)
|
||||
return -EINVAL;
|
||||
|
||||
sc->spec_config.fft_period = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spectral_fft_period = {
|
||||
.read = read_file_spectral_fft_period,
|
||||
.write = write_file_spectral_fft_period,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static struct dentry *create_buf_file_handler(const char *filename,
|
||||
struct dentry *parent,
|
||||
umode_t mode,
|
||||
@ -1059,11 +1236,13 @@ static int remove_buf_file_handler(struct dentry *dentry)
|
||||
void ath_debug_send_fft_sample(struct ath_softc *sc,
|
||||
struct fft_sample_tlv *fft_sample_tlv)
|
||||
{
|
||||
int length;
|
||||
if (!sc->rfs_chan_spec_scan)
|
||||
return;
|
||||
|
||||
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv,
|
||||
fft_sample_tlv->length + sizeof(*fft_sample_tlv));
|
||||
length = __be16_to_cpu(fft_sample_tlv->length) +
|
||||
sizeof(*fft_sample_tlv);
|
||||
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
@ -1893,6 +2072,16 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spec_scan_ctl);
|
||||
debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spectral_short_repeat);
|
||||
debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_spectral_count);
|
||||
debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_spectral_period);
|
||||
debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spectral_fft_period);
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
|
@ -219,6 +219,7 @@ struct ath_tx_stats {
|
||||
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
|
||||
* @rx_beacons: No. of beacons received.
|
||||
* @rx_frags: No. of rx-fragements received.
|
||||
* @rx_spectral: No of spectral packets received.
|
||||
*/
|
||||
struct ath_rx_stats {
|
||||
u32 rx_pkts_all;
|
||||
@ -237,6 +238,7 @@ struct ath_rx_stats {
|
||||
u32 rx_too_many_frags_err;
|
||||
u32 rx_beacons;
|
||||
u32 rx_frags;
|
||||
u32 rx_spectral;
|
||||
};
|
||||
|
||||
struct ath_stats {
|
||||
|
@ -497,6 +497,13 @@ static void ath9k_init_misc(struct ath_softc *sc)
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
|
||||
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
|
||||
|
||||
sc->spec_config.enabled = 0;
|
||||
sc->spec_config.short_repeat = true;
|
||||
sc->spec_config.count = 8;
|
||||
sc->spec_config.endless = false;
|
||||
sc->spec_config.period = 0xFF;
|
||||
sc->spec_config.fft_period = 0xF;
|
||||
}
|
||||
|
||||
static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
|
||||
@ -915,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
|
||||
|
||||
ath9k_eeprom_release(sc);
|
||||
|
||||
if (sc->rfs_chan_spec_scan) {
|
||||
if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
|
||||
relay_close(sc->rfs_chan_spec_scan);
|
||||
sc->rfs_chan_spec_scan = NULL;
|
||||
}
|
||||
|
@ -605,13 +605,13 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
* reported, then decryption and MIC errors are irrelevant,
|
||||
* the frame is going to be dropped either way
|
||||
*/
|
||||
if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
rs->rs_status |= ATH9K_RXERR_PHY;
|
||||
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
|
||||
rs->rs_phyerr = phyerr;
|
||||
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
} else if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
else if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
rs->rs_status |= ATH9K_RXERR_MIC;
|
||||
|
@ -1099,45 +1099,34 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_spec_scan param;
|
||||
|
||||
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
||||
ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NOTE: this will generate a few samples ...
|
||||
*
|
||||
* TODO: review default parameters, and/or define an interface to set
|
||||
* them.
|
||||
*/
|
||||
param.enabled = 1;
|
||||
param.short_repeat = true;
|
||||
param.count = 8;
|
||||
param.endless = false;
|
||||
param.period = 0xFF;
|
||||
param.fft_period = 0xF;
|
||||
|
||||
switch (spectral_mode) {
|
||||
case SPECTRAL_DISABLED:
|
||||
param.enabled = 0;
|
||||
sc->spec_config.enabled = 0;
|
||||
break;
|
||||
case SPECTRAL_BACKGROUND:
|
||||
/* send endless samples.
|
||||
* TODO: is this really useful for "background"?
|
||||
*/
|
||||
param.endless = 1;
|
||||
sc->spec_config.endless = 1;
|
||||
sc->spec_config.enabled = 1;
|
||||
break;
|
||||
case SPECTRAL_CHANSCAN:
|
||||
break;
|
||||
case SPECTRAL_MANUAL:
|
||||
sc->spec_config.endless = 0;
|
||||
sc->spec_config.enabled = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_ops(ah)->spectral_scan_config(ah, ¶m);
|
||||
ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
sc->spectral_mode = spectral_mode;
|
||||
|
@ -474,8 +474,6 @@ void ath_mci_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_mci_coex *mci = &sc->mci_coex;
|
||||
struct ath_mci_buf *buf = &mci->sched_buf;
|
||||
|
||||
ar9003_mci_cleanup(ah);
|
||||
|
||||
|
@ -1016,18 +1016,20 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
static s8 fix_rssi_inv_only(u8 rssi_val)
|
||||
{
|
||||
if (rssi_val == 128)
|
||||
rssi_val = 0;
|
||||
return (s8) rssi_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
/* returns 1 if this was a spectral frame, even if not handled. */
|
||||
static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
{
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
u8 bins[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 *vdata = (u8 *)hdr;
|
||||
@ -1035,7 +1037,8 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_radar_info *radar_info;
|
||||
struct ath_ht20_mag_info *mag_info;
|
||||
int len = rs->rs_datalen;
|
||||
int i, dc_pos;
|
||||
int dc_pos;
|
||||
u16 length, max_magnitude;
|
||||
|
||||
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
|
||||
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
|
||||
@ -1044,7 +1047,14 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* check if spectral scan bit is set. This does not have to be checked
|
||||
* if received through a SPECTRAL phy error, but shouldn't hurt.
|
||||
*/
|
||||
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
|
||||
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
|
||||
return 0;
|
||||
|
||||
/* Variation in the data length is possible and will be fixed later.
|
||||
* Note that we only support HT20 for now.
|
||||
@ -1053,19 +1063,13 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
*/
|
||||
if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
|
||||
(len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
|
||||
return;
|
||||
|
||||
/* check if spectral scan bit is set. This does not have to be checked
|
||||
* if received through a SPECTRAL phy error, but shouldn't hurt.
|
||||
*/
|
||||
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
|
||||
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
|
||||
fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
fft_sample.tlv.length = __cpu_to_be16(length);
|
||||
|
||||
fft_sample.freq = ah->curchan->chan->center_freq;
|
||||
fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
|
||||
fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
|
||||
fft_sample.noise = ah->noise;
|
||||
|
||||
@ -1093,7 +1097,7 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DC value (value in the middle) is the blind spot of the spectral
|
||||
@ -1105,19 +1109,41 @@ static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
/* mag data is at the end of the frame, in front of radar_info */
|
||||
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
|
||||
|
||||
/* Apply exponent and grab further auxiliary information. */
|
||||
for (i = 0; i < SPECTRAL_HT20_NUM_BINS; i++)
|
||||
fft_sample.data[i] = bins[i] << mag_info->max_exp;
|
||||
/* copy raw bins without scaling them */
|
||||
memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
|
||||
fft_sample.max_exp = mag_info->max_exp & 0xf;
|
||||
|
||||
fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
fft_sample.max_magnitude = __cpu_to_be16(max_magnitude);
|
||||
fft_sample.max_index = spectral_max_index(mag_info->all_bins);
|
||||
fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
|
||||
fft_sample.tsf = tsf;
|
||||
fft_sample.tsf = __cpu_to_be64(tsf);
|
||||
|
||||
ath_debug_send_fft_sample(sc, &fft_sample.tlv);
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ath9k_apply_ampdu_details(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
if (rs->rs_isaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
|
||||
|
||||
rxs->ampdu_reference = sc->rx.ampdu_ref;
|
||||
|
||||
if (!rs->rs_moreaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_IS_LAST;
|
||||
sc->rx.ampdu_ref++;
|
||||
}
|
||||
|
||||
if (rs->rs_flags & ATH9K_RX_DELIM_CRC_PRE)
|
||||
rxs->flag |= RX_FLAG_AMPDU_DELIM_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
@ -1202,8 +1228,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
|
||||
rxs->mactime += 0x100000000ULL;
|
||||
|
||||
if ((rs.rs_status & ATH9K_RXERR_PHY))
|
||||
ath_process_fft(sc, hdr, &rs, rxs->mactime);
|
||||
if (rs.rs_status & ATH9K_RXERR_PHY) {
|
||||
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
|
||||
RX_STAT_INC(rx_spectral);
|
||||
goto requeue_drop_frag;
|
||||
}
|
||||
}
|
||||
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
@ -1320,6 +1350,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
|
||||
ath_ant_comb_scan(sc, &rs);
|
||||
|
||||
ath9k_apply_ampdu_details(sc, &rs, rxs);
|
||||
|
||||
ieee80211_rx(hw, skb);
|
||||
|
||||
requeue_drop_frag:
|
||||
|
@ -204,7 +204,6 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
}
|
||||
|
||||
/* FW don't support scan after connection attempt */
|
||||
@ -228,8 +227,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
}
|
||||
/* 0-based channel indexes */
|
||||
cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
|
||||
wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch,
|
||||
request->channels[i]->center_freq);
|
||||
wil_dbg_misc(wil, "Scan for ch %d : %d MHz\n", ch,
|
||||
request->channels[i]->center_freq);
|
||||
}
|
||||
|
||||
return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
|
||||
@ -425,8 +424,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
|
||||
channel->center_freq, info->privacy ? "secure" : "open");
|
||||
wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
|
||||
channel->center_freq, info->privacy ? "secure" : "open");
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
info->ssid, info->ssid_len);
|
||||
|
||||
|
@ -38,7 +38,9 @@
|
||||
#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE
|
||||
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
|
||||
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
|
||||
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT)
|
||||
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \
|
||||
ISR_MISC_MBOX_EVT | \
|
||||
ISR_MISC_FW_ERROR)
|
||||
|
||||
#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
|
||||
BIT_DMA_PSEUDO_CAUSE_TX | \
|
||||
@ -50,7 +52,6 @@
|
||||
|
||||
static inline void wil_icr_clear(u32 x, void __iomem *addr)
|
||||
{
|
||||
|
||||
}
|
||||
#else /* defined(CONFIG_WIL6210_ISR_COR) */
|
||||
/* configure to Write-1-to-Clear mode */
|
||||
@ -94,7 +95,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
|
||||
|
||||
static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
|
||||
HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
|
||||
@ -125,7 +126,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
|
||||
|
||||
static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
set_bit(wil_status_irqen, &wil->status);
|
||||
|
||||
@ -135,7 +136,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
|
||||
|
||||
void wil6210_disable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
wil6210_mask_irq_tx(wil);
|
||||
wil6210_mask_irq_rx(wil);
|
||||
@ -145,7 +146,7 @@ void wil6210_disable_irq(struct wil6210_priv *wil)
|
||||
|
||||
void wil6210_enable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_IRQ(wil, "%s()\n", __func__);
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICC));
|
||||
@ -167,7 +168,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
||||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: RX\n");
|
||||
@ -177,7 +178,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
||||
wil6210_mask_irq_rx(wil);
|
||||
|
||||
if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
|
||||
wil_dbg_IRQ(wil, "RX done\n");
|
||||
wil_dbg_irq(wil, "RX done\n");
|
||||
isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
|
||||
wil_rx_handle(wil);
|
||||
}
|
||||
@ -197,7 +198,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: TX\n");
|
||||
@ -208,13 +209,13 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
|
||||
if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
|
||||
uint i;
|
||||
wil_dbg_IRQ(wil, "TX done\n");
|
||||
wil_dbg_irq(wil, "TX done\n");
|
||||
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
|
||||
for (i = 0; i < 24; i++) {
|
||||
u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i);
|
||||
if (isr & mask) {
|
||||
isr &= ~mask;
|
||||
wil_dbg_IRQ(wil, "TX done(%i)\n", i);
|
||||
wil_dbg_irq(wil, "TX done(%i)\n", i);
|
||||
wil_tx_complete(wil, i);
|
||||
}
|
||||
}
|
||||
@ -228,6 +229,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void wil_notify_fw_error(struct wil6210_priv *wil)
|
||||
{
|
||||
struct device *dev = &wil_to_ndev(wil)->dev;
|
||||
char *envp[3] = {
|
||||
[0] = "SOURCE=wil6210",
|
||||
[1] = "EVENT=FW_ERROR",
|
||||
[2] = NULL,
|
||||
};
|
||||
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
@ -235,7 +247,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
||||
HOSTADDR(RGF_DMA_EP_MISC_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
|
||||
wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr);
|
||||
|
||||
if (!isr) {
|
||||
wil_err(wil, "spurious IRQ: MISC\n");
|
||||
@ -244,8 +256,15 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
||||
|
||||
wil6210_mask_irq_misc(wil);
|
||||
|
||||
if (isr & ISR_MISC_FW_ERROR) {
|
||||
wil_dbg_irq(wil, "IRQ: Firmware error\n");
|
||||
clear_bit(wil_status_fwready, &wil->status);
|
||||
wil_notify_fw_error(wil);
|
||||
isr &= ~ISR_MISC_FW_ERROR;
|
||||
}
|
||||
|
||||
if (isr & ISR_MISC_FW_READY) {
|
||||
wil_dbg_IRQ(wil, "IRQ: FW ready\n");
|
||||
wil_dbg_irq(wil, "IRQ: FW ready\n");
|
||||
/**
|
||||
* Actual FW ready indicated by the
|
||||
* WMI_FW_READY_EVENTID
|
||||
@ -268,10 +287,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
|
||||
struct wil6210_priv *wil = cookie;
|
||||
u32 isr = wil->isr_misc;
|
||||
|
||||
wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr);
|
||||
wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
|
||||
|
||||
if (isr & ISR_MISC_MBOX_EVT) {
|
||||
wil_dbg_IRQ(wil, "MBOX event\n");
|
||||
wil_dbg_irq(wil, "MBOX event\n");
|
||||
wmi_recv_cmd(wil);
|
||||
isr &= ~ISR_MISC_MBOX_EVT;
|
||||
}
|
||||
@ -293,7 +312,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
|
||||
wil_dbg_IRQ(wil, "Thread IRQ\n");
|
||||
wil_dbg_irq(wil, "Thread IRQ\n");
|
||||
/* Discover real IRQ cause */
|
||||
if (wil->isr_misc)
|
||||
wil6210_irq_misc_thread(irq, cookie);
|
||||
@ -370,6 +389,8 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
||||
if (wil6210_debug_irq_mask(wil, pseudo_cause))
|
||||
return IRQ_NONE;
|
||||
|
||||
wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause);
|
||||
|
||||
wil6210_mask_irq_pseudo(wil);
|
||||
|
||||
/* Discover real IRQ cause
|
||||
@ -401,8 +422,6 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
||||
if (rc != IRQ_WAKE_THREAD)
|
||||
wil6210_unmask_irq_pseudo(wil);
|
||||
|
||||
wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
wil_link_off(wil);
|
||||
clear_bit(wil_status_fwconnected, &wil->status);
|
||||
@ -80,11 +80,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++)
|
||||
wil_vring_fini_tx(wil, i);
|
||||
|
||||
clear_bit(wil_status_dontscan, &wil->status);
|
||||
}
|
||||
|
||||
static void wil_disconnect_worker(struct work_struct *work)
|
||||
@ -99,7 +101,7 @@ static void wil_connect_timer_fn(ulong x)
|
||||
{
|
||||
struct wil6210_priv *wil = (void *)x;
|
||||
|
||||
wil_dbg(wil, "Connect timeout\n");
|
||||
wil_dbg_misc(wil, "Connect timeout\n");
|
||||
|
||||
/* reschedule to thread context - disconnect won't
|
||||
* run from atomic context
|
||||
@ -107,9 +109,18 @@ static void wil_connect_timer_fn(ulong x)
|
||||
schedule_work(&wil->disconnect_worker);
|
||||
}
|
||||
|
||||
static void wil_cache_mbox_regs(struct wil6210_priv *wil)
|
||||
{
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
}
|
||||
|
||||
int wil_priv_init(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
mutex_init(&wil->mutex);
|
||||
mutex_init(&wil->wmi_mutex);
|
||||
@ -136,11 +147,7 @@ int wil_priv_init(struct wil6210_priv *wil)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
wil_cache_mbox_regs(wil);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -162,7 +169,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
|
||||
|
||||
static void wil_target_reset(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg(wil, "Resetting...\n");
|
||||
wil_dbg_misc(wil, "Resetting...\n");
|
||||
|
||||
/* register write */
|
||||
#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a))
|
||||
@ -202,7 +209,7 @@ static void wil_target_reset(struct wil6210_priv *wil)
|
||||
|
||||
msleep(2000);
|
||||
|
||||
wil_dbg(wil, "Reset completed\n");
|
||||
wil_dbg_misc(wil, "Reset completed\n");
|
||||
|
||||
#undef W
|
||||
#undef S
|
||||
@ -225,8 +232,8 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
|
||||
wil_err(wil, "Firmware not ready\n");
|
||||
return -ETIME;
|
||||
} else {
|
||||
wil_dbg(wil, "FW ready after %d ms\n",
|
||||
jiffies_to_msecs(to-left));
|
||||
wil_dbg_misc(wil, "FW ready after %d ms\n",
|
||||
jiffies_to_msecs(to-left));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -243,14 +250,14 @@ int wil_reset(struct wil6210_priv *wil)
|
||||
cancel_work_sync(&wil->disconnect_worker);
|
||||
wil6210_disconnect(wil, NULL);
|
||||
|
||||
wmi_event_flush(wil);
|
||||
|
||||
flush_workqueue(wil->wmi_wq);
|
||||
flush_workqueue(wil->wmi_wq_conn);
|
||||
|
||||
wil6210_disable_irq(wil);
|
||||
wil->status = 0;
|
||||
|
||||
wmi_event_flush(wil);
|
||||
|
||||
flush_workqueue(wil->wmi_wq_conn);
|
||||
flush_workqueue(wil->wmi_wq);
|
||||
|
||||
/* TODO: put MAC in reset */
|
||||
wil_target_reset(wil);
|
||||
|
||||
@ -258,11 +265,7 @@ int wil_reset(struct wil6210_priv *wil)
|
||||
wil->pending_connect_cid = -1;
|
||||
INIT_COMPLETION(wil->wmi_ready);
|
||||
|
||||
/* make shadow copy of registers that should not change on run time */
|
||||
wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
|
||||
sizeof(struct wil6210_mbox_ctl));
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
|
||||
wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
|
||||
wil_cache_mbox_regs(wil);
|
||||
|
||||
/* TODO: release MAC reset */
|
||||
wil6210_enable_irq(wil);
|
||||
@ -278,7 +281,7 @@ void wil_link_on(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
netif_carrier_on(ndev);
|
||||
netif_tx_wake_all_queues(ndev);
|
||||
@ -288,7 +291,7 @@ void wil_link_off(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
wil_dbg(wil, "%s()\n", __func__);
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
netif_carrier_off(ndev);
|
||||
@ -311,27 +314,27 @@ static int __wil_up(struct wil6210_priv *wil)
|
||||
wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC);
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wil_dbg(wil, "type: STATION\n");
|
||||
wil_dbg_misc(wil, "type: STATION\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
wil_dbg(wil, "type: AP\n");
|
||||
wil_dbg_misc(wil, "type: AP\n");
|
||||
bi = 100;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
wil_dbg(wil, "type: P2P_CLIENT\n");
|
||||
wil_dbg_misc(wil, "type: P2P_CLIENT\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
wil_dbg(wil, "type: P2P_GO\n");
|
||||
wil_dbg_misc(wil, "type: P2P_GO\n");
|
||||
bi = 100;
|
||||
ndev->type = ARPHRD_ETHER;
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
wil_dbg(wil, "type: Monitor\n");
|
||||
wil_dbg_misc(wil, "type: Monitor\n");
|
||||
bi = 0;
|
||||
ndev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
|
||||
@ -354,7 +357,7 @@ static int __wil_up(struct wil6210_priv *wil)
|
||||
wmi_set_channel(wil, channel->hw_value);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
/* MAC address - pre-requisite for other commands */
|
||||
|
@ -35,37 +35,12 @@ static int wil_stop(struct net_device *ndev)
|
||||
return wil_down(wil);
|
||||
}
|
||||
|
||||
/*
|
||||
* AC to queue mapping
|
||||
*
|
||||
* AC_VO -> queue 3
|
||||
* AC_VI -> queue 2
|
||||
* AC_BE -> queue 1
|
||||
* AC_BK -> queue 0
|
||||
*/
|
||||
static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb)
|
||||
{
|
||||
static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
|
||||
struct wil6210_priv *wil = ndev_to_wil(ndev);
|
||||
u16 rc;
|
||||
|
||||
skb->priority = cfg80211_classify8021d(skb);
|
||||
|
||||
rc = wil_1d_to_queue[skb->priority];
|
||||
|
||||
wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority,
|
||||
(int)rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct net_device_ops wil_netdev_ops = {
|
||||
.ndo_open = wil_open,
|
||||
.ndo_stop = wil_stop,
|
||||
.ndo_start_xmit = wil_start_xmit,
|
||||
.ndo_select_queue = wil_select_queue,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
||||
@ -97,7 +72,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
|
||||
ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
|
||||
cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
|
||||
|
||||
ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1);
|
||||
ndev = alloc_netdev(0, "wlan%d", ether_setup);
|
||||
if (!ndev) {
|
||||
dev_err(dev, "alloc_netdev_mqs failed\n");
|
||||
rc = -ENOMEM;
|
||||
|
@ -53,7 +53,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
||||
}
|
||||
wil->n_msi = use_msi;
|
||||
if (wil->n_msi) {
|
||||
wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi);
|
||||
wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
|
||||
rc = pci_enable_msi_block(pdev, wil->n_msi);
|
||||
if (rc && (wil->n_msi == 3)) {
|
||||
wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
|
||||
@ -65,7 +65,7 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
||||
wil->n_msi = 0;
|
||||
}
|
||||
} else {
|
||||
wil_dbg(wil, "MSI interrupts disabled, use INTx\n");
|
||||
wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
|
||||
}
|
||||
|
||||
rc = wil6210_init_irq(wil, pdev->irq);
|
||||
|
@ -100,8 +100,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
|
||||
d->dma.status = TX_DMA_STATUS_DU;
|
||||
}
|
||||
|
||||
wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
|
||||
vring->va, (unsigned long long)vring->pa, vring->ctx);
|
||||
wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
|
||||
vring->va, (unsigned long long)vring->pa, vring->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -353,8 +353,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
|
||||
wil_rx_add_radiotap_header(wil, skb, d);
|
||||
|
||||
wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
|
||||
wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
wil_vring_advance_head(vring, 1);
|
||||
@ -369,7 +369,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
*/
|
||||
ftype = wil_rxdesc_ftype(d) << 2;
|
||||
if (ftype != IEEE80211_FTYPE_DATA) {
|
||||
wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
/* TODO: process it */
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
@ -430,6 +430,8 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
||||
int rc;
|
||||
unsigned int len = skb->len;
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (in_interrupt())
|
||||
rc = netif_rx(skb);
|
||||
else
|
||||
@ -459,13 +461,11 @@ void wil_rx_handle(struct wil6210_priv *wil)
|
||||
wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
|
||||
return;
|
||||
}
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
while (NULL != (skb = wil_vring_reap_rx(wil, v))) {
|
||||
wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
skb->dev = ndev;
|
||||
skb_reset_mac_header(skb);
|
||||
@ -484,53 +484,18 @@ void wil_rx_handle(struct wil6210_priv *wil)
|
||||
|
||||
int wil_rx_init(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct vring *vring = &wil->vring_rx;
|
||||
int rc;
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = WMI_RX_CHAIN_ADD,
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
},
|
||||
.mid = 0, /* TODO - what is it? */
|
||||
.decap_trans_type = WMI_DECAP_TYPE_802_3,
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event evt;
|
||||
} __packed evt;
|
||||
|
||||
vring->size = WIL6210_RX_RING_SIZE;
|
||||
rc = wil_vring_alloc(wil, vring);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
||||
cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size);
|
||||
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
struct ieee80211_channel *ch = wdev->preset_chandef.chan;
|
||||
|
||||
cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
|
||||
if (ch)
|
||||
cmd.sniffer_cfg.channel = ch->hw_value - 1;
|
||||
cmd.sniffer_cfg.phy_info_mode =
|
||||
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
|
||||
cmd.sniffer_cfg.phy_support =
|
||||
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
|
||||
? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
|
||||
}
|
||||
/* typical time for secure PCP is 840ms */
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
|
||||
rc = wmi_rx_chain_add(wil, vring);
|
||||
if (rc)
|
||||
goto err_free;
|
||||
|
||||
vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
|
||||
|
||||
wil_dbg(wil, "Rx init: status %d tail 0x%08x\n",
|
||||
le32_to_cpu(evt.evt.status), vring->hwtail);
|
||||
|
||||
rc = wil_rx_refill(wil, vring->size);
|
||||
if (rc)
|
||||
goto err_free;
|
||||
@ -546,25 +511,8 @@ void wil_rx_fini(struct wil6210_priv *wil)
|
||||
{
|
||||
struct vring *vring = &wil->vring_rx;
|
||||
|
||||
if (vring->va) {
|
||||
int rc;
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = cpu_to_le32(WMI_RX_CHAIN_DEL),
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
},
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event cfg;
|
||||
} __packed wmi_rx_cfg_reply;
|
||||
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID,
|
||||
&wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply),
|
||||
100);
|
||||
if (vring->va)
|
||||
wil_vring_free(wil, vring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
||||
@ -617,6 +565,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
||||
if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
|
||||
wil_err(wil, "Tx config failed, status 0x%02x\n",
|
||||
reply.cmd.status);
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
||||
@ -689,7 +638,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
uint i = swhead;
|
||||
dma_addr_t pa;
|
||||
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
|
||||
if (avail < vring->size/8)
|
||||
netif_tx_stop_all_queues(wil_to_ndev(wil));
|
||||
@ -706,9 +655,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
pa = dma_map_single(dev, skb->data,
|
||||
skb_headlen(skb), DMA_TO_DEVICE);
|
||||
|
||||
wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
|
||||
wil_dbg_txrx(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
|
||||
skb->data, (unsigned long long)pa);
|
||||
wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
if (unlikely(dma_mapping_error(dev, pa)))
|
||||
@ -737,12 +686,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
|
||||
d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
|
||||
|
||||
wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
/* advance swhead */
|
||||
wil_vring_advance_head(vring, nr_frags + 1);
|
||||
wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
|
||||
/* hold reference to skb
|
||||
* to prevent skb release before accounting
|
||||
@ -775,7 +724,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
struct vring *vring;
|
||||
int rc;
|
||||
|
||||
wil_dbg_TXRX(wil, "%s()\n", __func__);
|
||||
wil_dbg_txrx(wil, "%s()\n", __func__);
|
||||
if (!test_bit(wil_status_fwready, &wil->status)) {
|
||||
wil_err(wil, "FW not ready\n");
|
||||
goto drop;
|
||||
@ -802,15 +751,13 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
}
|
||||
switch (rc) {
|
||||
case 0:
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
/* statistics will be updated on the tx_complete */
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
case -ENOMEM:
|
||||
return NETDEV_TX_BUSY;
|
||||
default:
|
||||
; /* goto drop; */
|
||||
break;
|
||||
break; /* goto drop; */
|
||||
}
|
||||
drop:
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
@ -827,6 +774,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
*/
|
||||
void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
struct vring *vring = &wil->vring_tx[ringid];
|
||||
|
||||
@ -835,7 +783,7 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
return;
|
||||
}
|
||||
|
||||
wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid);
|
||||
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
||||
|
||||
while (!wil_vring_is_empty(vring)) {
|
||||
volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
|
||||
@ -844,16 +792,23 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
if (!(d->dma.status & TX_DMA_STATUS_DU))
|
||||
break;
|
||||
|
||||
wil_dbg_TXRX(wil,
|
||||
wil_dbg_txrx(wil,
|
||||
"Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
|
||||
vring->swtail, d->dma.length, d->dma.status,
|
||||
d->dma.error);
|
||||
wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4,
|
||||
wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
|
||||
skb = vring->ctx[vring->swtail];
|
||||
if (skb) {
|
||||
if (d->dma.error == 0) {
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
} else {
|
||||
ndev->stats.tx_errors++;
|
||||
}
|
||||
|
||||
dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
vring->ctx[vring->swtail] = NULL;
|
||||
|
@ -36,8 +36,6 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
||||
|
||||
#define WIL6210_MEM_SIZE (2*1024*1024UL)
|
||||
|
||||
#define WIL6210_TX_QUEUES (4)
|
||||
|
||||
#define WIL6210_RX_RING_SIZE (128)
|
||||
#define WIL6210_TX_RING_SIZE (128)
|
||||
#define WIL6210_MAX_TX_RINGS (24)
|
||||
@ -101,8 +99,7 @@ struct RGF_ICR {
|
||||
#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */
|
||||
#define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0)
|
||||
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */
|
||||
|
||||
/* Interrupt moderation control */
|
||||
#define RGF_DMA_ITR_CNT_TRSH (0x881c5c)
|
||||
@ -121,8 +118,9 @@ struct RGF_ICR {
|
||||
#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2
|
||||
|
||||
/* ISR register bits */
|
||||
#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0
|
||||
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1
|
||||
#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT(0)
|
||||
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT(1)
|
||||
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
|
||||
|
||||
/* Hardware definitions end */
|
||||
|
||||
@ -272,17 +270,18 @@ struct wil6210_priv {
|
||||
#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg)
|
||||
#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg)
|
||||
|
||||
#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
|
||||
#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
|
||||
#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
|
||||
#define wil_dbg_irq(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
|
||||
#define wil_dbg_txrx(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
|
||||
#define wil_dbg_wmi(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
|
||||
#define wil_dbg_misc(wil, fmt, arg...) wil_dbg(wil, "DBG[MISC]" fmt, ##arg)
|
||||
|
||||
#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \
|
||||
#define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii)
|
||||
|
||||
#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \
|
||||
#define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
@ -328,6 +327,7 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
|
||||
const void *mac_addr, int key_len, const void *key);
|
||||
int wmi_echo(struct wil6210_priv *wil);
|
||||
int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
|
||||
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq);
|
||||
void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
|
||||
|
@ -18,8 +18,10 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include "wil6210.h"
|
||||
#include "txrx.h"
|
||||
#include "wmi.h"
|
||||
|
||||
/**
|
||||
@ -186,7 +188,6 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
||||
wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
|
||||
(int)(sizeof(cmd) + len), r->entry_size);
|
||||
return -ERANGE;
|
||||
|
||||
}
|
||||
|
||||
might_sleep();
|
||||
@ -213,7 +214,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
||||
}
|
||||
/* next head */
|
||||
next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
|
||||
wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
|
||||
wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
|
||||
/* wait till FW finish with previous command */
|
||||
for (retry = 5; retry > 0; retry--) {
|
||||
r->tail = ioread32(wil->csr + HOST_MBOX +
|
||||
@ -234,10 +235,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
||||
}
|
||||
cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
|
||||
/* set command */
|
||||
wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
|
||||
wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
|
||||
wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
|
||||
wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
|
||||
sizeof(cmd), true);
|
||||
wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
len, true);
|
||||
wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
|
||||
wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
|
||||
@ -273,7 +274,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
struct wmi_ready_event *evt = d;
|
||||
u32 ver = le32_to_cpu(evt->sw_version);
|
||||
|
||||
wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
|
||||
wil_dbg_wmi(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
|
||||
|
||||
if (!is_valid_ether_addr(ndev->dev_addr)) {
|
||||
memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
|
||||
@ -286,7 +287,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
|
||||
int len)
|
||||
{
|
||||
wil_dbg_WMI(wil, "WMI: FW ready\n");
|
||||
wil_dbg_wmi(wil, "WMI: FW ready\n");
|
||||
|
||||
set_bit(wil_status_fwready, &wil->status);
|
||||
/* reuse wmi_ready for the firmware ready indication */
|
||||
@ -309,11 +310,11 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
u32 d_len = le32_to_cpu(data->info.len);
|
||||
u16 d_status = le16_to_cpu(data->info.status);
|
||||
|
||||
wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n",
|
||||
wil_dbg_wmi(wil, "MGMT: channel %d MCS %d SNR %d\n",
|
||||
data->info.channel, data->info.mcs, data->info.snr);
|
||||
wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
|
||||
wil_dbg_wmi(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
|
||||
le16_to_cpu(data->info.stype));
|
||||
wil_dbg_WMI(wil, "qid %d mid %d cid %d\n",
|
||||
wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
|
||||
data->info.qid, data->info.mid, data->info.cid);
|
||||
|
||||
if (!channel) {
|
||||
@ -329,13 +330,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
|
||||
size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
|
||||
u.beacon.variable);
|
||||
wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap);
|
||||
wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
|
||||
|
||||
bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
|
||||
tsf, cap, bi, ie_buf, ie_len,
|
||||
signal, GFP_KERNEL);
|
||||
if (bss) {
|
||||
wil_dbg_WMI(wil, "Added BSS %pM\n",
|
||||
wil_dbg_wmi(wil, "Added BSS %pM\n",
|
||||
rx_mgmt_frame->bssid);
|
||||
cfg80211_put_bss(bss);
|
||||
} else {
|
||||
@ -351,7 +352,7 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
|
||||
struct wmi_scan_complete_event *data = d;
|
||||
bool aborted = (data->status != 0);
|
||||
|
||||
wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
|
||||
wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
|
||||
cfg80211_scan_done(wil->scan_request, aborted);
|
||||
wil->scan_request = NULL;
|
||||
} else {
|
||||
@ -386,9 +387,9 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
return;
|
||||
}
|
||||
ch = evt->channel + 1;
|
||||
wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n",
|
||||
wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n",
|
||||
evt->bssid, ch, evt->cid);
|
||||
wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
evt->assoc_info, len - sizeof(*evt), true);
|
||||
|
||||
/* figure out IE's */
|
||||
@ -450,14 +451,13 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
|
||||
{
|
||||
struct wmi_disconnect_event *evt = d;
|
||||
|
||||
wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n",
|
||||
wil_dbg_wmi(wil, "Disconnect %pM reason %d proto %d wmi\n",
|
||||
evt->bssid,
|
||||
evt->protocol_reason_status, evt->disconnect_reason);
|
||||
|
||||
wil->sinfo_gen++;
|
||||
|
||||
wil6210_disconnect(wil, evt->bssid);
|
||||
clear_bit(wil_status_dontscan, &wil->status);
|
||||
}
|
||||
|
||||
static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
@ -476,7 +476,7 @@ static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector);
|
||||
wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector);
|
||||
wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector);
|
||||
wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n"
|
||||
wil_dbg_wmi(wil, "Link status, MCS %d TSF 0x%016llx\n"
|
||||
"BF status 0x%08x SNR 0x%08x\n"
|
||||
"Tx Tpt %d goodput %d Rx goodput %d\n"
|
||||
"Sectors(rx:tx) my %d:%d peer %d:%d\n",
|
||||
@ -501,7 +501,7 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
|
||||
struct sk_buff *skb;
|
||||
struct ethhdr *eth;
|
||||
|
||||
wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len,
|
||||
wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
|
||||
evt->src_mac);
|
||||
|
||||
if (eapol_len > 196) { /* TODO: revisit size limit */
|
||||
@ -599,15 +599,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
|
||||
iowrite32(0, wil->csr + HOSTADDR(r->tail) +
|
||||
offsetof(struct wil6210_mbox_ring_desc, sync));
|
||||
/* indicate */
|
||||
wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n",
|
||||
wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
|
||||
le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
|
||||
hdr.flags);
|
||||
if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
|
||||
(len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
|
||||
wil_dbg_WMI(wil, "WMI event 0x%04x\n",
|
||||
wil_dbg_wmi(wil, "WMI event 0x%04x\n",
|
||||
evt->event.wmi.id);
|
||||
}
|
||||
wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
&evt->event.hdr, sizeof(hdr) + len, true);
|
||||
|
||||
/* advance tail */
|
||||
@ -623,7 +623,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
|
||||
{
|
||||
int q = queue_work(wil->wmi_wq,
|
||||
&wil->wmi_event_worker);
|
||||
wil_dbg_WMI(wil, "queue_work -> %d\n", q);
|
||||
wil_dbg_wmi(wil, "queue_work -> %d\n", q);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,7 +650,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
|
||||
cmdid, reply_id, to_msec);
|
||||
rc = -ETIME;
|
||||
} else {
|
||||
wil_dbg_WMI(wil,
|
||||
wil_dbg_wmi(wil,
|
||||
"wmi_call(0x%04x->0x%04x) completed in %d msec\n",
|
||||
cmdid, reply_id,
|
||||
to_msec - jiffies_to_msecs(remain));
|
||||
@ -680,7 +680,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
|
||||
|
||||
memcpy(cmd.mac, addr, ETH_ALEN);
|
||||
|
||||
wil_dbg_WMI(wil, "Set MAC %pM\n", addr);
|
||||
wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
|
||||
|
||||
return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
|
||||
}
|
||||
@ -778,7 +778,7 @@ int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
|
||||
|
||||
skb_set_mac_header(skb, 0);
|
||||
eth = eth_hdr(skb);
|
||||
wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
|
||||
wil_dbg_wmi(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
|
||||
if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0)
|
||||
goto found_dest;
|
||||
@ -853,11 +853,60 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
|
||||
{
|
||||
struct wireless_dev *wdev = wil->wdev;
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wmi_cfg_rx_chain_cmd cmd = {
|
||||
.action = WMI_RX_CHAIN_ADD,
|
||||
.rx_sw_ring = {
|
||||
.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
|
||||
.ring_mem_base = cpu_to_le64(vring->pa),
|
||||
.ring_size = cpu_to_le16(vring->size),
|
||||
},
|
||||
.mid = 0, /* TODO - what is it? */
|
||||
.decap_trans_type = WMI_DECAP_TYPE_802_3,
|
||||
};
|
||||
struct {
|
||||
struct wil6210_mbox_hdr_wmi wmi;
|
||||
struct wmi_cfg_rx_chain_done_event evt;
|
||||
} __packed evt;
|
||||
int rc;
|
||||
|
||||
if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
struct ieee80211_channel *ch = wdev->preset_chandef.chan;
|
||||
|
||||
cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
|
||||
if (ch)
|
||||
cmd.sniffer_cfg.channel = ch->hw_value - 1;
|
||||
cmd.sniffer_cfg.phy_info_mode =
|
||||
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
|
||||
cmd.sniffer_cfg.phy_support =
|
||||
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
|
||||
? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
|
||||
}
|
||||
/* typical time for secure PCP is 840ms */
|
||||
rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
|
||||
|
||||
wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
|
||||
le32_to_cpu(evt.evt.status), vring->hwtail);
|
||||
|
||||
if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
|
||||
rc = -EINVAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wmi_event_flush(struct wil6210_priv *wil)
|
||||
{
|
||||
struct pending_wmi_event *evt, *t;
|
||||
|
||||
wil_dbg_WMI(wil, "%s()\n", __func__);
|
||||
wil_dbg_wmi(wil, "%s()\n", __func__);
|
||||
|
||||
list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
|
||||
list_del(&evt->list);
|
||||
@ -899,7 +948,7 @@ static void wmi_event_handle(struct wil6210_priv *wil,
|
||||
wmi_evt_call_handler(wil, id, evt_data,
|
||||
len - sizeof(*wmi));
|
||||
}
|
||||
wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id);
|
||||
wil_dbg_wmi(wil, "Complete WMI 0x%04x\n", id);
|
||||
complete(&wil->wmi_ready);
|
||||
return;
|
||||
}
|
||||
@ -964,7 +1013,7 @@ void wmi_connect_worker(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
wil_dbg_WMI(wil, "Configure for connection CID %d\n",
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d\n",
|
||||
wil->pending_connect_cid);
|
||||
|
||||
rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
|
||||
|
@ -26,6 +26,7 @@ brcmfmac-objs += \
|
||||
wl_cfg80211.o \
|
||||
fwil.o \
|
||||
fweh.o \
|
||||
p2p.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
@ -37,4 +38,4 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
|
||||
usb.o
|
||||
brcmfmac-$(CONFIG_BRCMDBG) += \
|
||||
dhd_dbg.o
|
||||
dhd_dbg.o
|
||||
|
@ -72,6 +72,7 @@
|
||||
#define BRCMF_C_SET_WSEC 134
|
||||
#define BRCMF_C_GET_PHY_NOISE 135
|
||||
#define BRCMF_C_GET_BSS_INFO 136
|
||||
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
||||
#define BRCMF_C_GET_PHYLIST 180
|
||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
@ -149,6 +150,7 @@
|
||||
#define BRCMF_E_REASON_MINTXRATE 9
|
||||
#define BRCMF_E_REASON_TXFAIL 10
|
||||
|
||||
#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4
|
||||
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
|
||||
#define BRCMF_E_REASON_DIRECTED_ROAM 6
|
||||
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
||||
@ -375,6 +377,28 @@ struct brcmf_join_params {
|
||||
struct brcmf_assoc_params_le params_le;
|
||||
};
|
||||
|
||||
/* scan params for extended join */
|
||||
struct brcmf_join_scan_params_le {
|
||||
u8 scan_type; /* 0 use default, active or passive scan */
|
||||
__le32 nprobes; /* -1 use default, nr of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the home
|
||||
* channel between channel scans
|
||||
*/
|
||||
};
|
||||
|
||||
/* extended join params */
|
||||
struct brcmf_ext_join_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */
|
||||
struct brcmf_join_scan_params_le scan_le;
|
||||
struct brcmf_assoc_params_le assoc_le;
|
||||
};
|
||||
|
||||
struct brcmf_wsec_key {
|
||||
u32 index; /* key index */
|
||||
u32 len; /* key length */
|
||||
@ -451,6 +475,19 @@ struct brcmf_sta_info_le {
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
};
|
||||
|
||||
/*
|
||||
* WLC_E_PROBRESP_MSG
|
||||
* WLC_E_P2P_PROBREQ_MSG
|
||||
* WLC_E_ACTION_FRAME_RX
|
||||
*/
|
||||
struct brcmf_rx_mgmt_data {
|
||||
__be16 version;
|
||||
__be16 chanspec;
|
||||
__be32 rssi;
|
||||
__be32 mactime;
|
||||
__be32 rate;
|
||||
};
|
||||
|
||||
/* Bus independent dongle command */
|
||||
struct brcmf_dcmd {
|
||||
uint cmd; /* common dongle cmd definition */
|
||||
@ -489,9 +526,6 @@ struct brcmf_pub {
|
||||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
|
||||
struct brcmf_fweh_info fweh;
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
@ -515,9 +549,11 @@ struct brcmf_cfg80211_vif;
|
||||
* @vif: points to cfg80211 specific interface information.
|
||||
* @ndev: associated network device.
|
||||
* @stats: interface specific network statistics.
|
||||
* @idx: interface index in device firmware.
|
||||
* @ifidx: interface index in device firmware.
|
||||
* @bssidx: index of bss associated with this interface.
|
||||
* @mac_addr: assigned mac address.
|
||||
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
|
||||
* @pend_8021x_wait: used for signalling change in count.
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
@ -526,9 +562,11 @@ struct brcmf_if {
|
||||
struct net_device_stats stats;
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
int idx;
|
||||
int ifidx;
|
||||
s32 bssidx;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
};
|
||||
|
||||
|
||||
@ -547,9 +585,10 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
struct sk_buff *rxp);
|
||||
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
|
||||
s32 bssidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
|
||||
s32 ifidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
|
||||
extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
|
||||
|
||||
#endif /* _BRCMF_H_ */
|
||||
|
@ -24,18 +24,6 @@ enum brcmf_bus_state {
|
||||
BRCMF_BUS_DATA /* Ready for frame transfers */
|
||||
};
|
||||
|
||||
struct dngl_stats {
|
||||
unsigned long rx_packets; /* total packets received */
|
||||
unsigned long tx_packets; /* total packets transmitted */
|
||||
unsigned long rx_bytes; /* total bytes received */
|
||||
unsigned long tx_bytes; /* total bytes transmitted */
|
||||
unsigned long rx_errors; /* bad packets received */
|
||||
unsigned long tx_errors; /* packet transmit problems */
|
||||
unsigned long rx_dropped; /* packets dropped by dongle */
|
||||
unsigned long tx_dropped; /* packets dropped by dongle */
|
||||
unsigned long multicast; /* multicast packets received */
|
||||
};
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
char *name;
|
||||
char *param;
|
||||
@ -72,11 +60,12 @@ struct brcmf_bus_ops {
|
||||
* @drvr: public driver information.
|
||||
* @state: operational state of the bus interface.
|
||||
* @maxctl: maximum size for rxctl request message.
|
||||
* @drvr_up: indicates driver up/down status.
|
||||
* @tx_realloc: number of tx packets realloced for headroom.
|
||||
* @dstats: dongle-based statistical data.
|
||||
* @align: alignment requirement for the bus.
|
||||
* @dcmd_list: bus/device specific dongle initialization commands.
|
||||
* @chip: device identifier of the dongle chip.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
*/
|
||||
struct brcmf_bus {
|
||||
union {
|
||||
@ -87,10 +76,10 @@ struct brcmf_bus {
|
||||
struct brcmf_pub *drvr;
|
||||
enum brcmf_bus_state state;
|
||||
uint maxctl;
|
||||
bool drvr_up;
|
||||
unsigned long tx_realloc;
|
||||
struct dngl_stats dstats;
|
||||
u8 align;
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
struct list_head dcmd_list;
|
||||
|
||||
struct brcmf_bus_ops *ops;
|
||||
|
@ -303,6 +303,14 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
|
||||
return -EBADE;
|
||||
}
|
||||
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
* events this is easy because it contains the bssidx which maps
|
||||
* 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
* bssidx 1 is used for p2p0 and no data can be received or
|
||||
* transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
*/
|
||||
if (*ifidx)
|
||||
(*ifidx)++;
|
||||
|
||||
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
|
||||
BDC_PROTO_VER) {
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_proto.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "fwil.h"
|
||||
|
||||
@ -40,6 +42,12 @@ MODULE_LICENSE("Dual BSD/GPL");
|
||||
int brcmf_msg_level;
|
||||
module_param(brcmf_msg_level, int, 0);
|
||||
|
||||
/* P2P0 enable */
|
||||
static int brcmf_p2p_enable;
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
|
||||
MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
|
||||
#endif
|
||||
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
|
||||
{
|
||||
@ -70,9 +78,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
u32 buflen;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, multicast_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* Determine initial value of allmulti flag */
|
||||
@ -129,9 +138,10 @@ _brcmf_set_mac_address(struct work_struct *work)
|
||||
struct brcmf_if *ifp;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, setmacaddr_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
ETH_ALEN);
|
||||
if (err < 0) {
|
||||
@ -168,7 +178,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethhdr *eh;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* Can the device send data? */
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
@ -179,8 +189,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!drvr->iflist[ifp->idx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->idx);
|
||||
if (!drvr->iflist[ifp->bssidx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->bssidx);
|
||||
netif_stop_queue(ndev);
|
||||
dev_kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
@ -192,14 +202,14 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct sk_buff *skb2;
|
||||
|
||||
brcmf_dbg(INFO, "%s: insufficient headroom\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
drvr->bus_if->tx_realloc++;
|
||||
skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
|
||||
dev_kfree_skb(skb);
|
||||
skb = skb2;
|
||||
if (skb == NULL) {
|
||||
brcmf_err("%s: skb_realloc_headroom failed\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
@ -217,19 +227,21 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
if (is_multicast_ether_addr(eh->h_dest))
|
||||
drvr->tx_multicast++;
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&drvr->pend_8021x_cnt);
|
||||
atomic_inc(&ifp->pend_8021x_cnt);
|
||||
|
||||
/* If the protocol uses a data header, apply it */
|
||||
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
|
||||
brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
|
||||
|
||||
/* Use bus module to send data frame */
|
||||
ret = brcmf_bus_txdata(drvr->bus_if, skb);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
drvr->bus_if->dstats.tx_dropped++;
|
||||
else
|
||||
drvr->bus_if->dstats.tx_packets++;
|
||||
if (ret) {
|
||||
ifp->stats.tx_dropped++;
|
||||
} else {
|
||||
ifp->stats.tx_packets++;
|
||||
ifp->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
/* Return ok: we always eat the packet */
|
||||
return NETDEV_TX_OK;
|
||||
@ -270,12 +282,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
skb_queue_walk_safe(skb_list, skb, pnext) {
|
||||
skb_unlink(skb, skb_list);
|
||||
|
||||
/* process and remove protocol-specific header
|
||||
*/
|
||||
/* process and remove protocol-specific header */
|
||||
ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENODATA)
|
||||
bus_if->dstats.rx_errors++;
|
||||
ifp = drvr->iflist[ifidx];
|
||||
|
||||
if (ret || !ifp || !ifp->ndev) {
|
||||
if ((ret != -ENODATA) && ifp)
|
||||
ifp->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
@ -295,21 +308,11 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
eth = skb->data;
|
||||
len = skb->len;
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (ifp == NULL)
|
||||
ifp = drvr->iflist[0];
|
||||
|
||||
if (!ifp || !ifp->ndev ||
|
||||
ifp->ndev->reg_state != NETREG_REGISTERED) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb->dev = ifp->ndev;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
bus_if->dstats.multicast++;
|
||||
ifp->stats.multicast++;
|
||||
|
||||
skb->data = eth;
|
||||
skb->len = len;
|
||||
@ -325,8 +328,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
ifp->ndev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
bus_if->dstats.rx_bytes += skb->len;
|
||||
bus_if->dstats.rx_packets++; /* Local count */
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
ifp->stats.rx_bytes += skb->len;
|
||||
ifp->stats.rx_packets++;
|
||||
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
@ -348,36 +356,31 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
|
||||
u16 type;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_proto_hdrpull(drvr, &ifidx, txp);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (!ifp)
|
||||
return;
|
||||
|
||||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
|
||||
if (type == ETH_P_PAE) {
|
||||
atomic_dec(&drvr->pend_8021x_cnt);
|
||||
if (waitqueue_active(&drvr->pend_8021x_wait))
|
||||
wake_up(&drvr->pend_8021x_wait);
|
||||
atomic_dec(&ifp->pend_8021x_cnt);
|
||||
if (waitqueue_active(&ifp->pend_8021x_wait))
|
||||
wake_up(&ifp->pend_8021x_wait);
|
||||
}
|
||||
if (!success)
|
||||
ifp->stats.tx_errors++;
|
||||
}
|
||||
|
||||
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_bus *bus_if = ifp->drvr->bus_if;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Copy dongle stats to net device stats */
|
||||
ifp->stats.rx_packets = bus_if->dstats.rx_packets;
|
||||
ifp->stats.tx_packets = bus_if->dstats.tx_packets;
|
||||
ifp->stats.rx_bytes = bus_if->dstats.rx_bytes;
|
||||
ifp->stats.tx_bytes = bus_if->dstats.tx_bytes;
|
||||
ifp->stats.rx_errors = bus_if->dstats.rx_errors;
|
||||
ifp->stats.tx_errors = bus_if->dstats.tx_errors;
|
||||
ifp->stats.rx_dropped = bus_if->dstats.rx_dropped;
|
||||
ifp->stats.tx_dropped = bus_if->dstats.tx_dropped;
|
||||
ifp->stats.multicast = bus_if->dstats.multicast;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
return &ifp->stats;
|
||||
}
|
||||
@ -429,7 +432,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
u32 toe_cmpnt, csum_dir;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* all ethtool calls start with a cmd word */
|
||||
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
|
||||
@ -452,13 +455,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
sprintf(info.driver, "dhd");
|
||||
strcpy(info.version, BRCMF_VERSION_STR);
|
||||
}
|
||||
|
||||
/* otherwise, require dongle to be up */
|
||||
else if (!drvr->bus_if->drvr_up) {
|
||||
brcmf_err("dongle is not up\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* finally, report dongle driver type */
|
||||
/* report dongle driver type */
|
||||
else
|
||||
sprintf(info.driver, "wl");
|
||||
|
||||
@ -532,9 +529,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
|
||||
|
||||
if (!drvr->iflist[ifp->idx])
|
||||
if (!drvr->iflist[ifp->bssidx])
|
||||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
@ -546,17 +543,12 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||
static int brcmf_netdev_stop(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (drvr->bus_if->drvr_up == 0)
|
||||
return 0;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
brcmf_cfg80211_down(ndev);
|
||||
|
||||
/* Set state and stop OS transmissions */
|
||||
drvr->bus_if->drvr_up = false;
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
return 0;
|
||||
@ -570,7 +562,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
u32 toe_ol;
|
||||
s32 ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* If bus is not ready, can't continue */
|
||||
if (bus_if->state != BRCMF_BUS_DATA) {
|
||||
@ -578,9 +570,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
atomic_set(&drvr->pend_8021x_cnt, 0);
|
||||
|
||||
memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
|
||||
atomic_set(&ifp->pend_8021x_cnt, 0);
|
||||
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
|
||||
@ -591,7 +581,6 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
|
||||
/* Allow transmit calls */
|
||||
netif_start_queue(ndev);
|
||||
drvr->bus_if->drvr_up = true;
|
||||
if (brcmf_cfg80211_up(ndev)) {
|
||||
brcmf_err("failed to bring up cfg80211\n");
|
||||
return -1;
|
||||
@ -610,29 +599,18 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_virt = {
|
||||
.ndo_open = brcmf_cfg80211_up,
|
||||
.ndo_stop = brcmf_cfg80211_down,
|
||||
.ndo_get_stats = brcmf_netdev_get_stats,
|
||||
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
|
||||
.ndo_start_xmit = brcmf_netdev_start_xmit,
|
||||
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct net_device *ndev;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* set appropriate operations */
|
||||
if (!ifp->idx)
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
else
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_virt;
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
|
||||
ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
|
||||
ndev->ethtool_ops = &brcmf_ethtool_ops;
|
||||
@ -643,7 +621,14 @@ int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (rtnl_locked)
|
||||
err = register_netdevice(ndev);
|
||||
else
|
||||
err = register_netdev(ndev);
|
||||
if (err != 0) {
|
||||
brcmf_err("couldn't register the net device\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -657,16 +642,78 @@ fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
char *name, u8 *addr_mask)
|
||||
static int brcmf_net_p2p_open(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_up(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_stop(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_down(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
|
||||
struct ifreq *ifr, int cmd)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_p2p = {
|
||||
.ndo_open = brcmf_net_p2p_open,
|
||||
.ndo_stop = brcmf_net_p2p_stop,
|
||||
.ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
|
||||
.ndo_start_xmit = brcmf_net_p2p_start_xmit
|
||||
};
|
||||
|
||||
static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_p2p;
|
||||
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
brcmf_err("couldn't register the p2p net device\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
int i;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
@ -678,7 +725,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
} else {
|
||||
brcmf_err("ignore IF event\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
@ -695,16 +742,15 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
ifp->drvr = drvr;
|
||||
drvr->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
drvr->iflist[bssidx] = ifp;
|
||||
ifp->ifidx = ifidx;
|
||||
ifp->bssidx = bssidx;
|
||||
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (addr_mask != NULL)
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
|
||||
init_waitqueue_head(&ifp->pend_8021x_wait);
|
||||
|
||||
if (mac_addr != NULL)
|
||||
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
||||
current->pid, ifp->ndev->name, ifp->mac_addr);
|
||||
@ -712,19 +758,18 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
return ifp;
|
||||
}
|
||||
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface\n");
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
return;
|
||||
}
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
|
||||
if (ifp->ndev) {
|
||||
if (ifidx == 0) {
|
||||
if (bssidx == 0) {
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
rtnl_lock();
|
||||
brcmf_netdev_stop(ifp->ndev);
|
||||
@ -734,12 +779,14 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||
netif_stop_queue(ifp->ndev);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
unregister_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
if (ifidx == 0)
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (bssidx == 0)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(ifp->ndev);
|
||||
}
|
||||
@ -779,8 +826,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||
|
||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
||||
|
||||
init_waitqueue_head(&drvr->pend_8021x_wait);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
@ -795,6 +840,7 @@ int brcmf_bus_start(struct device *dev)
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
@ -810,6 +856,13 @@ int brcmf_bus_start(struct device *dev)
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
if (brcmf_p2p_enable)
|
||||
p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
|
||||
else
|
||||
p2p_ifp = NULL;
|
||||
if (IS_ERR(p2p_ifp))
|
||||
p2p_ifp = NULL;
|
||||
|
||||
/* signal bus ready */
|
||||
bus_if->state = BRCMF_BUS_DATA;
|
||||
|
||||
@ -828,16 +881,22 @@ int brcmf_bus_start(struct device *dev)
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = brcmf_net_attach(ifp);
|
||||
ret = brcmf_net_attach(ifp, false);
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
brcmf_err("failed: %d\n", ret);
|
||||
if (drvr->config)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(drvr->iflist[0]->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
if (p2p_ifp) {
|
||||
free_netdev(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if ((brcmf_p2p_enable) && (p2p_ifp))
|
||||
brcmf_net_p2p_attach(p2p_ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -863,12 +922,13 @@ void brcmf_dev_reset(struct device *dev)
|
||||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
if (drvr->iflist[0])
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
}
|
||||
|
||||
void brcmf_detach(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
s32 i;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
@ -895,19 +955,18 @@ void brcmf_detach(struct device *dev)
|
||||
kfree(drvr);
|
||||
}
|
||||
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
|
||||
{
|
||||
return atomic_read(&drvr->pend_8021x_cnt);
|
||||
return atomic_read(&ifp->pend_8021x_cnt);
|
||||
}
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
int err;
|
||||
|
||||
err = wait_event_timeout(drvr->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(drvr),
|
||||
err = wait_event_timeout(ifp->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(ifp),
|
||||
msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
|
||||
|
||||
WARN_ON(!err);
|
||||
@ -915,6 +974,16 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
return !err;
|
||||
}
|
||||
|
||||
/*
|
||||
* return chip id and rev of the device encoded in u32.
|
||||
*/
|
||||
u32 brcmf_get_chip_info(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_bus *bus = ifp->drvr->bus_if;
|
||||
|
||||
return bus->chip << 4 | bus->chiprev;
|
||||
}
|
||||
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
{
|
||||
brcmf_debugfs_init();
|
||||
|
@ -1096,7 +1096,6 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
|
||||
type != BRCMF_SDIO_FT_SUPER) {
|
||||
brcmf_err("HW header length too long\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
rd->len = 0;
|
||||
@ -1298,7 +1297,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
if (errcode < 0) {
|
||||
brcmf_err("glom read of %d bytes failed: %d\n",
|
||||
dlen, errcode);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (bus->glomerr++ < 3) {
|
||||
@ -1478,7 +1476,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
||||
if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
|
||||
rdlen, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
}
|
||||
@ -1486,7 +1483,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
||||
if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
|
||||
len, len - doff, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
@ -1634,7 +1630,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
if (!pkt) {
|
||||
/* Give up on data, request rtx of events */
|
||||
brcmf_err("brcmu_pkt_buf_get_skb failed\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_dropped++;
|
||||
brcmf_sdbrcm_rxfail(bus, false,
|
||||
RETRYCHAN(rd->channel));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
@ -1652,7 +1647,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
brcmf_err("read %d bytes from channel %d failed: %d\n",
|
||||
rd->len, rd->channel, sdret);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, true,
|
||||
RETRYCHAN(rd->channel));
|
||||
@ -1940,10 +1934,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
||||
datalen = pkt->len - SDPCM_HDRLEN;
|
||||
|
||||
ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
|
||||
if (ret)
|
||||
bus->sdiodev->bus_if->dstats.tx_errors++;
|
||||
else
|
||||
bus->sdiodev->bus_if->dstats.tx_bytes += datalen;
|
||||
|
||||
/* In poll mode, need to check for other events */
|
||||
if (!bus->intr && cnt) {
|
||||
@ -1962,8 +1952,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
||||
}
|
||||
|
||||
/* Deflow-control stack if needed */
|
||||
if (bus->sdiodev->bus_if->drvr_up &&
|
||||
(bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
|
||||
bus->txoff = false;
|
||||
brcmf_txflowblock(bus->sdiodev->dev, false);
|
||||
@ -2710,9 +2699,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
* address of sdpcm_shared structure
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
||||
(u8 *)&addr_le, 4);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2731,10 +2721,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
}
|
||||
|
||||
/* Read hndrte_shared structure */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2836,14 +2824,12 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
||||
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
@ -3308,9 +3294,6 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bus->sdiodev->bus_if->drvr_up)
|
||||
return -EISCONN;
|
||||
|
||||
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
|
||||
&bus->sdiodev->func[2]->dev);
|
||||
if (ret) {
|
||||
@ -3941,6 +3924,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
||||
/* Assign bus interface call back */
|
||||
bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
|
||||
bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
|
||||
bus->sdiodev->bus_if->chip = bus->ci->chip;
|
||||
bus->sdiodev->bus_if->chiprev = bus->ci->chiprev;
|
||||
|
||||
/* Attach to the brcmf/OS/network interface */
|
||||
ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
|
||||
|
@ -189,24 +189,24 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->ifidx];
|
||||
ifp = drvr->iflist[ifevent->bssidx];
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
||||
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
|
||||
emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
err = brcmf_net_attach(ifp);
|
||||
err = brcmf_net_attach(ifp, false);
|
||||
}
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_DEL)
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
brcmf_del_if(drvr, ifevent->bssidx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,8 +250,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
drvr = container_of(fweh, struct brcmf_pub, fweh);
|
||||
|
||||
while ((event = brcmf_fweh_dequeue_event(fweh))) {
|
||||
ifp = drvr->iflist[event->ifidx];
|
||||
|
||||
brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
|
||||
brcmf_fweh_event_name(event->code), event->code,
|
||||
event->emsg.ifidx, event->emsg.bsscfgidx,
|
||||
@ -283,6 +281,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
goto event_free;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[emsg.bsscfgidx];
|
||||
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||
event->data);
|
||||
if (err) {
|
||||
|
@ -83,6 +83,7 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
|
||||
BRCMF_ENUM_DEF(TRACE, 52) \
|
||||
BRCMF_ENUM_DEF(IF, 54) \
|
||||
BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
|
||||
BRCMF_ENUM_DEF(RSSI, 56) \
|
||||
BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
|
||||
BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
|
||||
@ -96,8 +97,11 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
|
||||
BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
|
||||
BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
|
||||
BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
|
||||
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74)
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75)
|
||||
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
BRCMF_E_##id = (val),
|
||||
|
@ -45,9 +45,10 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
||||
if (data != NULL)
|
||||
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
|
||||
if (set)
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
else
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
|
||||
if (err >= 0)
|
||||
@ -100,6 +101,7 @@ brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
|
||||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
@ -116,6 +118,7 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
*data = le32_to_cpu(data_le);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
66
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
66
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWIL_TYPES_H_
|
||||
#define FWIL_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
||||
|
||||
|
||||
enum brcmf_fil_p2p_if_types {
|
||||
BRCMF_FIL_P2P_IF_CLIENT,
|
||||
BRCMF_FIL_P2P_IF_GO,
|
||||
BRCMF_FIL_P2P_IF_DYNBCN_GO,
|
||||
BRCMF_FIL_P2P_IF_DEV,
|
||||
};
|
||||
|
||||
struct brcmf_fil_p2p_if_le {
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 type;
|
||||
__le16 chspec;
|
||||
};
|
||||
|
||||
struct brcmf_fil_chan_info_le {
|
||||
__le32 hw_channel;
|
||||
__le32 target_channel;
|
||||
__le32 scan_channel;
|
||||
};
|
||||
|
||||
struct brcmf_fil_action_frame_le {
|
||||
u8 da[ETH_ALEN];
|
||||
__le16 len;
|
||||
__le32 packet_id;
|
||||
u8 data[BRCMF_FIL_ACTION_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct brcmf_fil_af_params_le {
|
||||
__le32 channel;
|
||||
__le32 dwell_time;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
struct brcmf_fil_action_frame_le action_frame;
|
||||
};
|
||||
|
||||
struct brcmf_fil_bss_enable_le {
|
||||
__le32 bsscfg_idx;
|
||||
__le32 enable;
|
||||
};
|
||||
|
||||
#endif /* FWIL_TYPES_H_ */
|
2277
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
2277
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
File diff suppressed because it is too large
Load Diff
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef WL_CFGP2P_H_
|
||||
#define WL_CFGP2P_H_
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
struct brcmf_cfg80211_info;
|
||||
|
||||
/**
|
||||
* enum p2p_bss_type - different type of BSS configurations.
|
||||
*
|
||||
* @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg.
|
||||
* @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg.
|
||||
* @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg.
|
||||
* @P2PAPI_BSSCFG_MAX: used for range checking.
|
||||
*/
|
||||
enum p2p_bss_type {
|
||||
P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
|
||||
P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
|
||||
P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
|
||||
P2PAPI_BSSCFG_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_bss - peer-to-peer bss related information.
|
||||
*
|
||||
* @vif: virtual interface of this P2P bss.
|
||||
* @private_data: TBD
|
||||
*/
|
||||
struct p2p_bss {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_p2p_status - P2P specific dongle status.
|
||||
*
|
||||
* @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_DEL: NOT-USED?
|
||||
* @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
||||
* @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
|
||||
* @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
|
||||
* @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response.
|
||||
* @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active.
|
||||
*/
|
||||
enum brcmf_p2p_status {
|
||||
BRCMF_P2P_STATUS_ENABLED,
|
||||
BRCMF_P2P_STATUS_IF_ADD,
|
||||
BRCMF_P2P_STATUS_IF_DEL,
|
||||
BRCMF_P2P_STATUS_IF_DELETING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
||||
BRCMF_P2P_STATUS_GO_NEG_PHASE,
|
||||
BRCMF_P2P_STATUS_DISCOVER_LISTEN,
|
||||
BRCMF_P2P_STATUS_SENDING_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL
|
||||
};
|
||||
|
||||
/**
|
||||
* struct afx_hdl - action frame off channel storage.
|
||||
*
|
||||
* @afx_work: worker thread for searching channel
|
||||
* @act_frm_scan: thread synchronizing struct.
|
||||
* @is_active: channel searching active.
|
||||
* @peer_chan: current channel.
|
||||
* @is_listen: sets mode for afx worker.
|
||||
* @my_listen_chan: this peers listen channel.
|
||||
* @peer_listen_chan: remote peers listen channel.
|
||||
* @tx_dst_addr: mac address where tx af should be sent to.
|
||||
*/
|
||||
struct afx_hdl {
|
||||
struct work_struct afx_work;
|
||||
struct completion act_frm_scan;
|
||||
bool is_active;
|
||||
s32 peer_chan;
|
||||
bool is_listen;
|
||||
u16 my_listen_chan;
|
||||
u16 peer_listen_chan;
|
||||
u8 tx_dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_p2p_info - p2p specific driver information.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
* @status: status of P2P (see enum brcmf_p2p_status).
|
||||
* @dev_addr: P2P device address.
|
||||
* @int_addr: P2P interface address.
|
||||
* @bss_idx: informate for P2P bss types.
|
||||
* @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @ssid: ssid for P2P GO.
|
||||
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @remain_on_channel: contains copy of struct used by cfg80211.
|
||||
* @remain_on_channel_cookie: cookie counter for remain on channel cmd
|
||||
* @next_af_subtype: expected action frame subtype.
|
||||
* @send_af_done: indication that action frame tx is complete.
|
||||
* @afx_hdl: action frame search handler info.
|
||||
* @af_sent_channel: channel action frame is sent.
|
||||
* @af_tx_sent_jiffies: jiffies time when af tx was transmitted.
|
||||
* @wait_next_af: thread synchronizing struct.
|
||||
* @gon_req_action: about to send go negotiation requets frame.
|
||||
* @block_gon_req_tx: drop tx go negotiation requets frame.
|
||||
*/
|
||||
struct brcmf_p2p_info {
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
unsigned long status;
|
||||
u8 dev_addr[ETH_ALEN];
|
||||
u8 int_addr[ETH_ALEN];
|
||||
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
|
||||
struct timer_list listen_timer;
|
||||
struct brcmf_ssid ssid;
|
||||
u8 listen_channel;
|
||||
struct ieee80211_channel remain_on_channel;
|
||||
u32 remain_on_channel_cookie;
|
||||
u8 next_af_subtype;
|
||||
struct completion send_af_done;
|
||||
struct afx_hdl afx_hdl;
|
||||
u32 af_sent_channel;
|
||||
unsigned long af_tx_sent_jiffies;
|
||||
struct completion wait_next_af;
|
||||
bool gon_req_action;
|
||||
bool block_gon_req_tx;
|
||||
};
|
||||
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
|
||||
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
||||
enum nl80211_iftype type, u32 *flags,
|
||||
struct vif_params *params);
|
||||
int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
|
||||
enum brcmf_fil_p2p_if_types if_type);
|
||||
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
||||
struct cfg80211_scan_request *request,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie);
|
||||
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
|
||||
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct brcmf_fil_af_params_le *af_params);
|
||||
bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi);
|
||||
s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
#endif /* WL_CFGP2P_H_ */
|
@ -421,10 +421,6 @@ static void brcmf_usb_tx_complete(struct urb *urb)
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
|
||||
req->skb);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
if (urb->status == 0)
|
||||
devinfo->bus_pub.bus->dstats.tx_packets++;
|
||||
else
|
||||
devinfo->bus_pub.bus->dstats.tx_errors++;
|
||||
|
||||
brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
|
||||
|
||||
@ -451,10 +447,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
||||
req->skb = NULL;
|
||||
|
||||
/* zero lenght packets indicate usb "failure". Do not refill */
|
||||
if (urb->status == 0 && urb->actual_length) {
|
||||
devinfo->bus_pub.bus->dstats.rx_packets++;
|
||||
} else {
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
if (urb->status != 0 || !urb->actual_length) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
|
||||
return;
|
||||
@ -1257,6 +1250,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
||||
bus->bus_priv.usb = bus_pub;
|
||||
dev_set_drvdata(dev, bus);
|
||||
bus->ops = &brcmf_usb_bus_ops;
|
||||
bus->chip = bus_pub->devid;
|
||||
bus->chiprev = bus_pub->chiprev;
|
||||
|
||||
/* Attach to the common driver interface */
|
||||
ret = brcmf_attach(0, dev);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,38 @@
|
||||
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
||||
#define IE_MAX_LEN 512
|
||||
|
||||
/* IE TLV processing */
|
||||
#define TLV_LEN_OFF 1 /* length offset */
|
||||
#define TLV_HDR_LEN 2 /* header length */
|
||||
#define TLV_BODY_OFF 2 /* body offset */
|
||||
#define TLV_OUI_LEN 3 /* oui id length */
|
||||
|
||||
/* 802.11 Mgmt Packet flags */
|
||||
#define BRCMF_VNDR_IE_BEACON_FLAG 0x1
|
||||
#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2
|
||||
#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4
|
||||
#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8
|
||||
#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10
|
||||
#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20
|
||||
/* vendor IE in IW advertisement protocol ID field */
|
||||
#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40
|
||||
/* allow custom IE id */
|
||||
#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100
|
||||
|
||||
/* P2P Action Frames flags (spec ordered) */
|
||||
#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000
|
||||
#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000
|
||||
#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000
|
||||
#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000
|
||||
#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000
|
||||
#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000
|
||||
#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000
|
||||
#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000
|
||||
#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000
|
||||
|
||||
#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
|
||||
|
||||
|
||||
/**
|
||||
* enum brcmf_scan_status - dongle scan status
|
||||
*
|
||||
@ -52,11 +84,19 @@ enum brcmf_scan_status {
|
||||
BRCMF_SCAN_STATUS_ABORT,
|
||||
};
|
||||
|
||||
/* wi-fi mode */
|
||||
/**
|
||||
* enum wl_mode - driver mode of virtual interface.
|
||||
*
|
||||
* @WL_MODE_BSS: connects to BSS.
|
||||
* @WL_MODE_IBSS: operate as ad-hoc.
|
||||
* @WL_MODE_AP: operate as access-point.
|
||||
* @WL_MODE_P2P: provide P2P discovery.
|
||||
*/
|
||||
enum wl_mode {
|
||||
WL_MODE_BSS,
|
||||
WL_MODE_IBSS,
|
||||
WL_MODE_AP
|
||||
WL_MODE_AP,
|
||||
WL_MODE_P2P
|
||||
};
|
||||
|
||||
/* dongle configuration */
|
||||
@ -108,6 +148,7 @@ struct brcmf_cfg80211_profile {
|
||||
* @BRCMF_VIF_STATUS_READY: ready for operation.
|
||||
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
|
||||
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
|
||||
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
|
||||
*/
|
||||
@ -115,6 +156,7 @@ enum brcmf_vif_status {
|
||||
BRCMF_VIF_STATUS_READY,
|
||||
BRCMF_VIF_STATUS_CONNECTING,
|
||||
BRCMF_VIF_STATUS_CONNECTED,
|
||||
BRCMF_VIF_STATUS_DISCONNECTING,
|
||||
BRCMF_VIF_STATUS_AP_CREATING,
|
||||
BRCMF_VIF_STATUS_AP_CREATED
|
||||
};
|
||||
@ -122,16 +164,22 @@ enum brcmf_vif_status {
|
||||
/**
|
||||
* struct vif_saved_ie - holds saved IEs for a virtual interface.
|
||||
*
|
||||
* @probe_req_ie: IE info for probe request.
|
||||
* @probe_res_ie: IE info for probe response.
|
||||
* @beacon_ie: IE info for beacon frame.
|
||||
* @probe_req_ie_len: IE info length for probe request.
|
||||
* @probe_res_ie_len: IE info length for probe response.
|
||||
* @beacon_ie_len: IE info length for beacon frame.
|
||||
*/
|
||||
struct vif_saved_ie {
|
||||
u8 probe_req_ie[IE_MAX_LEN];
|
||||
u8 probe_res_ie[IE_MAX_LEN];
|
||||
u8 beacon_ie[IE_MAX_LEN];
|
||||
u8 assoc_req_ie[IE_MAX_LEN];
|
||||
u32 probe_req_ie_len;
|
||||
u32 probe_res_ie_len;
|
||||
u32 beacon_ie_len;
|
||||
u32 assoc_req_ie_len;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -145,6 +193,7 @@ struct vif_saved_ie {
|
||||
* @sme_state: SME state using enum brcmf_vif_status bits.
|
||||
* @pm_block: power-management blocked.
|
||||
* @list: linked list.
|
||||
* @mgmt_rx_reg: registered rx mgmt frame types.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif {
|
||||
struct brcmf_if *ifp;
|
||||
@ -156,6 +205,7 @@ struct brcmf_cfg80211_vif {
|
||||
bool pm_block;
|
||||
struct vif_saved_ie saved_ie;
|
||||
struct list_head list;
|
||||
u16 mgmt_rx_reg;
|
||||
};
|
||||
|
||||
/* association inform */
|
||||
@ -189,6 +239,9 @@ struct escan_info {
|
||||
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
||||
struct wiphy *wiphy;
|
||||
struct net_device *ndev;
|
||||
s32 (*run)(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct cfg80211_scan_request *request, u16 action);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -272,11 +325,28 @@ struct brcmf_pno_scanresults_le {
|
||||
__le32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif_event - virtual interface event information.
|
||||
*
|
||||
* @vif_wq: waitqueue awaiting interface event from firmware.
|
||||
* @vif_event_lock: protects other members in this structure.
|
||||
* @vif_complete: completion for net attach.
|
||||
* @action: either add, change, or delete.
|
||||
* @vif: virtual interface object related to the event.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif_event {
|
||||
wait_queue_head_t vif_wq;
|
||||
struct mutex vif_event_lock;
|
||||
u8 action;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @p2p: peer-to-peer specific information.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
@ -304,10 +374,12 @@ struct brcmf_pno_scanresults_le {
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
* @vif_event: vif event signalling.
|
||||
*/
|
||||
struct brcmf_cfg80211_info {
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct brcmf_p2p_info p2p;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_scan_results *bss_list;
|
||||
@ -335,6 +407,21 @@ struct brcmf_cfg80211_info {
|
||||
u8 *escan_ioctl_buf;
|
||||
struct list_head vif_list;
|
||||
u8 vif_cnt;
|
||||
struct brcmf_cfg80211_vif_event vif_event;
|
||||
struct completion vif_disabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_tlv - tag_ID/length/value_buffer tuple.
|
||||
*
|
||||
* @id: tag identifier.
|
||||
* @len: number of bytes in value buffer.
|
||||
* @data: value buffer.
|
||||
*/
|
||||
struct brcmf_tlv {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||
@ -389,4 +476,26 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
bool pm_block);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
||||
|
||||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct ieee80211_channel *ch);
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
|
||||
u8 action, ulong timeout);
|
||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
bool aborted, bool fw_abort);
|
||||
void brcmf_set_mpc(struct net_device *ndev, int mpc);
|
||||
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
||||
|
||||
#endif /* _wl_cfg80211_h_ */
|
||||
|
@ -101,8 +101,6 @@
|
||||
#define DOT11_RTS_LEN 16
|
||||
#define DOT11_CTS_LEN 10
|
||||
#define DOT11_BA_BITMAP_LEN 128
|
||||
#define DOT11_MIN_BEACON_PERIOD 1
|
||||
#define DOT11_MAX_BEACON_PERIOD 0xFFFF
|
||||
#define DOT11_MAXNUMFRAGS 16
|
||||
#define DOT11_MAX_FRAG_LEN 2346
|
||||
|
||||
@ -5555,8 +5553,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
|
||||
|
||||
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||
{
|
||||
if (period < DOT11_MIN_BEACON_PERIOD ||
|
||||
period > DOT11_MAX_BEACON_PERIOD)
|
||||
if (period == 0)
|
||||
return -EINVAL;
|
||||
|
||||
wlc->default_bss->beacon_period = period;
|
||||
@ -7408,9 +7405,13 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||
struct brcms_bss_cfg *cfg,
|
||||
bool suspend)
|
||||
{
|
||||
u16 prb_resp[BCN_TMPL_LEN / 2];
|
||||
u16 *prb_resp;
|
||||
int len = BCN_TMPL_LEN;
|
||||
|
||||
prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
|
||||
if (!prb_resp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* write the probe response to hardware, or save in
|
||||
* the config structure
|
||||
@ -7444,6 +7445,8 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||
|
||||
if (suspend)
|
||||
brcms_c_enable_mac(wlc);
|
||||
|
||||
kfree(prb_resp);
|
||||
}
|
||||
|
||||
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
|
||||
|
@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
||||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
return;
|
||||
@ -1035,26 +1035,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of RB/SKB */
|
||||
rxb->page_dma =
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
rxb->page = page;
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
@ -1284,8 +1292,15 @@ il3945_rx_handle(struct il_priv *il)
|
||||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
|
@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
||||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get physical address of the RB */
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
BUG_ON(rxb->page);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of the RB */
|
||||
rxb->page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
/* dma address must be no more than 36 bits */
|
||||
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
|
||||
/* and also 256 byte aligned! */
|
||||
BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
@ -725,6 +728,16 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
|
||||
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
|
||||
/* We know which subframes of an A-MPDU belong
|
||||
* together since we get a single PHY response
|
||||
* from the firmware for all of them.
|
||||
*/
|
||||
|
||||
rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status.ampdu_reference = il->_4965.ampdu_ref;
|
||||
}
|
||||
|
||||
il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
|
||||
&rx_status);
|
||||
}
|
||||
@ -736,6 +749,7 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
|
||||
{
|
||||
struct il_rx_pkt *pkt = rxb_addr(rxb);
|
||||
il->_4965.last_phy_res_valid = true;
|
||||
il->_4965.ampdu_ref++;
|
||||
memcpy(&il->_4965.last_phy_res, pkt->u.raw,
|
||||
sizeof(struct il_rx_phy_res));
|
||||
}
|
||||
@ -4281,8 +4295,16 @@ il4965_rx_handle(struct il_priv *il)
|
||||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
@ -6573,9 +6595,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
/* extract MAC Address */
|
||||
il4965_eeprom_get_mac(il, il->addresses[0].addr);
|
||||
D_INFO("MAC address: %pM\n", il->addresses[0].addr);
|
||||
|
@ -1748,7 +1748,6 @@ static void
|
||||
il4965_post_associate(struct il_priv *il)
|
||||
{
|
||||
struct ieee80211_vif *vif = il->vif;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vif || !il->is_open)
|
||||
@ -1759,8 +1758,6 @@ il4965_post_associate(struct il_priv *il)
|
||||
|
||||
il_scan_cancel_timeout(il, 200);
|
||||
|
||||
conf = &il->hw->conf;
|
||||
|
||||
il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
il_commit_rxon(il);
|
||||
|
||||
|
@ -1134,8 +1134,9 @@ struct il_wep_cmd {
|
||||
#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1)
|
||||
#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
|
||||
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0xf0
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_POS 4
|
||||
#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7)
|
||||
|
||||
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
|
||||
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
|
||||
|
@ -1356,6 +1356,7 @@ struct il_priv {
|
||||
struct {
|
||||
struct il_rx_phy_res last_phy_res;
|
||||
bool last_phy_res_valid;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
|
||||
|
@ -43,8 +43,20 @@ config IWLWIFI
|
||||
module will be called iwlwifi.
|
||||
|
||||
config IWLDVM
|
||||
tristate "Intel Wireless WiFi"
|
||||
tristate "Intel Wireless WiFi DVM Firmware support"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This is the driver supporting the DVM firmware which is
|
||||
currently the only firmware available for existing devices.
|
||||
|
||||
config IWLMVM
|
||||
tristate "Intel Wireless WiFi MVM Firmware support"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This is the driver supporting the MVM firmware which is
|
||||
currently only available for 7000 series devices.
|
||||
|
||||
Say yes if you have such a device.
|
||||
|
||||
menu "Debugging Options"
|
||||
depends on IWLWIFI
|
||||
|
@ -5,8 +5,10 @@ iwlwifi-objs += iwl-drv.o
|
||||
iwlwifi-objs += iwl-debug.o
|
||||
iwlwifi-objs += iwl-notif-wait.o
|
||||
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
|
||||
iwlwifi-objs += pcie/7000.o
|
||||
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
|
||||
@ -15,5 +17,6 @@ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
|
||||
|
||||
|
||||
obj-$(CONFIG_IWLDVM) += dvm/
|
||||
obj-$(CONFIG_IWLMVM) += mvm/
|
||||
|
||||
CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
@ -459,14 +459,12 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true)) {
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true, &flags)) {
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
|
||||
status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
iwl_trans_release_nic_access(priv->trans, &flags);
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (ret == 0) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
@ -353,11 +353,8 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(priv->trans, false)) {
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(priv->trans, false, ®_flags))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
@ -388,8 +385,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
}
|
||||
}
|
||||
/* Allow device to power down */
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
iwl_trans_release_nic_access(priv->trans, ®_flags);
|
||||
}
|
||||
|
||||
static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
||||
@ -1717,9 +1713,8 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&trans->reg_lock, reg_flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false))
|
||||
goto out_unlock;
|
||||
if (!iwl_trans_grab_nic_access(trans, false, ®_flags))
|
||||
return pos;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
@ -1757,9 +1752,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
}
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_trans_release_nic_access(trans);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
|
||||
iwl_trans_release_nic_access(trans, ®_flags);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@ -1991,13 +1984,13 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
/* SKU Control */
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
|
||||
/* write radio config values to register */
|
||||
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
||||
@ -2009,10 +2002,11 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
priv->nvm_data->radio_cfg_dash <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
|
||||
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val);
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH,
|
||||
reg_val);
|
||||
|
||||
IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
|
||||
priv->nvm_data->radio_cfg_type,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
@ -411,8 +411,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
|
||||
* BT traffic, as they would just be disrupted by BT.
|
||||
*/
|
||||
if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) {
|
||||
IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n",
|
||||
priv->bt_traffic_load);
|
||||
IWL_DEBUG_COEX(priv,
|
||||
"BT traffic (%d), no aggregation allowed\n",
|
||||
priv->bt_traffic_load);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portionhelp of the ieee80211 subsystem header files.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
@ -185,10 +185,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
||||
priv->thermal_throttle.ct_kill_toggle = true;
|
||||
}
|
||||
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, false))
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, false, &flags))
|
||||
iwl_trans_release_nic_access(priv->trans, &flags);
|
||||
|
||||
/* Reschedule the ct_kill timer to occur in
|
||||
* CT_KILL_EXIT_DURATION seconds to ensure we get a
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -83,6 +83,7 @@ enum iwl_device_family {
|
||||
IWL_DEVICE_FAMILY_6030,
|
||||
IWL_DEVICE_FAMILY_6050,
|
||||
IWL_DEVICE_FAMILY_6150,
|
||||
IWL_DEVICE_FAMILY_7000,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
@ -116,6 +116,7 @@ do { \
|
||||
#define IWL_DL_HCMD 0x00000004
|
||||
#define IWL_DL_STATE 0x00000008
|
||||
/* 0x000000F0 - 0x00000010 */
|
||||
#define IWL_DL_TE 0x00000020
|
||||
#define IWL_DL_EEPROM 0x00000040
|
||||
#define IWL_DL_RADIO 0x00000080
|
||||
/* 0x00000F00 - 0x00000100 */
|
||||
@ -156,6 +157,7 @@ do { \
|
||||
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
|
||||
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
|
||||
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
|
||||
#define IWL_DEBUG_TE(p, f, a...) IWL_DEBUG(p, IWL_DL_TE, f, ## a)
|
||||
#define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a)
|
||||
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
|
||||
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -139,8 +139,10 @@ struct iwl_drv {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DVM_OP_MODE 0
|
||||
#define MVM_OP_MODE 1
|
||||
enum {
|
||||
DVM_OP_MODE = 0,
|
||||
MVM_OP_MODE = 1,
|
||||
};
|
||||
|
||||
/* Protects the table contents, i.e. the ops pointer & drv list */
|
||||
static struct mutex iwlwifi_opmode_table_mtx;
|
||||
@ -149,8 +151,8 @@ static struct iwlwifi_opmode_table {
|
||||
const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */
|
||||
struct list_head drv; /* list of devices using this op_mode */
|
||||
} iwlwifi_opmode_table[] = { /* ops set when driver is initialized */
|
||||
{ .name = "iwldvm", .ops = NULL },
|
||||
{ .name = "iwlmvm", .ops = NULL },
|
||||
[DVM_OP_MODE] = { .name = "iwldvm", .ops = NULL },
|
||||
[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -268,7 +270,7 @@ struct fw_sec_parsing {
|
||||
*/
|
||||
struct iwl_tlv_calib_data {
|
||||
__le32 ucode_type;
|
||||
__le64 calib;
|
||||
struct iwl_tlv_calib_ctrl calib;
|
||||
} __packed;
|
||||
|
||||
struct iwl_firmware_pieces {
|
||||
@ -358,7 +360,11 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
|
||||
ucode_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
drv->fw.default_calib[ucode_type] = le64_to_cpu(def_calib->calib);
|
||||
drv->fw.default_calib[ucode_type].flow_trigger =
|
||||
def_calib->calib.flow_trigger;
|
||||
drv->fw.default_calib[ucode_type].event_trigger =
|
||||
def_calib->calib.event_trigger;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -959,7 +965,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
release_firmware(ucode_raw);
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
op = &iwlwifi_opmode_table[DVM_OP_MODE];
|
||||
if (fw->mvm_fw)
|
||||
op = &iwlwifi_opmode_table[MVM_OP_MODE];
|
||||
else
|
||||
op = &iwlwifi_opmode_table[DVM_OP_MODE];
|
||||
|
||||
/* add this device to the list of devices using this op_mode */
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -66,7 +66,7 @@
|
||||
/* for all modules */
|
||||
#define DRV_NAME "iwlwifi"
|
||||
#define IWLWIFI_VERSION "in-tree:"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2003-2012 Intel Corporation"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2003-2013 Intel Corporation"
|
||||
#define DRV_AUTHOR "<ilw@linux.intel.com>"
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -703,9 +703,9 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
return n_channels;
|
||||
}
|
||||
|
||||
static int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band)
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band)
|
||||
{
|
||||
struct ieee80211_channel *chan = &data->channels[0];
|
||||
int n = 0, idx = 0;
|
||||
@ -728,10 +728,10 @@ static int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||
|
||||
static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
int max_bit_rate = 0;
|
||||
u8 rx_chains;
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -126,4 +126,13 @@ static inline void iwl_free_nvm_data(struct iwl_nvm_data *data)
|
||||
int iwl_nvm_check_version(struct iwl_nvm_data *data,
|
||||
struct iwl_trans *trans);
|
||||
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum ieee80211_band band);
|
||||
|
||||
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band);
|
||||
|
||||
#endif /* __iwl_eeprom_parse_h__ */
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -414,6 +414,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
||||
* uCode/driver must write "1" in order to clear this flag
|
||||
*/
|
||||
#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
|
||||
#define FH_TSSR_TX_MSG_CONFIG_REG (FH_TSSR_LOWER_BOUND + 0x008)
|
||||
|
||||
#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -139,6 +139,19 @@ struct fw_img {
|
||||
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
|
||||
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
|
||||
|
||||
/*
|
||||
* Calibration control struct.
|
||||
* Sent as part of the phy configuration command.
|
||||
* @flow_trigger: bitmap for which calibrations to perform according to
|
||||
* flow triggers.
|
||||
* @event_trigger: bitmap for which calibrations to perform according to
|
||||
* event triggers.
|
||||
*/
|
||||
struct iwl_tlv_calib_ctrl {
|
||||
__le32 flow_trigger;
|
||||
__le32 event_trigger;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
@ -153,6 +166,7 @@ struct fw_img {
|
||||
* @inst_evtlog_ptr: event log offset for runtime ucode.
|
||||
* @inst_evtlog_size: event log size for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offfset for runtime ucode.
|
||||
* @mvm_fw: indicates this is MVM firmware
|
||||
*/
|
||||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
@ -168,7 +182,7 @@ struct iwl_fw {
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
|
||||
u64 default_calib[IWL_UCODE_TYPE_MAX];
|
||||
struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX];
|
||||
u32 phy_config;
|
||||
|
||||
bool mvm_fw;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
@ -35,54 +35,6 @@
|
||||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
|
||||
}
|
||||
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
|
||||
}
|
||||
|
||||
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
__iwl_set_bit(trans, reg, mask);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bit);
|
||||
|
||||
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
__iwl_clear_bit(trans, reg, mask);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bit);
|
||||
|
||||
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 v;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
WARN_ON_ONCE(value & ~mask);
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
v = iwl_read32(trans, reg);
|
||||
v &= ~mask;
|
||||
v |= value;
|
||||
iwl_write32(trans, reg, v);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_mask);
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
@ -103,13 +55,10 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
u32 value = 0x5a5a5a5a;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
value = iwl_read32(trans, reg);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -119,12 +68,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
iwl_write32(trans, reg, value);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_direct32);
|
||||
|
||||
@ -162,12 +109,10 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
unsigned long flags;
|
||||
u32 val = 0x5a5a5a5a;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_prph);
|
||||
@ -176,12 +121,10 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_prph);
|
||||
|
||||
@ -189,13 +132,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
__iwl_read_prph(trans, ofs) | mask);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
|
||||
|
||||
@ -204,13 +145,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
(__iwl_read_prph(trans, ofs) & mask) | bits);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
|
||||
|
||||
@ -219,12 +158,10 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
__iwl_write_prph(trans, ofs, (val & ~mask));
|
||||
iwl_trans_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2003 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project.
|
||||
*
|
||||
@ -51,12 +51,15 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
|
||||
return val;
|
||||
}
|
||||
|
||||
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, mask);
|
||||
}
|
||||
|
||||
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value);
|
||||
static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
346
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
Normal file
346
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
Normal file
@ -0,0 +1,346 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
|
||||
/* NVM offsets (in words) definitions */
|
||||
enum wkp_nvm_offsets {
|
||||
/* NVM HW-Section offset (in words) definitions */
|
||||
HW_ADDR = 0x15,
|
||||
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
NVM_SW_SECTION = 0x1C0,
|
||||
NVM_VERSION = 0,
|
||||
RADIO_CFG = 1,
|
||||
SKU = 2,
|
||||
N_HW_ADDRS = 3,
|
||||
NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
|
||||
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
NVM_CALIB_SECTION = 0x2B8,
|
||||
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
|
||||
};
|
||||
|
||||
/* SKU Capabilities (actual values from NVM definition) */
|
||||
enum nvm_sku_bits {
|
||||
NVM_SKU_CAP_BAND_24GHZ = BIT(0),
|
||||
NVM_SKU_CAP_BAND_52GHZ = BIT(1),
|
||||
NVM_SKU_CAP_11N_ENABLE = BIT(2),
|
||||
};
|
||||
|
||||
/* radio config bits (actual values from NVM definition) */
|
||||
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
|
||||
#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
|
||||
#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
|
||||
#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
|
||||
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
|
||||
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
|
||||
|
||||
/*
|
||||
* These are the channel numbers in the order that they are stored in the NVM
|
||||
*/
|
||||
static const u8 iwl_nvm_channels[] = {
|
||||
/* 2.4 GHz */
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
/* 5 GHz */
|
||||
36, 40, 44 , 48, 52, 56, 60, 64,
|
||||
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
|
||||
149, 153, 157, 161, 165
|
||||
};
|
||||
|
||||
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
|
||||
#define NUM_2GHZ_CHANNELS 14
|
||||
#define FIRST_2GHZ_HT_MINUS 5
|
||||
#define LAST_2GHZ_HT_PLUS 9
|
||||
#define LAST_5GHZ_HT 161
|
||||
|
||||
|
||||
/* rate data (static) */
|
||||
static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
|
||||
{ .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
|
||||
{ .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
|
||||
{ .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
|
||||
{ .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
|
||||
{ .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
|
||||
{ .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
|
||||
{ .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
|
||||
{ .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
|
||||
};
|
||||
#define RATES_24_OFFS 0
|
||||
#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
|
||||
#define RATES_52_OFFS 4
|
||||
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
|
||||
|
||||
/**
|
||||
* enum iwl_nvm_channel_flags - channel flags in NVM
|
||||
* @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
|
||||
* @NVM_CHANNEL_IBSS: usable as an IBSS channel
|
||||
* @NVM_CHANNEL_ACTIVE: active scanning allowed
|
||||
* @NVM_CHANNEL_RADAR: radar detection required
|
||||
* @NVM_CHANNEL_DFS: dynamic freq selection candidate
|
||||
* @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
|
||||
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
|
||||
*/
|
||||
enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
NVM_CHANNEL_IBSS = BIT(1),
|
||||
NVM_CHANNEL_ACTIVE = BIT(3),
|
||||
NVM_CHANNEL_RADAR = BIT(4),
|
||||
NVM_CHANNEL_DFS = BIT(7),
|
||||
NVM_CHANNEL_WIDE = BIT(8),
|
||||
NVM_CHANNEL_40MHZ = BIT(9),
|
||||
};
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) \
|
||||
((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
|
||||
|
||||
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 * const nvm_ch_flags)
|
||||
{
|
||||
int ch_idx;
|
||||
int n_channels = 0;
|
||||
struct ieee80211_channel *channel;
|
||||
u16 ch_flags;
|
||||
bool is_5ghz;
|
||||
|
||||
for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
|
||||
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
|
||||
if (!(ch_flags & NVM_CHANNEL_VALID)) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d Flags %x [%sGHz] - No traffic\n",
|
||||
iwl_nvm_channels[ch_idx],
|
||||
ch_flags,
|
||||
(ch_idx >= NUM_2GHZ_CHANNELS) ?
|
||||
"5.2" : "2.4");
|
||||
continue;
|
||||
}
|
||||
|
||||
channel = &data->channels[n_channels];
|
||||
n_channels++;
|
||||
|
||||
channel->hw_value = iwl_nvm_channels[ch_idx];
|
||||
channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
|
||||
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
|
||||
channel->center_freq =
|
||||
ieee80211_channel_to_frequency(
|
||||
channel->hw_value, channel->band);
|
||||
|
||||
/* TODO: Need to be dependent to the NVM */
|
||||
channel->flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (ch_idx < NUM_2GHZ_CHANNELS &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
} else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
|
||||
(ch_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
else
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
}
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_IBSS))
|
||||
channel->flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_ACTIVE))
|
||||
channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
|
||||
if (ch_flags & NVM_CHANNEL_RADAR)
|
||||
channel->flags |= IEEE80211_CHAN_RADAR;
|
||||
|
||||
/* Initialize regulatory-based run-time data */
|
||||
|
||||
/* TODO: read the real value from the NVM */
|
||||
channel->max_power = 0;
|
||||
is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
channel->hw_value,
|
||||
is_5ghz ? "5.2" : "2.4",
|
||||
CHECK_AND_PRINT_I(VALID),
|
||||
CHECK_AND_PRINT_I(IBSS),
|
||||
CHECK_AND_PRINT_I(ACTIVE),
|
||||
CHECK_AND_PRINT_I(RADAR),
|
||||
CHECK_AND_PRINT_I(WIDE),
|
||||
CHECK_AND_PRINT_I(DFS),
|
||||
ch_flags,
|
||||
channel->max_power,
|
||||
((ch_flags & NVM_CHANNEL_IBSS) &&
|
||||
!(ch_flags & NVM_CHANNEL_RADAR))
|
||||
? "" : "not ");
|
||||
}
|
||||
|
||||
return n_channels;
|
||||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw)
|
||||
{
|
||||
int n_channels = iwl_init_channel_map(dev, cfg, data,
|
||||
&nvm_sw[NVM_CHANNELS]);
|
||||
int n_used = 0;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_2GHZ];
|
||||
sband->band = IEEE80211_BAND_2GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
||||
sband->n_bitrates = N_RATES_24;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ);
|
||||
|
||||
sband = &data->bands[IEEE80211_BAND_5GHZ];
|
||||
sband->band = IEEE80211_BAND_5GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
|
||||
sband->n_bitrates = N_RATES_52;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
n_used, n_channels);
|
||||
}
|
||||
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
u8 hw_addr[ETH_ALEN];
|
||||
u16 radio_cfg, sku;
|
||||
|
||||
data = kzalloc(sizeof(*data) +
|
||||
sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
|
||||
radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
|
||||
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
|
||||
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
|
||||
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
|
||||
data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
|
||||
data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
|
||||
sku = le16_to_cpup(nvm_sw + SKU);
|
||||
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
|
||||
data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
|
||||
data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
||||
data->sku_cap_11n_enable = false;
|
||||
|
||||
/* check overrides (some devices have wrong NVM) */
|
||||
if (cfg->valid_tx_ant)
|
||||
data->valid_tx_ant = cfg->valid_tx_ant;
|
||||
if (cfg->valid_rx_ant)
|
||||
data->valid_rx_ant = cfg->valid_rx_ant;
|
||||
|
||||
if (!data->valid_tx_ant || !data->valid_rx_ant) {
|
||||
IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
|
||||
|
||||
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
|
||||
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
|
||||
|
||||
/* The byte order is little endian 16 bit, meaning 214365 */
|
||||
memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
|
||||
data->hw_addr[0] = hw_addr[1];
|
||||
data->hw_addr[1] = hw_addr[0];
|
||||
data->hw_addr[2] = hw_addr[3];
|
||||
data->hw_addr[3] = hw_addr[2];
|
||||
data->hw_addr[4] = hw_addr[5];
|
||||
data->hw_addr[5] = hw_addr[4];
|
||||
|
||||
iwl_init_sbands(dev, cfg, data, nvm_sw);
|
||||
|
||||
data->calib_version = 255; /* TODO:
|
||||
this value will prevent some checks from
|
||||
failing, we need to check if this
|
||||
field is still needed, and if it does,
|
||||
where is it in the NVM*/
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);
|
80
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
Normal file
80
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
Normal file
@ -0,0 +1,80 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
#ifndef __iwl_nvm_parse_h__
|
||||
#define __iwl_nvm_parse_h__
|
||||
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
/**
|
||||
* iwl_parse_nvm_data - parse NVM data and return values
|
||||
*
|
||||
* This function parses all NVM values we need and then
|
||||
* returns a (newly allocated) struct containing all the
|
||||
* relevant values for driver use. The struct must be freed
|
||||
* later with iwl_free_nvm_data().
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib);
|
||||
|
||||
#endif /* __iwl_nvm_parse_h__ */
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -63,6 +63,8 @@
|
||||
#ifndef __iwl_op_mode_h__
|
||||
#define __iwl_op_mode_h__
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
struct iwl_op_mode;
|
||||
struct iwl_trans;
|
||||
struct sk_buff;
|
||||
|
514
drivers/net/wireless/iwlwifi/iwl-phy-db.c
Normal file
514
drivers/net/wireless/iwlwifi/iwl-phy-db.c
Normal file
@ -0,0 +1,514 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-phy-db.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */
|
||||
#define IWL_NUM_PAPD_CH_GROUPS 4
|
||||
#define IWL_NUM_TXP_CH_GROUPS 9
|
||||
|
||||
struct iwl_phy_db_entry {
|
||||
u16 size;
|
||||
u8 *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_phy_db - stores phy configuration and calibration data.
|
||||
*
|
||||
* @cfg: phy configuration.
|
||||
* @calib_nch: non channel specific calibration data.
|
||||
* @calib_ch: channel specific calibration data.
|
||||
* @calib_ch_group_papd: calibration data related to papd channel group.
|
||||
* @calib_ch_group_txp: calibration data related to tx power chanel group.
|
||||
*/
|
||||
struct iwl_phy_db {
|
||||
struct iwl_phy_db_entry cfg;
|
||||
struct iwl_phy_db_entry calib_nch;
|
||||
struct iwl_phy_db_entry calib_ch;
|
||||
struct iwl_phy_db_entry calib_ch_group_papd[IWL_NUM_PAPD_CH_GROUPS];
|
||||
struct iwl_phy_db_entry calib_ch_group_txp[IWL_NUM_TXP_CH_GROUPS];
|
||||
|
||||
u32 channel_num;
|
||||
u32 channel_size;
|
||||
|
||||
struct iwl_trans *trans;
|
||||
};
|
||||
|
||||
enum iwl_phy_db_section_type {
|
||||
IWL_PHY_DB_CFG = 1,
|
||||
IWL_PHY_DB_CALIB_NCH,
|
||||
IWL_PHY_DB_CALIB_CH,
|
||||
IWL_PHY_DB_CALIB_CHG_PAPD,
|
||||
IWL_PHY_DB_CALIB_CHG_TXP,
|
||||
IWL_PHY_DB_MAX
|
||||
};
|
||||
|
||||
#define PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
|
||||
|
||||
/*
|
||||
* phy db - configure operational ucode
|
||||
*/
|
||||
struct iwl_phy_db_cmd {
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/* for parsing of tx power channel group data that comes from the firmware*/
|
||||
struct iwl_phy_db_chg_txp {
|
||||
__le32 space;
|
||||
__le16 max_channel_idx;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* phy db - Receieve phy db chunk after calibrations
|
||||
*/
|
||||
struct iwl_calib_res_notif_phy_db {
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
|
||||
static inline void iwl_phy_db_test_pic(__le32 pic)
|
||||
{
|
||||
WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
|
||||
}
|
||||
|
||||
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!phy_db)
|
||||
return phy_db;
|
||||
|
||||
phy_db->trans = trans;
|
||||
|
||||
/* TODO: add default values of the phy db. */
|
||||
return phy_db;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_init);
|
||||
|
||||
/*
|
||||
* get phy db section: returns a pointer to a phy db section specified by
|
||||
* type and channel group id.
|
||||
*/
|
||||
static struct iwl_phy_db_entry *
|
||||
iwl_phy_db_get_section(struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u16 chg_id)
|
||||
{
|
||||
if (!phy_db || type >= IWL_PHY_DB_MAX)
|
||||
return NULL;
|
||||
|
||||
switch (type) {
|
||||
case IWL_PHY_DB_CFG:
|
||||
return &phy_db->cfg;
|
||||
case IWL_PHY_DB_CALIB_NCH:
|
||||
return &phy_db->calib_nch;
|
||||
case IWL_PHY_DB_CALIB_CH:
|
||||
return &phy_db->calib_ch;
|
||||
case IWL_PHY_DB_CALIB_CHG_PAPD:
|
||||
if (chg_id >= IWL_NUM_PAPD_CH_GROUPS)
|
||||
return NULL;
|
||||
return &phy_db->calib_ch_group_papd[chg_id];
|
||||
case IWL_PHY_DB_CALIB_CHG_TXP:
|
||||
if (chg_id >= IWL_NUM_TXP_CH_GROUPS)
|
||||
return NULL;
|
||||
return &phy_db->calib_ch_group_txp[chg_id];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void iwl_phy_db_free_section(struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u16 chg_id)
|
||||
{
|
||||
struct iwl_phy_db_entry *entry =
|
||||
iwl_phy_db_get_section(phy_db, type, chg_id);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
kfree(entry->data);
|
||||
entry->data = NULL;
|
||||
entry->size = 0;
|
||||
}
|
||||
|
||||
void iwl_phy_db_free(struct iwl_phy_db *phy_db)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!phy_db)
|
||||
return;
|
||||
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0);
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0);
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CH, 0);
|
||||
for (i = 0; i < IWL_NUM_PAPD_CH_GROUPS; i++)
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i);
|
||||
for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++)
|
||||
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_TXP, i);
|
||||
|
||||
kfree(phy_db);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_free);
|
||||
|
||||
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
gfp_t alloc_ctx)
|
||||
{
|
||||
struct iwl_calib_res_notif_phy_db *phy_db_notif =
|
||||
(struct iwl_calib_res_notif_phy_db *)pkt->data;
|
||||
enum iwl_phy_db_section_type type = le16_to_cpu(phy_db_notif->type);
|
||||
u16 size = le16_to_cpu(phy_db_notif->length);
|
||||
struct iwl_phy_db_entry *entry;
|
||||
u16 chg_id = 0;
|
||||
|
||||
if (!phy_db)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CHG_PAPD ||
|
||||
type == IWL_PHY_DB_CALIB_CHG_TXP)
|
||||
chg_id = le16_to_cpup((__le16 *)phy_db_notif->data);
|
||||
|
||||
entry = iwl_phy_db_get_section(phy_db, type, chg_id);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
kfree(entry->data);
|
||||
entry->data = kmemdup(phy_db_notif->data, size, alloc_ctx);
|
||||
if (!entry->data) {
|
||||
entry->size = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
entry->size = size;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CH) {
|
||||
phy_db->channel_num =
|
||||
le32_to_cpup((__le32 *)phy_db_notif->data);
|
||||
phy_db->channel_size =
|
||||
(size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
|
||||
(size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_set_section);
|
||||
|
||||
static int is_valid_channel(u16 ch_id)
|
||||
{
|
||||
if (ch_id <= 14 ||
|
||||
(36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
|
||||
(100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
|
||||
(145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 ch_id_to_ch_index(u16 ch_id)
|
||||
{
|
||||
if (WARN_ON(!is_valid_channel(ch_id)))
|
||||
return 0xff;
|
||||
|
||||
if (ch_id <= 14)
|
||||
return ch_id - 1;
|
||||
if (ch_id <= 64)
|
||||
return (ch_id + 20) / 4;
|
||||
if (ch_id <= 140)
|
||||
return (ch_id - 12) / 4;
|
||||
return (ch_id - 13) / 4;
|
||||
}
|
||||
|
||||
|
||||
static u16 channel_id_to_papd(u16 ch_id)
|
||||
{
|
||||
if (WARN_ON(!is_valid_channel(ch_id)))
|
||||
return 0xff;
|
||||
|
||||
if (1 <= ch_id && ch_id <= 14)
|
||||
return 0;
|
||||
if (36 <= ch_id && ch_id <= 64)
|
||||
return 1;
|
||||
if (100 <= ch_id && ch_id <= 140)
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id)
|
||||
{
|
||||
struct iwl_phy_db_chg_txp *txp_chg;
|
||||
int i;
|
||||
u8 ch_index = ch_id_to_ch_index(ch_id);
|
||||
if (ch_index == 0xff)
|
||||
return 0xff;
|
||||
|
||||
for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++) {
|
||||
txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
|
||||
if (!txp_chg)
|
||||
return 0xff;
|
||||
/*
|
||||
* Looking for the first channel group that its max channel is
|
||||
* higher then wanted channel.
|
||||
*/
|
||||
if (le16_to_cpu(txp_chg->max_channel_idx) >= ch_index)
|
||||
return i;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
static
|
||||
int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
|
||||
u32 type, u8 **data, u16 *size, u16 ch_id)
|
||||
{
|
||||
struct iwl_phy_db_entry *entry;
|
||||
u32 channel_num;
|
||||
u32 channel_size;
|
||||
u16 ch_group_id = 0;
|
||||
u16 index;
|
||||
|
||||
if (!phy_db)
|
||||
return -EINVAL;
|
||||
|
||||
/* find wanted channel group */
|
||||
if (type == IWL_PHY_DB_CALIB_CHG_PAPD)
|
||||
ch_group_id = channel_id_to_papd(ch_id);
|
||||
else if (type == IWL_PHY_DB_CALIB_CHG_TXP)
|
||||
ch_group_id = channel_id_to_txp(phy_db, ch_id);
|
||||
|
||||
entry = iwl_phy_db_get_section(phy_db, type, ch_group_id);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == IWL_PHY_DB_CALIB_CH) {
|
||||
index = ch_id_to_ch_index(ch_id);
|
||||
channel_num = phy_db->channel_num;
|
||||
channel_size = phy_db->channel_size;
|
||||
if (index >= channel_num) {
|
||||
IWL_ERR(phy_db->trans, "Wrong channel number %d\n",
|
||||
ch_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
*data = entry->data + CHANNEL_NUM_SIZE + index * channel_size;
|
||||
*size = channel_size;
|
||||
} else {
|
||||
*data = entry->data;
|
||||
*size = entry->size;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)*data) +
|
||||
(*size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, *size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type,
|
||||
u16 length, void *data)
|
||||
{
|
||||
struct iwl_phy_db_cmd phy_db_cmd;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = PHY_DB_CMD,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sending PHY-DB hcmd of type %d, of length %d\n",
|
||||
type, length);
|
||||
|
||||
/* Set phy db cmd variables */
|
||||
phy_db_cmd.type = cpu_to_le16(type);
|
||||
phy_db_cmd.length = cpu_to_le16(length);
|
||||
|
||||
/* Set hcmd variables */
|
||||
cmd.data[0] = &phy_db_cmd;
|
||||
cmd.len[0] = sizeof(struct iwl_phy_db_cmd);
|
||||
cmd.data[1] = data;
|
||||
cmd.len[1] = length;
|
||||
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
|
||||
|
||||
return iwl_trans_send_cmd(phy_db->trans, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_phy_db_send_all_channel_groups(
|
||||
struct iwl_phy_db *phy_db,
|
||||
enum iwl_phy_db_section_type type,
|
||||
u8 max_ch_groups)
|
||||
{
|
||||
u16 i;
|
||||
int err;
|
||||
struct iwl_phy_db_entry *entry;
|
||||
|
||||
/* Send all the channel specific groups to operational fw */
|
||||
for (i = 0; i < max_ch_groups; i++) {
|
||||
entry = iwl_phy_db_get_section(phy_db,
|
||||
type,
|
||||
i);
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
/* Send the requested PHY DB section */
|
||||
err = iwl_send_phy_db_cmd(phy_db,
|
||||
type,
|
||||
entry->size,
|
||||
entry->data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Can't SEND phy_db section %d (%d), err %d",
|
||||
type, i, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sent PHY_DB HCMD, type = %d num = %d",
|
||||
type, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
|
||||
{
|
||||
u8 *data = NULL;
|
||||
u16 size = 0;
|
||||
int err;
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Sending phy db data and configuration to runtime image\n");
|
||||
|
||||
/* Send PHY DB CFG section */
|
||||
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CFG,
|
||||
&data, &size, 0);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans, "Cannot get Phy DB cfg section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CFG, size, data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send HCMD of Phy DB cfg section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CALIB_NCH,
|
||||
&data, &size, 0);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot get Phy DB non specific channel section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CALIB_NCH, size, data);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send HCMD of Phy DB non specific channel section\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send all the TXP channel specific data */
|
||||
err = iwl_phy_db_send_all_channel_groups(phy_db,
|
||||
IWL_PHY_DB_CALIB_CHG_PAPD,
|
||||
IWL_NUM_PAPD_CH_GROUPS);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send channel specific PAPD groups");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send all the TXP channel specific data */
|
||||
err = iwl_phy_db_send_all_channel_groups(phy_db,
|
||||
IWL_PHY_DB_CALIB_CHG_TXP,
|
||||
IWL_NUM_TXP_CH_GROUPS);
|
||||
if (err) {
|
||||
IWL_ERR(phy_db->trans,
|
||||
"Cannot send channel specific TX power groups");
|
||||
return err;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"Finished sending phy db non channel data\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_phy_db_data);
|
82
drivers/net/wireless/iwlwifi/iwl-phy-db.h
Normal file
82
drivers/net/wireless/iwlwifi/iwl-phy-db.h
Normal file
@ -0,0 +1,82 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __IWL_PHYDB_H__
|
||||
#define __IWL_PHYDB_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans);
|
||||
|
||||
void iwl_phy_db_free(struct iwl_phy_db *phy_db);
|
||||
|
||||
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
gfp_t alloc_ctx);
|
||||
|
||||
|
||||
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db);
|
||||
|
||||
#endif /* __IWL_PHYDB_H__ */
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -97,6 +97,9 @@
|
||||
|
||||
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
|
||||
|
||||
/* Device system time */
|
||||
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
|
||||
|
||||
/**
|
||||
* Tx Scheduler
|
||||
*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user