Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git patches for v6.7.

Major changes:

ath12k

* read board data variant name from SMBIOS
This commit is contained in:
Kalle Valo 2023-10-09 09:45:08 +03:00
commit 164f1842d9
15 changed files with 248 additions and 115 deletions

View File

@ -1964,20 +1964,13 @@ static ssize_t ath10k_write_btcoex(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
size_t buf_size;
int ret;
ssize_t ret;
bool val;
u32 pdev_param;
buf_size = min(count, (sizeof(buf) - 1));
if (copy_from_user(buf, ubuf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (kstrtobool(buf, &val) != 0)
return -EINVAL;
ret = kstrtobool_from_user(ubuf, count, &val);
if (ret)
return ret;
if (!ar->coex_support)
return -EOPNOTSUPP;
@ -2000,7 +1993,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
ar->running_fw->fw_file.fw_features)) {
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
if (ret) {
ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
ath10k_warn(ar, "failed to enable btcoex: %zd\n", ret);
ret = count;
goto exit;
}
@ -2103,19 +2096,12 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
size_t buf_size;
int ret;
ssize_t ret;
bool val;
buf_size = min(count, (sizeof(buf) - 1));
if (copy_from_user(buf, ubuf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (kstrtobool(buf, &val) != 0)
return -EINVAL;
ret = kstrtobool_from_user(ubuf, count, &val);
if (ret)
return ret;
mutex_lock(&ar->conf_mutex);
@ -2239,21 +2225,16 @@ static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
ssize_t len;
ssize_t ret;
u32 mask;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoint(buf, 0, &mask))
return -EINVAL;
ret = kstrtoint_from_user(user_buf, count, 0, &mask);
if (ret)
return ret;
ar->sta_tid_stats_mask = mask;
return len;
return count;
}
static const struct file_operations fops_sta_tid_stats_mask = {

View File

@ -728,20 +728,13 @@ static int ath10k_peer_create(struct ath10k *ar,
const u8 *addr,
enum wmi_peer_type peer_type)
{
struct ath10k_vif *arvif;
struct ath10k_peer *peer;
int num_peers = 0;
int ret;
lockdep_assert_held(&ar->conf_mutex);
num_peers = ar->num_peers;
/* Each vdev consumes a peer entry as well */
list_for_each_entry(arvif, &ar->arvifs, list)
num_peers++;
if (num_peers >= ar->max_num_peers)
/* Each vdev consumes a peer entry as well. */
if (ar->num_peers + list_count_nodes(&ar->arvifs) >= ar->max_num_peers)
return -ENOBUFS;
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
@ -4503,18 +4496,21 @@ void __ath10k_scan_finish(struct ath10k *ar)
break;
case ATH10K_SCAN_RUNNING:
case ATH10K_SCAN_ABORTING:
if (ar->scan.is_roc && ar->scan.roc_notify)
ieee80211_remain_on_channel_expired(ar->hw);
fallthrough;
case ATH10K_SCAN_STARTING:
if (!ar->scan.is_roc) {
struct cfg80211_scan_info info = {
.aborted = (ar->scan.state ==
ATH10K_SCAN_ABORTING),
.aborted = ((ar->scan.state ==
ATH10K_SCAN_ABORTING) ||
(ar->scan.state ==
ATH10K_SCAN_STARTING)),
};
ieee80211_scan_completed(ar->hw, &info);
} else if (ar->scan.roc_notify) {
ieee80211_remain_on_channel_expired(ar->hw);
}
fallthrough;
case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE;
ar->scan_channel = NULL;
ar->scan.roc_freq = 0;

View File

@ -828,12 +828,20 @@ static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
static inline void ath10k_snoc_irq_disable(struct ath10k *ar)
{
ath10k_ce_disable_interrupts(ar);
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int id;
for (id = 0; id < CE_COUNT_MAX; id++)
disable_irq(ar_snoc->ce_irqs[id].irq_line);
}
static inline void ath10k_snoc_irq_enable(struct ath10k *ar)
{
ath10k_ce_enable_interrupts(ar);
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int id;
for (id = 0; id < CE_COUNT_MAX; id++)
enable_irq(ar_snoc->ce_irqs[id].irq_line);
}
static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
@ -1090,6 +1098,8 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar,
goto err_free_rri;
}
ath10k_ce_enable_interrupts(ar);
return 0;
err_free_rri:
@ -1253,8 +1263,8 @@ static int ath10k_snoc_request_irq(struct ath10k *ar)
for (id = 0; id < CE_COUNT_MAX; id++) {
ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
ath10k_snoc_per_engine_handler, 0,
ce_name[id], ar);
ath10k_snoc_per_engine_handler,
IRQF_NO_AUTOEN, ce_name[id], ar);
if (ret) {
ath10k_err(ar,
"failed to register IRQ handler for CE %d: %d\n",

View File

@ -384,16 +384,11 @@ static ssize_t write_file_spectral_count(struct file *file,
{
struct ath10k *ar = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
ssize_t ret;
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;
ret = kstrtoul_from_user(user_buf, count, 0, &val);
if (ret)
return ret;
if (val > 255)
return -EINVAL;
@ -440,16 +435,11 @@ static ssize_t write_file_spectral_bins(struct file *file,
{
struct ath10k *ar = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
ssize_t ret;
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;
ret = kstrtoul_from_user(user_buf, count, 0, &val);
if (ret)
return ret;
if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
return -EINVAL;

View File

@ -5,6 +5,7 @@
*/
#include <net/mac80211.h>
#include <net/cfg80211.h>
#include <linux/etherdevice.h>
#include <linux/bitfield.h>
#include <linux/inetdevice.h>
@ -7196,6 +7197,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
struct wmi_vdev_start_req_arg arg = {};
const struct cfg80211_chan_def *chandef = &ctx->def;
int ret = 0;
unsigned int dfs_cac_time;
lockdep_assert_held(&ar->conf_mutex);
@ -7275,20 +7277,21 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
arvif->vif->addr, arvif->vdev_id);
/* Enable CAC Flag in the driver by checking the channel DFS cac time,
* i.e dfs_cac_ms value which will be valid only for radar channels
* and state as NL80211_DFS_USABLE which indicates CAC needs to be
/* Enable CAC Flag in the driver by checking the all sub-channel's DFS
* state as NL80211_DFS_USABLE which indicates CAC needs to be
* done before channel usage. This flags is used to drop rx packets.
* during CAC.
*/
/* TODO Set the flag for other interface types as required */
if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
chandef->chan->dfs_cac_ms &&
chandef->chan->dfs_state == NL80211_DFS_USABLE) {
if (arvif->vdev_type == WMI_VDEV_TYPE_AP && ctx->radar_enabled &&
cfg80211_chandef_dfs_usable(ar->hw->wiphy, chandef)) {
set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
dfs_cac_time = cfg80211_chandef_dfs_cac_time(ar->hw->wiphy,
chandef);
ath11k_dbg(ab, ATH11K_DBG_MAC,
"CAC Started in chan_freq %d for vdev %d\n",
arg.channel.freq, arg.vdev_id);
"cac started dfs_cac_time %u center_freq %d center_freq1 %d for vdev %d\n",
dfs_cac_time, arg.channel.freq, chandef->center_freq1,
arg.vdev_id);
}
ret = ath11k_mac_set_txbf_conf(arvif);
@ -9057,6 +9060,14 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
if (ar->state != ATH11K_STATE_ON)
goto err_fallback;
/* Firmware doesn't provide Tx power during CAC hence no need to fetch
* the stats.
*/
if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) {
mutex_unlock(&ar->conf_mutex);
return -EAGAIN;
}
req_param.pdev_id = ar->pdev->pdev_id;
req_param.stats_id = WMI_REQUEST_PDEV_STAT;

View File

@ -398,6 +398,75 @@ static void ath12k_core_stop(struct ath12k_base *ab)
/* De-Init of components as needed */
}
static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
{
struct ath12k_base *ab = data;
const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC;
struct ath12k_smbios_bdf *smbios = (struct ath12k_smbios_bdf *)hdr;
ssize_t copied;
size_t len;
int i;
if (ab->qmi.target.bdf_ext[0] != '\0')
return;
if (hdr->type != ATH12K_SMBIOS_BDF_EXT_TYPE)
return;
if (hdr->length != ATH12K_SMBIOS_BDF_EXT_LENGTH) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"wrong smbios bdf ext type length (%d).\n",
hdr->length);
return;
}
if (!smbios->bdf_enabled) {
ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n");
return;
}
/* Only one string exists (per spec) */
if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"bdf variant magic does not match.\n");
return;
}
len = min_t(size_t,
strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
for (i = 0; i < len; i++) {
if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"bdf variant name contains non ascii chars.\n");
return;
}
}
/* Copy extension name without magic prefix */
copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
sizeof(ab->qmi.target.bdf_ext));
if (copied < 0) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"bdf variant string is longer than the buffer can accommodate\n");
return;
}
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"found and validated bdf variant smbios_type 0x%x bdf %s\n",
ATH12K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
}
int ath12k_core_check_smbios(struct ath12k_base *ab)
{
ab->qmi.target.bdf_ext[0] = '\0';
dmi_walk(ath12k_core_check_bdfext, ab);
if (ab->qmi.target.bdf_ext[0] == '\0')
return -ENODATA;
return 0;
}
static int ath12k_core_soc_create(struct ath12k_base *ab)
{
int ret;

View File

@ -11,6 +11,8 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/bitfield.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@ -32,6 +34,15 @@
/* Pending management packets threshold for dropping probe responses */
#define ATH12K_PRB_RSP_DROP_THRESHOLD ((ATH12K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4)
/* SMBIOS type containing Board Data File Name Extension */
#define ATH12K_SMBIOS_BDF_EXT_TYPE 0xF8
/* SMBIOS type structure length (excluding strings-set) */
#define ATH12K_SMBIOS_BDF_EXT_LENGTH 0x9
/* The magic used by QCA spec */
#define ATH12K_SMBIOS_BDF_EXT_MAGIC "BDF_"
#define ATH12K_INVALID_HW_MAC_ID 0xFF
#define ATH12K_RX_RATE_TABLE_NUM 320
#define ATH12K_RX_RATE_TABLE_11AX_NUM 576
@ -129,6 +140,13 @@ struct ath12k_ext_irq_grp {
struct net_device napi_ndev;
};
struct ath12k_smbios_bdf {
struct dmi_header hdr;
u32 padding;
u8 bdf_enabled;
u8 bdf_ext[];
} __packed;
#define HEHANDLE_CAP_PHYINFO_SIZE 3
#define HECAP_PHYINFO_SIZE 9
#define HECAP_MACINFO_SIZE 5
@ -792,7 +810,8 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
int ath12k_core_fetch_bdf(struct ath12k_base *ath12k,
struct ath12k_board_data *bd);
void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd);
int ath12k_core_check_dt(struct ath12k_base *ath12k);
int ath12k_core_check_smbios(struct ath12k_base *ab);
void ath12k_core_halt(struct ath12k *ar);
int ath12k_core_resume(struct ath12k_base *ab);
int ath12k_core_suspend(struct ath12k_base *ab);

View File

@ -64,7 +64,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask,
vaf.va = &args;
if (ath12k_debug_mask & mask)
dev_dbg(ab->dev, "%pV", &vaf);
dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
/* TODO: trace log */

View File

@ -3526,23 +3526,13 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
struct sk_buff_head *msdu_list)
{
struct ath12k_base *ab = ar->ab;
u16 msdu_len, peer_id;
u16 msdu_len;
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
u8 l3pad_bytes;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
spin_lock(&ab->base_lock);
if (!ath12k_peer_find_by_id(ab, peer_id)) {
spin_unlock(&ab->base_lock);
ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
peer_id);
return -EINVAL;
}
spin_unlock(&ab->base_lock);
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
/* First buffer will be freed by the caller, so deduct it's length */

View File

@ -4554,7 +4554,8 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
}
}
static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
struct ath12k_band_cap *band_cap,
struct ieee80211_he_cap_elem *he_cap_elem,
int iftype,
struct ieee80211_sta_eht_cap *eht_cap)
@ -4562,6 +4563,10 @@ static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)))
return;
eht_cap->has_eht = true;
memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
sizeof(eht_cap_elem->mac_cap_info));
@ -4627,7 +4632,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
}
ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i,
&data[idx].eht_cap);
idx++;
}
@ -5847,6 +5852,59 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
static enum wmi_phy_mode
ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
enum wmi_phy_mode mode,
enum nl80211_band band,
enum nl80211_iftype type)
{
struct ieee80211_sta_eht_cap *eht_cap;
enum wmi_phy_mode down_mode;
if (mode < MODE_11BE_EHT20)
return mode;
eht_cap = &ar->mac.iftype[band][type].eht_cap;
if (eht_cap->has_eht)
return mode;
switch (mode) {
case MODE_11BE_EHT20:
down_mode = MODE_11AX_HE20;
break;
case MODE_11BE_EHT40:
down_mode = MODE_11AX_HE40;
break;
case MODE_11BE_EHT80:
down_mode = MODE_11AX_HE80;
break;
case MODE_11BE_EHT80_80:
down_mode = MODE_11AX_HE80_80;
break;
case MODE_11BE_EHT160:
case MODE_11BE_EHT160_160:
case MODE_11BE_EHT320:
down_mode = MODE_11AX_HE160;
break;
case MODE_11BE_EHT20_2G:
down_mode = MODE_11AX_HE20_2G;
break;
case MODE_11BE_EHT40_2G:
down_mode = MODE_11AX_HE40_2G;
break;
default:
down_mode = mode;
break;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"mac vdev start phymode %s downgrade to %s\n",
ath12k_mac_phymode_str(mode),
ath12k_mac_phymode_str(down_mode));
return down_mode;
}
static int
ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
struct ieee80211_chanctx_conf *ctx,
@ -5873,6 +5931,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.band_center_freq2 = chandef->center_freq2;
arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
chandef->chan->band,
arvif->vif->type);
arg.min_power = 0;
arg.max_power = chandef->chan->max_power * 2;
arg.max_reg_power = chandef->chan->max_reg_power * 2;

