qcacld-3.0: Add new IOCTL to change SAP/P2P-GO's operating channel
Add new IOCTL 'CHANNEL_SWITCH' which is used to move the operating channel of SAP/P2P-GO. This IOCTL is supported only for SAP/P2P-GO and not for STA/P2P-GC. E.g., format to issue command through wpa_supplicant: DRIVER CHANNEL_SWITCH <CH> <BW> - <CH> is channel number to move (1 for ch1, 149 for ch149 etc.) - <BW> is bandwidth to move (20 for BW 20, 40 for BW 40 etc.) Change-Id: Ie65f2ceb9ece04053ab32ee60f83fd09cd232f77 CRs-Fixed: 955368
Dieser Commit ist enthalten in:

committet von
Akash Patel

Ursprung
a74bb024b1
Commit
794a098c18
@@ -1341,6 +1341,9 @@ struct hdd_context_s {
|
||||
/*---------------------------------------------------------------------------
|
||||
Function declarations and documentation
|
||||
-------------------------------------------------------------------------*/
|
||||
int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
|
||||
uint32_t chan_number,
|
||||
phy_ch_width chan_bw);
|
||||
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
|
||||
void wlan_hdd_check_sta_ap_concurrent_ch_intf(void *sta_pAdapter);
|
||||
#endif
|
||||
|
@@ -1921,6 +1921,13 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hdd_validate_channel_and_bandwidth(pHostapdAdapter,
|
||||
target_channel, target_bw);
|
||||
if (ret) {
|
||||
hdd_err("Invalid CH and BW combo");
|
||||
return ret;
|
||||
}
|
||||
|
||||
sta_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
|
||||
/*
|
||||
* conc_custom_rule1:
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "wlan_hdd_power.h"
|
||||
#include "wlan_hdd_driver_ops.h"
|
||||
#include "cds_concurrency.h"
|
||||
#include "wlan_hdd_hostapd.h"
|
||||
|
||||
#include "wlan_hdd_p2p.h"
|
||||
#include <linux/ctype.h>
|
||||
@@ -5954,6 +5955,123 @@ static int drv_cmd_set_fcc_channel(hdd_adapter_t *adapter,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_parse_set_channel_switch_command() - Parse and validate CHANNEL_SWITCH
|
||||
* command
|
||||
* @value: Pointer to the command
|
||||
* @chan_number: Pointer to the channel number
|
||||
* @chan_bw: Pointer to the channel bandwidth
|
||||
*
|
||||
* Parses and provides the channel number and channel width from the input
|
||||
* command which is expected to be of the format: CHANNEL_SWITCH <CH> <BW>
|
||||
* <CH> is channel number to move (where 1 = channel 1, 149 = channel 149, ...)
|
||||
* <BW> is bandwidth to move (where 20 = BW 20, 40 = BW 40, 80 = BW 80)
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure
|
||||
*/
|
||||
static int hdd_parse_set_channel_switch_command(uint8_t *value,
|
||||
uint32_t *chan_number,
|
||||
uint32_t *chan_bw)
|
||||
{
|
||||
const uint8_t *in_ptr = value;
|
||||
int ret;
|
||||
|
||||
in_ptr = strnchr(value, strlen(value), SPACE_ASCII_VALUE);
|
||||
|
||||
/* no argument after the command */
|
||||
if (NULL == in_ptr) {
|
||||
hdd_err("No argument after the command");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* no space after the command */
|
||||
if (SPACE_ASCII_VALUE != *in_ptr) {
|
||||
hdd_err("No space after the command ");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* remove empty spaces and move the next argument */
|
||||
while ((SPACE_ASCII_VALUE == *in_ptr) && ('\0' != *in_ptr))
|
||||
in_ptr++;
|
||||
|
||||
/* no argument followed by spaces */
|
||||
if ('\0' == *in_ptr) {
|
||||
hdd_err("No argument followed by spaces");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get the two arguments: channel number and bandwidth */
|
||||
ret = sscanf(in_ptr, "%u %u", chan_number, chan_bw);
|
||||
if (ret != 2) {
|
||||
hdd_err("Arguments retrieval from cmd string failed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drv_cmd_set_channel_switch() - Switch SAP/P2P-GO operating channel
|
||||
* @adapter: HDD adapter
|
||||
* @hdd_ctx: HDD context
|
||||
* @command: Pointer to the input command CHANNEL_SWITCH
|
||||
* @command_len: Command len
|
||||
* @priv_data: Private data
|
||||
*
|
||||
* Handles private IOCTL CHANNEL_SWITCH command to switch the operating channel
|
||||
* of SAP/P2P-GO
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure
|
||||
*/
|
||||
static int drv_cmd_set_channel_switch(hdd_adapter_t *adapter,
|
||||
hdd_context_t *hdd_ctx,
|
||||
uint8_t *command,
|
||||
uint8_t command_len,
|
||||
hdd_priv_data_t *priv_data)
|
||||
{
|
||||
struct net_device *dev = adapter->dev;
|
||||
int status;
|
||||
uint32_t chan_number = 0, chan_bw = 0;
|
||||
uint8_t *value = command;
|
||||
phy_ch_width width;
|
||||
|
||||
if ((adapter->device_mode != WLAN_HDD_P2P_GO) &&
|
||||
(adapter->device_mode != WLAN_HDD_SOFTAP)) {
|
||||
hdd_err("IOCTL CHANNEL_SWITCH not supported for mode %d",
|
||||
adapter->device_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status = hdd_parse_set_channel_switch_command(value,
|
||||
&chan_number, &chan_bw);
|
||||
if (status) {
|
||||
hdd_err("Invalid CHANNEL_SWITCH command");
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((chan_bw != 20) && (chan_bw != 40) && (chan_bw != 80)) {
|
||||
hdd_err("BW %d is not allowed for CHANNEL_SWITCH", chan_bw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (chan_bw == 80)
|
||||
width = CH_WIDTH_80MHZ;
|
||||
else if (chan_bw == 40)
|
||||
width = CH_WIDTH_40MHZ;
|
||||
else
|
||||
width = CH_WIDTH_20MHZ;
|
||||
|
||||
hdd_info("CH:%d BW:%d", chan_number, chan_bw);
|
||||
|
||||
status = hdd_softap_set_channel_change(dev, chan_number, width);
|
||||
if (status) {
|
||||
hdd_err("Set channel change fail");
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following table contains all supported WLAN HDD
|
||||
* IOCTL driver commands and the handler for each of them.
|
||||
@@ -6066,6 +6184,7 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = {
|
||||
{"RXFILTER-REMOVE", drv_cmd_rx_filter_remove},
|
||||
{"RXFILTER-ADD", drv_cmd_rx_filter_add},
|
||||
{"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel},
|
||||
{"CHANNEL_SWITCH", drv_cmd_set_channel_switch},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -232,6 +232,77 @@ const char *hdd_device_mode_to_string(uint8_t device_mode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
|
||||
* @adapter: HDD adapter
|
||||
* @chan_number: Channel number
|
||||
* @chan_bw: Bandwidth
|
||||
*
|
||||
* Checks if the given bandwidth is valid for the given channel number.
|
||||
*
|
||||
* Return: 0 for success, non-zero for failure
|
||||
*/
|
||||
int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
|
||||
uint32_t chan_number,
|
||||
phy_ch_width chan_bw)
|
||||
{
|
||||
uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
|
||||
uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
|
||||
bool found = false;
|
||||
tHalHandle hal;
|
||||
|
||||
hal = WLAN_HDD_GET_HAL_CTX(adapter);
|
||||
if (!hal) {
|
||||
hdd_err("Invalid HAL context");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
|
||||
hdd_err("No valid channel list");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (chan[i] == chan_number) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
hdd_err("Channel not in driver's valid channel list");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
|
||||
(!CDS_IS_CHANNEL_5GHZ(chan_number))) {
|
||||
hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
|
||||
if (chan_bw == CH_WIDTH_80MHZ) {
|
||||
hdd_err("BW80 not possible in 2.4GHz band");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
|
||||
(chan_bw != CH_WIDTH_MAX)) {
|
||||
hdd_err("Only BW20 possible on channel 14");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
|
||||
if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
|
||||
(chan_bw != CH_WIDTH_MAX)) {
|
||||
hdd_err("Only BW20 possible on channel 165");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __hdd_netdev_notifier_call(struct notifier_block *nb,
|
||||
unsigned long state, void *data)
|
||||
{
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren