Major changes:

iwlwifi:
 
 * new Tx power firmware API
 * bump max firmware API to 17
 * fix bug in debug prints
 * static checker fix
 * fix unused defines
 * fix command list on newest firmware
 
 brcmfmac:
 
 * support NVRAM loading for bcm47xx platform
 * new debugfs entry for msgbuf protocol layer used with PCIe devices
 
 ath10k:
 
 * add spectral scan support for qca99x0
 * add qca6164 support
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQEcBAABAgAGBQJV3dEKAAoJEG4XJFUm622bKpcH/2+9lcdUY0xplYPOA+eXIJoT
 lA7fvFzm3Ez17OPOu+RCSYGnsiYHW47ayCdKqBcVkVIiE5kiRaztvDL7NpCN1mCY
 SIJgixcL0aRinDqc2HZBJ2dG1AUeM7p3SxupuHFovtI2FBs8O+sWcx7/tJ26+f+Y
 tSRwcZkWKNUOwqjQckFfD/k5PpAo06hxg8Zw85N+qNhWB8NyVgIZqHID1vOwQc02
 rtqHl0BZxz2fKmsAeRKpZGlxFqYwc2Y/QT5YLgaOEDQ+gmoUsJKHUIge4fL7zTTG
 I6UUTUbtu83SMKTAeg6BztM+JklEZRNRL5VLboE36dSmSsUBbZxi/WKf+OG70SE=
 =W1bH
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-for-davem-2015-08-26' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
Major changes:

iwlwifi:

* new Tx power firmware API
* bump max firmware API to 17
* fix bug in debug prints
* static checker fix
* fix unused defines
* fix command list on newest firmware

brcmfmac:

* support NVRAM loading for bcm47xx platform
* new debugfs entry for msgbuf protocol layer used with PCIe devices

ath10k:

* add spectral scan support for qca99x0
* add qca6164 support
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-08-27 11:25:56 -07:00
commit 395250e483
37 changed files with 692 additions and 195 deletions

View File

@ -53,6 +53,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 7,
.has_shifted_cc_wraparound = true,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.fw = {
.dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE,
@ -68,6 +69,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.fw = {
.dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE,
@ -83,6 +85,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.fw = {
.dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE,
@ -98,6 +101,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.fw = {
/* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR,
@ -115,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 7,
.otp_exe_param = 0x00000700,
.continuous_frag_desc = true,
.channel_counters_freq_hz = 150000,
.fw = {
.dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE,
@ -231,6 +236,17 @@ static int ath10k_init_configure_target(struct ath10k *ar)
return ret;
}
/* Some devices have a special sanity check that verifies the PCI
* Device ID is written to this host interest var. It is known to be
* required to boot QCA6164.
*/
ret = ath10k_bmi_write32(ar, hi_hci_uart_pwr_mgmt_params_ext,
ar->dev_id);
if (ret) {
ath10k_err(ar, "failed to set pwr_mgmt_params: %d\n", ret);
return ret;
}
return 0;
}
@ -1411,13 +1427,13 @@ int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
void ath10k_core_stop(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
ath10k_debug_stop(ar);
/* try to suspend target */
if (ar->state != ATH10K_STATE_RESTARTING &&
ar->state != ATH10K_STATE_UTF)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_debug_stop(ar);
ath10k_hif_stop(ar);
ath10k_htt_tx_free(&ar->htt);
ath10k_htt_rx_free(&ar->htt);

View File

@ -554,6 +554,7 @@ struct ath10k {
u8 mac_addr[ETH_ALEN];
enum ath10k_hw_rev hw_rev;
u16 dev_id;
u32 chip_id;
u32 target_version;
u8 fw_version_major;
@ -609,6 +610,8 @@ struct ath10k {
*/
bool continuous_frag_desc;
u32 channel_counters_freq_hz;
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;

View File

@ -323,7 +323,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
if (ret) {
ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
goto unlock;
goto free;
}
/* Stat data may exceed htc-wmi buffer limit. In such case firmware
@ -386,7 +386,6 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
ath10k_debug_fw_stats_peers_free(&stats.peers);
unlock:
spin_unlock_bh(&ar->data_lock);
}

View File

@ -145,8 +145,10 @@ int ath10k_htc_send(struct ath10k_htc *htc,
skb_cb->eid = eid;
skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
ret = dma_mapping_error(dev, skb_cb->paddr);
if (ret)
if (ret) {
ret = -EIO;
goto err_credits;
}
sg_item.transfer_id = ep->eid;
sg_item.transfer_context = skb;

View File

@ -442,8 +442,10 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
DMA_TO_DEVICE);
res = dma_mapping_error(dev, skb_cb->paddr);
if (res)
if (res) {
res = -EIO;
goto err_free_txdesc;
}
skb_put(txdesc, len);
cmd = (struct htt_cmd *)txdesc->data;
@ -533,8 +535,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
DMA_TO_DEVICE);
res = dma_mapping_error(dev, skb_cb->paddr);
if (res)
if (res) {
res = -EIO;
goto err_free_txbuf;
}
switch (skb_cb->txmode) {
case ATH10K_HW_TXRX_RAW:

View File

@ -152,6 +152,6 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
cc -= cc_prev - cc_fix;
rcc -= rcc_prev;
survey->time = CCNT_TO_MSEC(cc);
survey->time_busy = CCNT_TO_MSEC(rcc);
survey->time = CCNT_TO_MSEC(ar, cc);
survey->time_busy = CCNT_TO_MSEC(ar, rcc);
}

View File

@ -552,8 +552,7 @@ enum ath10k_hw_rate_cck {
#define SCRATCH_3_ADDRESS ar->regs->scratch_3_address
#define CPU_INTR_ADDRESS 0x0010
/* Cycle counters are running at 88MHz */
#define CCNT_TO_MSEC(x) ((x) / 88000)
#define CCNT_TO_MSEC(ar, x) ((x) / ar->hw_params.channel_counters_freq_hz)
/* Firmware indications to the Host via SCRATCH_3 register. */
#define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address

View File

@ -247,6 +247,10 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
if (WARN_ON(arvif->vif->type != NL80211_IFTYPE_AP &&
arvif->vif->type != NL80211_IFTYPE_ADHOC))
return -EINVAL;
spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find(ar, arvif->vdev_id, addr);
spin_unlock_bh(&ar->data_lock);
@ -258,21 +262,34 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
if (arvif->wep_keys[i] == NULL)
continue;
flags = 0;
flags |= WMI_KEY_PAIRWISE;
switch (arvif->vif->type) {
case NL80211_IFTYPE_AP:
flags = WMI_KEY_PAIRWISE;
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
addr, flags);
if (ret < 0)
return ret;
if (arvif->def_wep_key_idx == i)
flags |= WMI_KEY_TX_USAGE;
flags = 0;
flags |= WMI_KEY_GROUP;
ret = ath10k_install_key(arvif, arvif->wep_keys[i],
SET_KEY, addr, flags);
if (ret < 0)
return ret;
break;
case NL80211_IFTYPE_ADHOC:
ret = ath10k_install_key(arvif, arvif->wep_keys[i],
SET_KEY, addr,
WMI_KEY_PAIRWISE);
if (ret < 0)
return ret;
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
addr, flags);
if (ret < 0)
return ret;
ret = ath10k_install_key(arvif, arvif->wep_keys[i],
SET_KEY, addr, WMI_KEY_GROUP);
if (ret < 0)
return ret;
break;
default:
WARN_ON(1);
return -EINVAL;
}
spin_lock_bh(&ar->data_lock);
peer->keys[i] = arvif->wep_keys[i];
@ -287,6 +304,9 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
*
* FIXME: Revisit. Perhaps this can be done in a less hacky way.
*/
if (arvif->vif->type != NL80211_IFTYPE_ADHOC)
return 0;
if (arvif->def_wep_key_idx == -1)
return 0;
@ -2999,6 +3019,8 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason)
IEEE80211_IFACE_ITER_RESUME_ALL,
ath10k_mac_tx_unlock_iter,
ar);
ieee80211_wake_queue(ar->hw, ar->hw->offchannel_tx_hw_queue);
}
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason)
@ -4122,7 +4144,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
if (ar->num_peers >= ar->max_num_peers) {
ath10k_warn(ar, "refusing vdev creation due to insufficient peer entry resources in firmware\n");
return -ENOBUFS;
ret = -ENOBUFS;
goto err;
}
if (ar->free_vdev_map == 0) {
@ -4340,6 +4363,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
}
}
spin_lock_bh(&ar->htt.tx_lock);
if (!ar->tx_paused)
ieee80211_wake_queue(ar->hw, arvif->vdev_id);
spin_unlock_bh(&ar->htt.tx_lock);
mutex_unlock(&ar->conf_mutex);
return 0;