View File

@ -370,8 +370,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
ret = ath12k_mhi_get_msi(ab_pci);
if (ret) {
ath12k_err(ab, "failed to get msi for mhi\n");
mhi_free_controller(mhi_ctrl);
return ret;
goto free_controller;
}
mhi_ctrl->iova_start = 0;
@ -388,11 +387,15 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config);
if (ret) {
ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
mhi_free_controller(mhi_ctrl);
return ret;
goto free_controller;
}
return 0;
free_controller:
mhi_free_controller(mhi_ctrl);
ab_pci->mhi_ctrl = NULL;
return ret;
}
void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)

View File

@ -2213,6 +2213,7 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
struct qmi_txn txn = {};
unsigned int board_id = ATH12K_BOARD_ID_DEFAULT;
int ret = 0;
int r;
int i;
memset(&req, 0, sizeof(req));
@ -2297,6 +2298,10 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
ab->qmi.target.fw_build_timestamp,
ab->qmi.target.fw_build_id);
r = ath12k_core_check_smbios(ab);
if (r)
ath12k_dbg(ab, ATH12K_DBG_QMI, "SMBIOS bdf variant name not set.\n");
out:
return ret;
}

View File

@ -2158,6 +2158,9 @@ enum wmi_tlv_service {
WMI_MAX_EXT_SERVICE = 256,
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
WMI_TLV_SERVICE_11BE = 289,
WMI_MAX_EXT2_SERVICE,
};

