Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/net/wireless/ti/cc33xx/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0

cc33xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
boot.o init.o scan.o debugfs.o
boot.o init.o scan.o debugfs.o sysfs.o

cc33xx_spi-objs = spi.o
cc33xx_sdio-objs = sdio.o
Expand Down
46 changes: 42 additions & 4 deletions drivers/net/wireless/ti/cc33xx/acx.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,10 +689,12 @@ int cc33xx_acx_default_rx_filter_enable(struct cc33xx *cc, bool enable,
static int cc33xx_rx_filter_get_fields_size(struct cc33xx_rx_filter *filter)
{
int i, fields_size = 0;
u8 data_len;

for (i = 0; i < filter->num_fields; i++) {
fields_size += filter->fields[i].len - sizeof(u8 *)
+ sizeof(struct cc33xx_rx_filter_field);
data_len = (filter->fields[i].flags & CC33XX_RX_FILTER_FLAG_MASKED) ?
filter->fields[i].len * 2 : filter->fields[i].len;
fields_size += RX_FILTER_FIELD_OVERHEAD + data_len;
}

return fields_size;
Expand All @@ -703,6 +705,7 @@ static void cc33xx_rx_filter_flatten_fields(struct cc33xx_rx_filter *filter,
{
int i;
struct cc33xx_rx_filter_field *field;
u8 data_len;

for (i = 0; i < filter->num_fields; i++) {
field = (struct cc33xx_rx_filter_field *)buf;
Expand All @@ -711,9 +714,11 @@ static void cc33xx_rx_filter_flatten_fields(struct cc33xx_rx_filter *filter,
field->flags = filter->fields[i].flags;
field->len = filter->fields[i].len;

memcpy(&field->pattern, filter->fields[i].pattern, field->len);
data_len = (filter->fields[i].flags & CC33XX_RX_FILTER_FLAG_MASKED) ?
filter->fields[i].len * 2 : filter->fields[i].len;
memcpy(&field->pattern, filter->fields[i].pattern, data_len);
buf += sizeof(struct cc33xx_rx_filter_field) - sizeof(u8 *);
buf += field->len;
buf += data_len;
}
}

Expand Down Expand Up @@ -848,6 +853,39 @@ int cc33xx_acx_set_antenna_select(struct cc33xx *cc, u8 selection)
return ret;
}

int cc33xx_acx_set_regdoamin_and_tx_control_params(struct cc33xx *wl, struct acx_phy_regdomain_tx_control_params *params)
{
struct acx_phy_regdomain_tx_control_params *acx;
int ret;

acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
ret = -ENOMEM;
goto out;
}

acx->bitmask = params->bitmask;
acx->country_code = params->country_code;
acx->reg_domain = params->reg_domain;

memcpy(acx->ble_ch_lim_1M, params->ble_ch_lim_1M, sizeof(u8) * BLE_LIM_CHANNELS_COUNT);
memcpy(acx->ble_ch_lim_2M, params->ble_ch_lim_2M, sizeof(u8) * BLE_LIM_CHANNELS_COUNT);

memcpy(acx->per_channel_power_limit, params->per_channel_power_limit, sizeof(u8) * REG_RULES_COUNT);


ret = cc33xx_cmd_configure(wl, PHY_REGDOMAIN_TX_POWER_PARAMS,
acx, sizeof(*acx));
if (ret < 0) {
cc33xx_warning("acx regdoamin_and_tx_control_params failed: %d", ret);
goto out;
}

out:
kfree(acx);
return ret;
}

int cc33xx_acx_set_tsf(struct cc33xx *cc, u64 tsf_val)
{
struct debug_set_tsf *set_tsf_cmd;
Expand Down
17 changes: 17 additions & 0 deletions drivers/net/wireless/ti/cc33xx/acx.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ enum cfg {
ENABLE_CHANNEL_UTILIZATION_NEXT_SCAN = 30,
SET_SEED_CFG = 31,
RESET_STATS = 32,
PHY_REGDOMAIN_TX_POWER_PARAMS = 33,

LAST_CFG_VALUE,
MAX_DOT11_CFG = LAST_CFG_VALUE,
Expand Down Expand Up @@ -579,6 +580,21 @@ struct acx_antenna_select {
u8 padding[3];
} __packed;

#define BLE_LIM_CHANNELS_COUNT (40)
#define REG_RULES_COUNT (520)

struct acx_phy_regdomain_tx_control_params {
struct acx_header header;

u8 bitmask;
u32 country_code;
u8 reg_domain;
u8 ble_ch_lim_1M[BLE_LIM_CHANNELS_COUNT];
u8 ble_ch_lim_2M[BLE_LIM_CHANNELS_COUNT];
u8 per_channel_power_limit[REG_RULES_COUNT];
u8 padding[2];
} __packed;

struct debug_set_tsf {
struct debug_header header;

Expand Down Expand Up @@ -797,5 +813,6 @@ int cc33xx_acx_twt_resume(struct cc33xx *wl);
int cc33xx_acx_twt_suspend(struct cc33xx *wl);
int cc33xx_acx_statistics(struct cc33xx *cc, void *stats);
int cc33xx_acx_clear_statistics(struct cc33xx *cc);
int cc33xx_acx_set_regdoamin_and_tx_control_params(struct cc33xx *wl, struct acx_phy_regdomain_tx_control_params *params);

#endif /* __CC33XX_ACX_H__ */
9 changes: 9 additions & 0 deletions drivers/net/wireless/ti/cc33xx/cc33xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ struct cc33xx_stats {
unsigned int excessive_retries;
};

struct cc33xx_wowlan_search {
bool enabled;
int filter_count;
struct cc33xx_rx_filter *active_filters[CC33XX_MAX_RX_FILTERS];
};

struct cc33xx_ant_diversity {
u8 diversity_enable;
s8 rssi_threshold;
Expand Down Expand Up @@ -217,6 +223,9 @@ struct cc33xx {

bool keep_device_power;

/* WoWLAN search pattern state */
struct cc33xx_wowlan_search wowlan_search;

/* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
*/
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/ti/cc33xx/cc33xx_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ struct cc33xx_link {

#define CC33XX_RX_FILTER_FLAG_IP_HEADER 0
#define CC33XX_RX_FILTER_FLAG_ETHERNET_HEADER BIT(1)
#define CC33XX_RX_FILTER_FLAG_SEARCH_ANYWHERE BIT(2)
#define CC33XX_RX_FILTER_FLAG_MASKED BIT(3)

struct ieee80211_header {
__le16 frame_ctl;
Expand Down Expand Up @@ -326,6 +328,8 @@ struct cc33xx_vif {

int rssi_thold;
int last_rssi_event;
bool cqm_enabled;
u32 cqm_rssi_hyst;

/* save the current encryption type for auto-arp config */
u8 encryption_type;
Expand Down
43 changes: 43 additions & 0 deletions drivers/net/wireless/ti/cc33xx/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static int __cc33xx_cmd_send(struct cc33xx *cc, u16 id, void *buf,
case CMD_BM_READ_DEVICE_INFO:
case CMD_SET_PROBE_IE:
case CMD_DEBUG:
case CMD_CQM_RSSI_CONFIG:
if (!res_len)
break; /* Response should be discarded */

Expand Down Expand Up @@ -2009,3 +2010,45 @@ int cmd_download_container_chunk(struct cc33xx *cc, u8 *chunk,

return ret;
}

int cc33xx_cmd_cqm_rssi_config(struct cc33xx *wl, struct cc33xx_vif *wlvif, bool enable, s8 threshold, u8 hysteresis)
{
struct cc33xx_cmd_cqm_rssi_config *cqm_params = NULL;
int ret = 0;
int role_id = wlvif->role_id;

cc33xx_debug(DEBUG_CMD, "CQM config: role=%u, enable=%d, threshold=%d dBm, hysteresis=%d",
role_id, enable, threshold, hysteresis);

if (wlvif && enable) {
wlvif->last_rssi_event = (enum nl80211_cqm_rssi_threshold_event) -1;
cc33xx_info("CQM: Reset last_rssi_event for role %u", role_id);
}

cqm_params = kzalloc(sizeof(*cqm_params), GFP_KERNEL);
if (!cqm_params) {
cc33xx_error("CQM: Failed to allocate command buffer");
return -ENOMEM;
}

cqm_params->role_id = role_id;
cqm_params->enable = enable;
cqm_params->threshold_dbm = threshold;
cqm_params->hysteresis_db = hysteresis;

ret = cc33xx_cmd_send(wl, CMD_CQM_RSSI_CONFIG, cqm_params, sizeof(*cqm_params), sizeof(*cqm_params));
if (ret < 0) {
cc33xx_error("CQM: Failed to send config command: %d", ret);
goto out;
}

if (cqm_params->header.status != CMD_STATUS_SUCCESS) {
ret = -EIO;
goto out;
}

out:
kfree(cqm_params);
return ret;
}

11 changes: 11 additions & 0 deletions drivers/net/wireless/ti/cc33xx/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ int cmd_set_bd_addr(struct cc33xx *cc, u8 *bd_addr);
int cmd_get_device_info(struct cc33xx *cc, u8 *info_buffer, size_t buffer_len);
int cmd_download_container_chunk(struct cc33xx *cc, u8 *chunk,
size_t chunk_len, bool is_last_chunk);
int cc33xx_cmd_cqm_rssi_config(struct cc33xx *wl, struct cc33xx_vif *wlvif, bool enable, s8 threshold, u8 hysteresis);

enum cc33xx_cmd {
CMD_EMPTY,
Expand Down Expand Up @@ -138,6 +139,7 @@ enum cc33xx_cmd {
CMD_SET_BD_ADDR = 38,
CMD_BLE_COMMANDS = 39,
CMD_SET_PS_MODE = 40,
CMD_CQM_RSSI_CONFIG = 44,

CMD_LAST_SUPPORTED_COMMAND,

Expand Down Expand Up @@ -698,4 +700,13 @@ struct cc33xx_cmd_get_device_info {
u8 device_info[700];
} __packed;

struct cc33xx_cmd_cqm_rssi_config {
struct cc33xx_cmd_header header;

u8 role_id;
u8 enable;
s8 threshold_dbm;
u8 hysteresis_db;
} __packed;

#endif /* __CC33XX_CMD_H__ */
73 changes: 73 additions & 0 deletions drivers/net/wireless/ti/cc33xx/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@

#define CC33XX_WAIT_EVENT_FAST_POLL_COUNT 20

struct cc33xx_rssi_snr_trigger_event {
u8 role_id;
u8 event_type;
s8 rssi_dbm;
u8 padding;
} __packed;

struct cc33xx_event_mailbox {
__le32 events_vector;

Expand Down Expand Up @@ -75,6 +82,9 @@ struct cc33xx_event_mailbox {
/* time sync low lsb*/
__le16 time_sync_tsf_low_lsb;

struct cc33xx_rssi_snr_trigger_event rssi_snr_trigger0;
struct cc33xx_rssi_snr_trigger_event rssi_snr_trigger1;

u8 ble_event[304];
u8 csi_data[136];
u8 reseed_request_size;
Expand Down Expand Up @@ -311,6 +321,59 @@ static void cc33xx_event_beacon_loss(struct cc33xx *cc,
}
}

static void wlcore_event_rssi_trigger(struct cc33xx *wl, struct cc33xx_rssi_snr_trigger_event *evt)
{
struct cc33xx_vif *wlvif = NULL;
struct ieee80211_vif *vif;
enum nl80211_cqm_rssi_threshold_event event_type;

cc33xx_debug(DEBUG_EVENT, "CQM: RSSI event: role=%u, type=%s, rssi=%d dBm", evt->role_id, evt->event_type ? "HIGH" : "LOW", evt->rssi_dbm);

if (evt->role_id >= CC33XX_MAX_ROLES)
return;

cc33xx_for_each_wlvif(wl, wlvif) {
if (wlvif->role_id == evt->role_id)
break;
}

if (!wlvif || wlvif->role_id != evt->role_id) {
cc33xx_error("CQM: RSSI event for unknown role %u", evt->role_id);
return;
}

if (wlvif->role_id == CC33XX_INVALID_ROLE_ID) {
cc33xx_error("CQM: RSSI event for invalid role");
return;
}

if (!wlvif->cqm_enabled) {
cc33xx_warning("CQM: RSSI event received but monitoring not enabled for role %u", evt->role_id);
return;
}

vif = cc33xx_wlvif_to_vif(wlvif);
if (!vif) {
cc33xx_warning("CQM: VIF is NULL for role %u", evt->role_id);
return;
}

event_type = evt->event_type ? NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;

if (event_type == wlvif->last_rssi_event) {
cc33xx_debug(DEBUG_EVENT, "CQM: Duplicate %s event filtered (role %u)", evt->event_type ? "HIGH" : "LOW", evt->role_id);
return;
}

ieee80211_cqm_rssi_notify(vif, event_type, evt->rssi_dbm, GFP_KERNEL);

wlvif->last_rssi_event = event_type;

cc33xx_debug(DEBUG_EVENT, "CQM: RSSI event notification sent to mac80211 (role %u)", evt->role_id);

}

void process_deferred_events(struct cc33xx *cc)
{
struct event_node *event_node, *tmp;
Expand Down Expand Up @@ -360,6 +423,16 @@ void process_deferred_events(struct cc33xx *cc)
if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
cc33xx_event_roc_complete(cc);

if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID)
{
cc33xx_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT_ID");
wlcore_event_rssi_trigger(cc, &event_data->rssi_snr_trigger0);
}

if (vector & RSSI_SNR_TRIGGER_1_EVENT_ID) {
cc33xx_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_1_EVENT_ID");
wlcore_event_rssi_trigger(cc, &event_data->rssi_snr_trigger1);
}
kfree(event_node);
}
}
Loading