View File

@ -58,11 +58,13 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
#define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
#define QCA988X_2_0_DEVICE_ID (0x003c)
#define QCA6164_2_1_DEVICE_ID (0x0041)
#define QCA6174_2_1_DEVICE_ID (0x003e)
#define QCA99X0_2_0_DEVICE_ID (0x0040)
static const struct pci_device_id ath10k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
{0}
@ -74,11 +76,19 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
* because of that.
*/
{ QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV },
{ QCA6164_2_1_DEVICE_ID, QCA6174_HW_2_1_CHIP_ID_REV },
{ QCA6164_2_1_DEVICE_ID, QCA6174_HW_2_2_CHIP_ID_REV },
{ QCA6164_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV },
{ QCA6164_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV },
{ QCA6164_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_1_CHIP_ID_REV },
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_2_CHIP_ID_REV },
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV },
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV },
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
};
@ -1667,8 +1677,10 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
req_paddr = dma_map_single(ar->dev, treq, req_len, DMA_TO_DEVICE);
ret = dma_mapping_error(ar->dev, req_paddr);
if (ret)
if (ret) {
ret = -EIO;
goto err_dma;
}
if (resp && resp_len) {
tresp = kzalloc(*resp_len, GFP_KERNEL);
@ -1680,8 +1692,10 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
resp_paddr = dma_map_single(ar->dev, tresp, *resp_len,
DMA_FROM_DEVICE);
ret = dma_mapping_error(ar->dev, resp_paddr);
if (ret)
if (ret) {
ret = EIO;
goto err_req;
}
xfer.wait_for_resp = true;
xfer.resp_len = 0;
@ -1810,6 +1824,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
case QCA988X_2_0_DEVICE_ID:
case QCA99X0_2_0_DEVICE_ID:
return 1;
case QCA6164_2_1_DEVICE_ID:
case QCA6174_2_1_DEVICE_ID:
switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) {
case QCA6174_HW_1_0_CHIP_ID_REV:
@ -2898,6 +2913,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
case QCA988X_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA988X;
break;
case QCA6164_2_1_DEVICE_ID:
case QCA6174_2_1_DEVICE_ID:
hw_rev = ATH10K_HW_QCA6174;
break;
@ -2922,6 +2938,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ar_pci->pdev = pdev;
ar_pci->dev = &pdev->dev;
ar_pci->ar = ar;
ar->dev_id = pci_dev->device;
if (pdev->subsystem_vendor || pdev->subsystem_device)
scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id),

View File

@ -57,7 +57,7 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
}
int ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
@ -73,6 +73,15 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
return -EINVAL;
/* qca99x0 reports bin size as 68 bytes (64 bytes + 4 bytes) in
* report mode 2. First 64 bytes carries inband tones (-32 to +31)
* and last 4 byte carries band edge detection data (+32) mainly
* used in radar detection purpose. Strip last 4 byte to make bin
* size is valid one.
*/
if (bin_len == 68)
bin_len -= 4;
reg0 = __le32_to_cpu(fftr->reg0);
reg1 = __le32_to_cpu(fftr->reg1);
@ -118,15 +127,14 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
freq1 = __le16_to_cpu(phyerr->freq1);
freq2 = __le16_to_cpu(phyerr->freq2);
freq1 = phyerr->freq1;
freq2 = phyerr->freq2;
fft_sample->freq1 = __cpu_to_be16(freq1);
fft_sample->freq2 = __cpu_to_be16(freq2);
chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
fft_sample->noise = __cpu_to_be16(
__le16_to_cpu(phyerr->nf_chains[chain_idx]));
fft_sample->noise = __cpu_to_be16(phyerr->nf_chains[chain_idx]);
bins = (u8 *)fftr;
bins += sizeof(*fftr);

View File

@ -47,7 +47,7 @@ enum ath10k_spectral_mode {
#ifdef CONFIG_ATH10K_DEBUGFS
int ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf);
int ath10k_spectral_start(struct ath10k *ar);
@ -59,7 +59,7 @@ void ath10k_spectral_destroy(struct ath10k *ar);
static inline int
ath10k_spectral_process_fft(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{

View File

@ -37,8 +37,10 @@ struct wmi_ops {
struct wmi_peer_kick_ev_arg *arg);
int (*pull_swba)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg);
int (*pull_phyerr_hdr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg);
int (*pull_svc_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg);
int (*pull_rdy)(struct ath10k *ar, struct sk_buff *skb,
@ -261,13 +263,23 @@ ath10k_wmi_pull_swba(struct ath10k *ar, struct sk_buff *skb,
}
static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
ath10k_wmi_pull_phyerr_hdr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr_hdr)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_phyerr_hdr(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_phyerr(ar, skb, arg);
return ar->wmi.ops->pull_phyerr(ar, phyerr_buf, left_len, arg);
}
static inline int

View File

@ -838,9 +838,9 @@ static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
return 0;
}
static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
static int ath10k_wmi_tlv_op_pull_phyerr_ev_hdr(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
const void **tb;
const struct wmi_tlv_phyerr_ev *ev;
@ -862,10 +862,10 @@ static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
return -EPROTO;
}
arg->num_phyerrs = ev->num_phyerrs;
arg->tsf_l32 = ev->tsf_l32;
arg->tsf_u32 = ev->tsf_u32;
arg->buf_len = ev->buf_len;
arg->num_phyerrs = __le32_to_cpu(ev->num_phyerrs);
arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
arg->buf_len = __le32_to_cpu(ev->buf_len);
arg->phyerrs = phyerrs;
kfree(tb);
@ -3407,7 +3407,8 @@ static const struct wmi_ops wmi_tlv_ops = {
.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
.pull_phyerr = ath10k_wmi_tlv_op_pull_phyerr_ev,
.pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,

View File

@ -2412,8 +2412,10 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
ar->ch_info_can_report_survey = true;
}
ar->survey_last_rx_clear_count = rx_clear_count;
ar->survey_last_cycle_count = cycle_count;
if (!(cmd_flags & WMI_CHAN_INFO_FLAG_PRE_COMPLETE)) {
ar->survey_last_rx_clear_count = rx_clear_count;
ar->survey_last_cycle_count = cycle_count;
}
exit:
spin_unlock_bh(&ar->data_lock);
@ -3236,6 +3238,7 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ath10k_warn(ar, "failed to map beacon: %d\n",
ret);
dev_kfree_skb_any(bcn);
ret = -EIO;
goto skip;
}
@ -3269,7 +3272,7 @@ void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb)
}
static void ath10k_dfs_radar_report(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_radar_report *rr,
u64 tsf)
{
@ -3313,7 +3316,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
}
/* report event to DFS pattern detector */
tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
tsf32l = phyerr->tsf_timestamp;
tsf64 = tsf & (~0xFFFFFFFFULL);
tsf64 |= tsf32l;
@ -3358,7 +3361,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
}
static int ath10k_dfs_fft_report(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
const struct phyerr_fft_report *fftr,
u64 tsf)
{
@ -3396,7 +3399,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar,
}
void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
@ -3405,11 +3408,11 @@ void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct phyerr_fft_report *fftr;
const u8 *tlv_buf;
buf_len = __le32_to_cpu(phyerr->buf_len);
buf_len = phyerr->buf_len;
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
"wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
phyerr->phy_err_code, phyerr->rssi_combined,
__le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
phyerr->tsf_timestamp, tsf, buf_len);
/* Skip event if DFS disabled */
if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
@ -3461,7 +3464,7 @@ void ath10k_wmi_event_dfs(struct ath10k *ar,
}
void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
@ -3470,7 +3473,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct phyerr_fft_report *fftr;
size_t fftr_len;
buf_len = __le32_to_cpu(phyerr->buf_len);
buf_len = phyerr->buf_len;
while (i < buf_len) {
if (i + sizeof(*tlv) > buf_len) {
@ -3514,65 +3517,169 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
}
}
static int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
static int ath10k_wmi_op_pull_phyerr_ev_hdr(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
struct wmi_phyerr_event *ev = (void *)skb->data;
if (skb->len < sizeof(*ev))
return -EPROTO;
arg->num_phyerrs = ev->num_phyerrs;
arg->tsf_l32 = ev->tsf_l32;
arg->tsf_u32 = ev->tsf_u32;
arg->buf_len = __cpu_to_le32(skb->len - sizeof(*ev));
arg->num_phyerrs = __le32_to_cpu(ev->num_phyerrs);
arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
arg->buf_len = skb->len - sizeof(*ev);
arg->phyerrs = ev->phyerrs;
return 0;
}
static int ath10k_wmi_10_4_op_pull_phyerr_ev_hdr(struct ath10k *ar,
struct sk_buff *skb,
struct wmi_phyerr_hdr_arg *arg)
{
struct wmi_10_4_phyerr_event *ev = (void *)skb->data;
if (skb->len < sizeof(*ev))
return -EPROTO;
/* 10.4 firmware always reports only one phyerr */
arg->num_phyerrs = 1;
arg->tsf_l32 = __le32_to_cpu(ev->tsf_l32);
arg->tsf_u32 = __le32_to_cpu(ev->tsf_u32);
arg->buf_len = skb->len;
arg->phyerrs = skb->data;
return 0;
}
int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar,
const void *phyerr_buf,
int left_len,
struct wmi_phyerr_ev_arg *arg)
{
const struct wmi_phyerr *phyerr = phyerr_buf;
int i;
if (left_len < sizeof(*phyerr)) {
ath10k_warn(ar, "wrong phyerr event head len %d (need: >=%zd)\n",
left_len, sizeof(*phyerr));
return -EINVAL;
}
arg->tsf_timestamp = __le32_to_cpu(phyerr->tsf_timestamp);
arg->freq1 = __le16_to_cpu(phyerr->freq1);
arg->freq2 = __le16_to_cpu(phyerr->freq2);
arg->rssi_combined = phyerr->rssi_combined;
arg->chan_width_mhz = phyerr->chan_width_mhz;
arg->buf_len = __le32_to_cpu(phyerr->buf_len);
arg->buf = phyerr->buf;
arg->hdr_len = sizeof(*phyerr);
for (i = 0; i < 4; i++)
arg->nf_chains[i] = __le16_to_cpu(phyerr->nf_chains[i]);
switch (phyerr->phy_err_code) {
case PHY_ERROR_GEN_SPECTRAL_SCAN:
arg->phy_err_code = PHY_ERROR_SPECTRAL_SCAN;
break;
case PHY_ERROR_GEN_FALSE_RADAR_EXT:
arg->phy_err_code = PHY_ERROR_FALSE_RADAR_EXT;
break;
case PHY_ERROR_GEN_RADAR:
arg->phy_err_code = PHY_ERROR_RADAR;
break;
default:
arg->phy_err_code = PHY_ERROR_UNKNOWN;
break;
}
return 0;
}
static int ath10k_wmi_10_4_op_pull_phyerr_ev(struct ath10k *ar,
const void *phyerr_buf,
int left_len,
struct wmi_phyerr_ev_arg *arg)
{
const struct wmi_10_4_phyerr_event *phyerr = phyerr_buf;
u32 phy_err_mask;
int i;
if (left_len < sizeof(*phyerr)) {
ath10k_warn(ar, "wrong phyerr event head len %d (need: >=%zd)\n",
left_len, sizeof(*phyerr));
return -EINVAL;
}
arg->tsf_timestamp = __le32_to_cpu(phyerr->tsf_timestamp);
arg->freq1 = __le16_to_cpu(phyerr->freq1);
arg->freq2 = __le16_to_cpu(phyerr->freq2);
arg->rssi_combined = phyerr->rssi_combined;
arg->chan_width_mhz = phyerr->chan_width_mhz;
arg->buf_len = __le32_to_cpu(phyerr->buf_len);
arg->buf = phyerr->buf;
arg->hdr_len = sizeof(*phyerr);
for (i = 0; i < 4; i++)
arg->nf_chains[i] = __le16_to_cpu(phyerr->nf_chains[i]);
phy_err_mask = __le32_to_cpu(phyerr->phy_err_mask[0]);
if (phy_err_mask & PHY_ERROR_10_4_SPECTRAL_SCAN_MASK)
arg->phy_err_code = PHY_ERROR_SPECTRAL_SCAN;
else if (phy_err_mask & PHY_ERROR_10_4_RADAR_MASK)
arg->phy_err_code = PHY_ERROR_RADAR;
else
arg->phy_err_code = PHY_ERROR_UNKNOWN;
return 0;
}
void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_phyerr_ev_arg arg = {};
const struct wmi_phyerr *phyerr;
struct wmi_phyerr_hdr_arg hdr_arg = {};
struct wmi_phyerr_ev_arg phyerr_arg = {};
const void *phyerr;
u32 count, i, buf_len, phy_err_code;
u64 tsf;
int left_len, ret;
ATH10K_DFS_STAT_INC(ar, phy_errors);
ret = ath10k_wmi_pull_phyerr(ar, skb, &arg);
ret = ath10k_wmi_pull_phyerr_hdr(ar, skb, &hdr_arg);
if (ret) {
ath10k_warn(ar, "failed to parse phyerr event: %d\n", ret);
ath10k_warn(ar, "failed to parse phyerr event hdr: %d\n", ret);
return;
}
left_len = __le32_to_cpu(arg.buf_len);
/* Check number of included events */
count = __le32_to_cpu(arg.num_phyerrs);
count = hdr_arg.num_phyerrs;
tsf = __le32_to_cpu(arg.tsf_u32);
left_len = hdr_arg.buf_len;
tsf = hdr_arg.tsf_u32;
tsf <<= 32;
tsf |= __le32_to_cpu(arg.tsf_l32);
tsf |= hdr_arg.tsf_l32;
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event phyerr count %d tsf64 0x%llX\n",
count, tsf);
phyerr = arg.phyerrs;
phyerr = hdr_arg.phyerrs;
for (i = 0; i < count; i++) {
/* Check if we can read event header */
if (left_len < sizeof(*phyerr)) {
ath10k_warn(ar, "single event (%d) wrong head len\n",
ret = ath10k_wmi_pull_phyerr(ar, phyerr, left_len, &phyerr_arg);
if (ret) {
ath10k_warn(ar, "failed to parse phyerr event (%d)\n",
i);
return;
}
left_len -= sizeof(*phyerr);
buf_len = __le32_to_cpu(phyerr->buf_len);
phy_err_code = phyerr->phy_err_code;
left_len -= phyerr_arg.hdr_len;
buf_len = phyerr_arg.buf_len;
phy_err_code = phyerr_arg.phy_err_code;
if (left_len < buf_len) {
ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
@ -3583,20 +3690,20 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
switch (phy_err_code) {
case PHY_ERROR_RADAR:
ath10k_wmi_event_dfs(ar, phyerr, tsf);
ath10k_wmi_event_dfs(ar, &phyerr_arg, tsf);
break;
case PHY_ERROR_SPECTRAL_SCAN:
ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
ath10k_wmi_event_spectral_scan(ar, &phyerr_arg, tsf);
break;
case PHY_ERROR_FALSE_RADAR_EXT:
ath10k_wmi_event_dfs(ar, phyerr, tsf);
ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
ath10k_wmi_event_dfs(ar, &phyerr_arg, tsf);
ath10k_wmi_event_spectral_scan(ar, &phyerr_arg, tsf);
break;
default:
break;
}
phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
phyerr = phyerr + phyerr_arg.hdr_len + buf_len;
}
}
@ -4488,6 +4595,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10_4_CHAN_INFO_EVENTID:
ath10k_wmi_event_chan_info(ar, skb);
break;
case WMI_10_4_PHYERR_EVENTID:
ath10k_wmi_event_phyerr(ar, skb);
break;
case WMI_10_4_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
break;
@ -6195,6 +6305,7 @@ static const struct wmi_ops wmi_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
@ -6266,6 +6377,7 @@ static const struct wmi_ops wmi_10_1_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
@ -6331,6 +6443,7 @@ static const struct wmi_ops wmi_10_2_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
@ -6392,6 +6505,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
@ -6447,6 +6561,8 @@ static const struct wmi_ops wmi_10_4_ops = {
.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
.pull_swba = ath10k_wmi_10_4_op_pull_swba_ev,
.pull_phyerr_hdr = ath10k_wmi_10_4_op_pull_phyerr_ev_hdr,
.pull_phyerr = ath10k_wmi_10_4_op_pull_phyerr_ev,
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
.get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
@ -6466,6 +6582,8 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
.gen_peer_create = ath10k_wmi_op_gen_peer_create,
.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
@ -6482,6 +6600,10 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
/* shared with 10.2 */
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,

View File

@ -2973,9 +2973,19 @@ struct wmi_10_4_mgmt_rx_event {
#define WMI_RX_STATUS_ERR_MIC 0x10
#define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20
#define PHY_ERROR_SPECTRAL_SCAN 0x26
#define PHY_ERROR_FALSE_RADAR_EXT 0x24
#define PHY_ERROR_RADAR 0x05
#define PHY_ERROR_GEN_SPECTRAL_SCAN 0x26
#define PHY_ERROR_GEN_FALSE_RADAR_EXT 0x24
#define PHY_ERROR_GEN_RADAR 0x05
#define PHY_ERROR_10_4_RADAR_MASK 0x4
#define PHY_ERROR_10_4_SPECTRAL_SCAN_MASK 0x4000000
enum phy_err_type {
PHY_ERROR_UNKNOWN,
PHY_ERROR_SPECTRAL_SCAN,
PHY_ERROR_FALSE_RADAR_EXT,
PHY_ERROR_RADAR
};
struct wmi_phyerr {
__le32 tsf_timestamp;
@ -2998,6 +3008,23 @@ struct wmi_phyerr_event {
struct wmi_phyerr phyerrs[0];
} __packed;
struct wmi_10_4_phyerr_event {
__le32 tsf_l32;
__le32 tsf_u32;
__le16 freq1;
__le16 freq2;
u8 rssi_combined;
u8 chan_width_mhz;
u8 phy_err_code;
u8 rsvd0;
__le32 rssi_chains[4];
__le16 nf_chains[4];
__le32 phy_err_mask[2];
__le32 tsf_timestamp;
__le32 buf_len;
u8 buf[0];
} __packed;
#define PHYERR_TLV_SIG 0xBB
#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB
#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8
@ -5590,6 +5617,7 @@ struct wmi_peer_sta_kickout_event {
} __packed;
#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
#define WMI_CHAN_INFO_FLAG_PRE_COMPLETE BIT(1)
/* Beacon filter wmi command info */
#define BCN_FLT_MAX_SUPPORTED_IES 256
@ -5788,11 +5816,24 @@ struct wmi_swba_ev_arg {
};
struct wmi_phyerr_ev_arg {
__le32 num_phyerrs;
__le32 tsf_l32;
__le32 tsf_u32;
__le32 buf_len;
const struct wmi_phyerr *phyerrs;
u32 tsf_timestamp;
u16 freq1;
u16 freq2;
u8 rssi_combined;
u8 chan_width_mhz;
u8 phy_err_code;
u16 nf_chains[4];
u32 buf_len;
const u8 *buf;
u8 hdr_len;
};
struct wmi_phyerr_hdr_arg {
u32 num_phyerrs;
u32 tsf_l32;
u32 tsf_u32;
u32 buf_len;
const void *phyerrs;
};
struct wmi_svc_rdy_ev_arg {
@ -6070,9 +6111,9 @@ void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct wmi_phyerr *phyerr, u64 tsf);
struct wmi_phyerr_ev_arg *phyerr, u64 tsf);
void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
struct wmi_phyerr_ev_arg *phyerr,
u64 tsf);
void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb);
@ -6101,5 +6142,6 @@ void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf,
int left_len, struct wmi_phyerr_ev_arg *arg);
#endif /* _WMI_H_ */

View File

@ -794,8 +794,11 @@ void ath9k_htc_ani_work(struct work_struct *work)
common->ani.longcal_timer = timestamp;
}
/* Short calibration applies only while caldone is false */
if (!common->ani.caldone) {
/*
* Short calibration applies only while caldone
* is false or -ETIMEDOUT
*/
if (common->ani.caldone <= 0) {
if ((timestamp - common->ani.shortcal_timer) >=
short_cal_interval) {
shortcal = true;
@ -844,7 +847,11 @@ void ath9k_htc_ani_work(struct work_struct *work)
*/
cal_interval = ATH_LONG_CALINTERVAL;
cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
if (!common->ani.caldone)
/*
* Short calibration applies only while caldone
* is false or -ETIMEDOUT
*/
if (common->ani.caldone <= 0)
cal_interval = min(cal_interval, (u32)short_cal_interval);
ieee80211_queue_delayed_work(common->hw, &priv->ani_work,

View File

@ -806,7 +806,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
u16 reply_id, void *reply, u8 reply_size, int to_msec)
{
int rc;
int remain;
unsigned long remain;
mutex_lock(&wil->wmi_mutex);

View File

@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 len)
return NULL;
}
static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif,
enum nl80211_iftype new_type)
{
int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
if (pos == vif)
iftype_num[new_type]++;
else
iftype_num[pos->wdev.iftype]++;
return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
}
static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype new_type)
{
int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
iftype_num[pos->wdev.iftype]++;
iftype_num[new_type]++;
return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
}
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
struct brcmf_wsec_key_le *key_le)
@ -663,8 +693,14 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
struct vif_params *params)
{
struct wireless_dev *wdev;
int err;
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
if (err) {
brcmf_err("iface validation failed: err=%d\n", err);
return ERR_PTR(err);
}
switch (type) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_STATION:
@ -823,8 +859,12 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 ap = 0;
s32 err = 0;
brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
if (err) {
brcmf_err("iface validation failed: err=%d\n", err);
return err;
}
switch (type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
@ -5695,63 +5735,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
}
};
/**
* brcmf_setup_ifmodes() - determine interface modes and combinations.
*
* @wiphy: wiphy object.
* @ifp: interface object needed for feat module api.
*
* The interface modes and combinations are determined dynamically here
* based on firmware functionality.
*
* no p2p and no mbss:
*
* #STA <= 1, #AP <= 1, channels = 1, 2 total
*
* no p2p and mbss:
*
* #STA <= 1, #AP <= 1, channels = 1, 2 total
* #AP <= 4, matching BI, channels = 1, 4 total
*
* p2p, no mchan, and mbss:
*
* #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
* #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
* #AP <= 4, matching BI, channels = 1, 4 total
*
* p2p, mchan, and mbss:
*
* #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
* #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
* #AP <= 4, matching BI, channels = 1, 4 total
*/
static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
{
struct ieee80211_iface_combination *combo = NULL;
struct ieee80211_iface_limit *limits = NULL;
int i = 0, max_iface_cnt;
struct ieee80211_iface_limit *c0_limits = NULL;
struct ieee80211_iface_limit *p2p_limits = NULL;
struct ieee80211_iface_limit *mbss_limits = NULL;
bool mbss, p2p;
int i, c, n_combos;
combo = kzalloc(sizeof(*combo), GFP_KERNEL);
mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
n_combos = 1 + !!p2p + !!mbss;
combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
if (!combo)
goto err;
limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
if (!limits)
c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
if (!c0_limits)
goto err;
if (p2p) {
p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
if (!p2p_limits)
goto err;
}
if (mbss) {
mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
if (!mbss_limits)
goto err;
}
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
combo->num_different_channels = 2;
else
combo->num_different_channels = 1;
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
limits[i].max = 1;
limits[i++].types = BIT(NL80211_IFTYPE_STATION);
limits[i].max = 4;
limits[i++].types = BIT(NL80211_IFTYPE_AP);
max_iface_cnt = 5;
} else {
limits[i].max = 2;
limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP);
max_iface_cnt = 2;
}
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
c = 0;
i = 0;
combo[c].num_different_channels = 1;
c0_limits[i].max = 1;
c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
if (p2p) {
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
combo[c].num_different_channels = 2;
wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_DEVICE);
limits[i].max = 1;
limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
limits[i].max = 1;
limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
max_iface_cnt += 2;
c0_limits[i].max = 1;
c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
c0_limits[i].max = 1;
c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
} else {
c0_limits[i].max = 1;
c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
}
combo->max_interfaces = max_iface_cnt;
combo->limits = limits;
combo->n_limits = i;
combo[c].max_interfaces = i;
combo[c].n_limits = i;
combo[c].limits = c0_limits;
if (p2p) {
c++;
i = 0;
combo[c].num_different_channels = 1;
p2p_limits[i].max = 1;
p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
p2p_limits[i].max = 1;
p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
p2p_limits[i].max = 1;
p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);
p2p_limits[i].max = 1;
p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
combo[c].max_interfaces = i;
combo[c].n_limits = i;
combo[c].limits = p2p_limits;
}
if (mbss) {
c++;
combo[c].beacon_int_infra_match = true;
combo[c].num_different_channels = 1;
mbss_limits[0].max = 4;
mbss_limits[0].types = BIT(NL80211_IFTYPE_AP);
combo[c].max_interfaces = 4;
combo[c].n_limits = 1;
combo[c].limits = mbss_limits;
}
wiphy->n_iface_combinations = n_combos;
wiphy->iface_combinations = combo;
wiphy->n_iface_combinations = 1;
return 0;
err:
kfree(limits);
kfree(c0_limits);
kfree(p2p_limits);
kfree(mbss_limits);
kfree(combo);
return -ENOMEM;
}
@ -5786,7 +5895,9 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy)
static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
{
struct brcmf_pub *drvr = ifp->drvr;
const struct ieee80211_iface_combination *combo;
struct ieee80211_supported_band *band;
u16 max_interfaces = 0;
__le32 bandlist[3];
u32 n_bands;
int err, i;
@ -5799,8 +5910,13 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
if (err)
return err;
for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
i < ARRAY_SIZE(drvr->addresses); i++) {
for (i = 0, combo = wiphy->iface_combinations;
i < wiphy->n_iface_combinations; i++, combo++) {
max_interfaces = max(max_interfaces, combo->max_interfaces);
}
for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);
i++) {
u8 *addr = drvr->addresses[i].addr;
memcpy(addr, drvr->mac, ETH_ALEN);
@ -6073,11 +6189,15 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
static void brcmf_free_wiphy(struct wiphy *wiphy)
{
int i;
if (!wiphy)
return;
if (wiphy->iface_combinations)
kfree(wiphy->iface_combinations->limits);
if (wiphy->iface_combinations) {
for (i = 0; i < wiphy->n_iface_combinations; i++)
kfree(wiphy->iface_combinations[i].limits);
}
kfree(wiphy->iface_combinations);
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);

View File

@ -19,6 +19,7 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/bcm47xx_nvram.h>
#include "debug.h"
#include "firmware.h"
@ -426,19 +427,33 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
struct brcmf_fw *fwctx = ctx;
u32 nvram_length = 0;
void *nvram = NULL;
u8 *data = NULL;
size_t data_len;
bool raw_nvram;
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail;
if (fw) {
nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
fwctx->domain_nr, fwctx->bus_nr);
release_firmware(fw);
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
if (fw && fw->data) {
data = (u8 *)fw->data;
data_len = fw->size;
raw_nvram = false;
} else {
data = bcm47xx_nvram_get_contents(&data_len);
if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail;
raw_nvram = true;
}
if (data)
nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
fwctx->domain_nr, fwctx->bus_nr);
if (raw_nvram)
bcm47xx_nvram_release_contents(data);
if (fw)
release_firmware(fw);
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail;
fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
kfree(fwctx);
return;
@ -473,15 +488,9 @@ static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
if (!ret)
return;
/* when nvram is optional call .done() callback here */
if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
fwctx->done(fwctx->dev, fw, NULL, 0);
kfree(fwctx);
return;
}
brcmf_fw_request_nvram_done(NULL, fwctx);
return;
/* failed nvram request */
release_firmware(fw);
fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
device_release_driver(fwctx->dev);