View File

@ -178,7 +178,7 @@ static void carl9170_usb_tx_data_complete(struct urb *urb)
switch (urb->status) {
/* everything is fine */
case 0:
carl9170_tx_callback(ar, (void *)urb->context);
carl9170_tx_callback(ar, urb->context);
break;
/* disconnect */
@ -369,7 +369,7 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
struct urb *urb;
while ((urb = usb_get_from_anchor(&ar->tx_err))) {
struct sk_buff *skb = (void *)urb->context;
struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
@ -397,7 +397,7 @@ static void carl9170_usb_tasklet(struct tasklet_struct *t)
static void carl9170_usb_rx_complete(struct urb *urb)
{
struct ar9170 *ar = (struct ar9170 *)urb->context;
struct ar9170 *ar = urb->context;
int err;
if (WARN_ON_ONCE(!ar))
@ -559,7 +559,7 @@ static int carl9170_usb_flush(struct ar9170 *ar)
int ret, err = 0;
while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
struct sk_buff *skb = (void *)urb->context;
struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
usb_free_urb(urb);
@ -668,7 +668,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
memcpy(ar->cmd.data, payload, plen);
spin_lock_bh(&ar->cmd_lock);
ar->readbuf = (u8 *)out;
ar->readbuf = out;
ar->readlen = outlen;
spin_unlock_bh(&ar->cmd_lock);

View File

@ -161,7 +161,7 @@ get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
struct channel_detector {
struct list_head head;
u16 freq;
struct pri_detector **detectors;
struct pri_detector *detectors[];
};
/* channel_detector_reset() - reset detector lines for a given channel */
@ -183,14 +183,13 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd,
if (cd == NULL)
return;
list_del(&cd->head);
if (cd->detectors) {
for (i = 0; i < dpd->num_radar_types; i++) {
struct pri_detector *de = cd->detectors[i];
if (de != NULL)
de->exit(de);
}
for (i = 0; i < dpd->num_radar_types; i++) {
struct pri_detector *de = cd->detectors[i];
if (de != NULL)
de->exit(de);
}
kfree(cd->detectors);
kfree(cd);
}
@ -200,16 +199,12 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
u32 i;
struct channel_detector *cd;
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
cd = kzalloc(struct_size(cd, detectors, dpd->num_radar_types), GFP_ATOMIC);
if (cd == NULL)
goto fail;
INIT_LIST_HEAD(&cd->head);
cd->freq = freq;
cd->detectors = kmalloc_array(dpd->num_radar_types,
sizeof(*cd->detectors), GFP_ATOMIC);
if (cd->detectors == NULL)
goto fail;
for (i = 0; i < dpd->num_radar_types; i++) {
const struct radar_detector_specs *rs = &dpd->radar_spec[i];