View File

@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
spin_lock_irqsave(&flow->block_lock, flags);
ring = flow->rings[flowid];
if (ring->blocked == blocked) {
spin_unlock_irqrestore(&flow->block_lock, flags);
return;
}
ifidx = brcmf_flowring_ifidx_get(flow, flowid);
currently_blocked = false;
for (i = 0; i < flow->nrofrings; i++) {
if (flow->rings[i]) {
if ((flow->rings[i]) && (i != flowid)) {
ring = flow->rings[i];
if ((ring->status == RING_OPEN) &&
(brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
}
}
}
ring->blocked = blocked;
if (currently_blocked == blocked) {
flow->rings[flowid]->blocked = blocked;
if (currently_blocked) {
spin_unlock_irqrestore(&flow->block_lock, flags);
return;
}

View File

@ -85,7 +85,6 @@ struct brcmf_event;
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) \
BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
@ -103,8 +102,7 @@ struct brcmf_event;
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
#define BRCMF_ENUM_DEF(id, val) \
BRCMF_E_##id = (val),
@ -112,7 +110,11 @@ struct brcmf_event;
/* firmware event codes sent by the dongle */
enum brcmf_fweh_event_code {
BRCMF_FWEH_EVENT_ENUM_DEFLIST
BRCMF_E_LAST
/* this determines event mask length which must match
* minimum length check in device firmware so it is
* hard-coded here.
*/
BRCMF_E_LAST = 139
};
#undef BRCMF_ENUM_DEF

View File

@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
}
}
#ifdef DEBUG
static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
{
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
struct brcmf_pub *drvr = bus_if->drvr;
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
struct brcmf_commonring *commonring;
u16 i;
struct brcmf_flowring_ring *ring;
struct brcmf_flowring_hash *hash;
commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n",
commonring->r_ptr, commonring->w_ptr, commonring->depth);
commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
seq_printf(seq, "h2d_rx_submit: rp %4u, wp %4u, depth %4u\n",
commonring->r_ptr, commonring->w_ptr, commonring->depth);
commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
seq_printf(seq, "d2h_ctl_cmplt: rp %4u, wp %4u, depth %4u\n",
commonring->r_ptr, commonring->w_ptr, commonring->depth);
commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
seq_printf(seq, "d2h_tx_cmplt: rp %4u, wp %4u, depth %4u\n",
commonring->r_ptr, commonring->w_ptr, commonring->depth);
commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
seq_printf(seq, "d2h_rx_cmplt: rp %4u, wp %4u, depth %4u\n",
commonring->r_ptr, commonring->w_ptr, commonring->depth);
seq_printf(seq, "\nh2d_flowrings: depth %u\n",
BRCMF_H2D_TXFLOWRING_MAX_ITEM);
seq_puts(seq, "Active flowrings:\n");
hash = msgbuf->flow->hash;
for (i = 0; i < msgbuf->flow->nrofrings; i++) {
if (!msgbuf->flow->rings[i])
continue;
ring = msgbuf->flow->rings[i];
if (ring->status != RING_OPEN)
continue;
commonring = msgbuf->flowrings[i];
hash = &msgbuf->flow->hash[ring->hash_id];
seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n"
" ifidx %u, fifo %u, da %pM\n",
i, commonring->r_ptr, commonring->w_ptr,
skb_queue_len(&ring->skblist), ring->blocked,
hash->ifidx, hash->fifo, hash->mac);
}
return 0;
}
#else
static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
{
return 0;
}
#endif
int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
{
@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
spin_lock_init(&msgbuf->flowring_work_lock);
INIT_LIST_HEAD(&msgbuf->work_queue);
brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
return 0;
fail:

View File

@ -473,7 +473,7 @@ do { \
} while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */
extern const char *const iwl_dvm_cmd_strings[REPLY_MAX];
extern const char *const iwl_dvm_cmd_strings[REPLY_MAX + 1];
static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
{

View File

@ -39,7 +39,7 @@
#define IWL_CMD_ENTRY(x) [x] = #x
const char *const iwl_dvm_cmd_strings[REPLY_MAX] = {
const char *const iwl_dvm_cmd_strings[REPLY_MAX + 1] = {
IWL_CMD_ENTRY(REPLY_ALIVE),
IWL_CMD_ENTRY(REPLY_ERROR),
IWL_CMD_ENTRY(REPLY_ECHO),

View File

@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 16
#define IWL7260_UCODE_API_MAX 17
/* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 12

View File

@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX 16
#define IWL8000_UCODE_API_MAX 17
/* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK 12

View File

@ -259,6 +259,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format
* @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority
* instead of 3.
* @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size
* (command version 3) that supports per-chain limits
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3,
@ -274,6 +276,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19,
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24,
IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27,
};
typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;

View File

@ -949,9 +949,10 @@ static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
int ret, conf_id;
unsigned int conf_id;
int ret;
ret = kstrtoint(buf, 0, &conf_id);
ret = kstrtouint(buf, 0, &conf_id);
if (ret)
return ret;

View File

@ -339,8 +339,13 @@ enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10),
/* BIT(11) reserved */
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
IWL_WOWLAN_WAKEUP_BY_IOAC_MAGIC_PACKET = BIT(13),
IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15),
IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_gtk_status {

View File

@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
*
* 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
@ -33,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -310,17 +312,22 @@ struct iwl_reduce_tx_power_cmd {
__le16 pwr_restriction;
} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
enum iwl_dev_tx_power_cmd_mode {
IWL_TX_POWER_MODE_SET_MAC = 0,
IWL_TX_POWER_MODE_SET_DEVICE = 1,
IWL_TX_POWER_MODE_SET_CHAINS = 2,
}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_2 */;
/**
* struct iwl_dev_tx_power_cmd - TX power reduction command
* REDUCE_TX_POWER_CMD = 0x9f
* @set_mode: 0 - MAC tx power, 1 - device tx power
* struct iwl_dev_tx_power_cmd_v2 - TX power reduction command
* @set_mode: see &enum iwl_dev_tx_power_cmd_mode
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
* @pwr_restriction: TX power restriction in 1/8 dBms.
* @dev_24: device TX power restriction in 1/8 dBms
* @dev_52_low: device TX power restriction upper band - low
* @dev_52_high: device TX power restriction upper band - high
*/
struct iwl_dev_tx_power_cmd {
struct iwl_dev_tx_power_cmd_v2 {
__le32 set_mode;
__le32 mac_context_id;
__le16 pwr_restriction;
@ -329,6 +336,20 @@ struct iwl_dev_tx_power_cmd {
__le16 dev_52_high;
} __packed; /* TX_REDUCED_POWER_API_S_VER_2 */
#define IWL_NUM_CHAIN_LIMITS 2
#define IWL_NUM_SUB_BANDS 5
/**
* struct iwl_dev_tx_power_cmd - TX power reduction command
* @v2: version 2 of the command, embedded here for easier software handling
* @per_chain_restriction: per chain restrictions
*/
struct iwl_dev_tx_power_cmd {
/* v3 is just an extension of v2 - keep this here */
struct iwl_dev_tx_power_cmd_v2 v2;
__le16 per_chain_restriction[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
} __packed; /* TX_REDUCED_POWER_API_S_VER_3 */
#define IWL_DEV_MAX_TX_POWER 0x7FFF
/**

View File

@ -1595,20 +1595,23 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s16 tx_power)
{
struct iwl_dev_tx_power_cmd cmd = {
.set_mode = 0,
.mac_context_id =
.v2.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
.v2.mac_context_id =
cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
.pwr_restriction = cpu_to_le16(8 * tx_power),
.v2.pwr_restriction = cpu_to_le16(8 * tx_power),
};
int len = sizeof(cmd);
if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV))
return iwl_mvm_set_tx_power_old(mvm, vif, tx_power);
if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
cmd.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,
sizeof(cmd), &cmd);
if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_CHAIN))
len = sizeof(cmd.v2);
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,

View File

@ -268,7 +268,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
#undef RX_HANDLER_GRP
#define CMD(x) [x] = #x
static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = {
CMD(MVM_ALIVE),
CMD(REPLY_ERROR),
CMD(INIT_COMPLETE_NOTIF),

View File

@ -349,10 +349,11 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_SCHED) {
WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR);
IWL_DEBUG_SCAN(mvm,
"Scheduled scan %s, EBS status %s, Last line %d, Last iteration %d, Time after last iteration %d\n",
IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",
aborted ? "aborted" : "completed",
iwl_mvm_ebs_status_str(scan_notif->ebs_status),
iwl_mvm_ebs_status_str(scan_notif->ebs_status));
IWL_DEBUG_SCAN(mvm,
"Last line %d, Last iteration %d, Time after last iteration %d\n",
scan_notif->last_schedule_line,
scan_notif->last_schedule_iteration,
__le32_to_cpu(scan_notif->time_after_last_iter));
@ -367,10 +368,11 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
} else if (mvm->scan_status & IWL_MVM_SCAN_SCHED) {
WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_REGULAR);
IWL_DEBUG_SCAN(mvm,
"Scheduled scan %s, EBS status %s, Last line %d, Last iteration %d, Time after last iteration %d (FW)\n",
IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",
aborted ? "aborted" : "completed",
iwl_mvm_ebs_status_str(scan_notif->ebs_status),
iwl_mvm_ebs_status_str(scan_notif->ebs_status));
IWL_DEBUG_SCAN(mvm,
"Last line %d, Last iteration %d, Time after last iteration %d (FW)\n",
scan_notif->last_schedule_line,
scan_notif->last_schedule_iteration,
__le32_to_cpu(scan_notif->time_after_last_iter));
@ -1346,11 +1348,13 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status &= ~mvm->scan_uid_status[uid];
IWL_DEBUG_SCAN(mvm,
"Scan completed, uid %u type %u, status %s, EBS status %s, Last line %d, Last iteration %d, Time from last iteration %d\n",
"Scan completed, uid %u type %u, status %s, EBS status %s\n",
uid, mvm->scan_uid_status[uid],
notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
"completed" : "aborted",
iwl_mvm_ebs_status_str(notif->ebs_status),
iwl_mvm_ebs_status_str(notif->ebs_status));
IWL_DEBUG_SCAN(mvm,
"Last line %d, Last iteration %d, Time from last iteration %d\n",
notif->last_schedule, notif->last_iter,
__le32_to_cpu(notif->time_from_last_iter));

View File

@ -203,8 +203,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
/* Copy firmware into DMA-accessible memory */
fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
if (!fw)
return -ENOMEM;
if (!fw) {
status = -ENOMEM;
goto out;
}
len = fw_entry->size;
if (len % 4)
@ -217,6 +219,8 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
status = rsi_copy_to_card(common, fw, len, num_blocks);
kfree(fw);
out:
release_firmware(fw_entry);
return status;
}

View File

@ -148,8 +148,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
/* Copy firmware into DMA-accessible memory */
fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
if (!fw)
return -ENOMEM;
if (!fw) {
status = -ENOMEM;
goto out;
}
len = fw_entry->size;
if (len % 4)
@ -162,6 +164,8 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
status = rsi_copy_to_card(common, fw, len, num_blocks);
kfree(fw);
out:
release_firmware(fw_entry);
return status;
}

View File

@ -321,6 +321,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
{RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/
{RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
{RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
{RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/

View File

@ -449,7 +449,7 @@ static void _rtl92ee_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw,
"Invalid RateSection %d in 2.4G,Rf %d,%dTx\n",
rate_section, path, txnum);
break;
};
}
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d\n", band);
@ -489,7 +489,7 @@ static u8 _rtl92ee_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw,
"Invalid RateSection %d in 2.4G,Rf %d,%dTx\n",
rate_section, path, txnum);
break;
};
}
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d()\n", band);
@ -853,7 +853,7 @@ static u8 _rtl92ee_get_rate_section_index(u32 regaddr)
else if (regaddr >= 0xE20 && regaddr <= 0xE4C)
index = (u8)((regaddr - 0xE20) / 4);
break;
};
}
return index;
}