Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

driver: wifi: siwx91x: Add Access Point (AP) mode support to siwx91x wifi driver #85906

Merged

Conversation

ArunmaniAlagarsamy2710
Copy link
Contributor

  • Implemented support for Wi-Fi Access Point (AP) mode.
  • Added support for AP-related Wi-Fi commands.
    Basic functionalities are included; further enhancements will be added in future PR.

return SL_WIFI_BANDWIDTH_80MHz;
default:
LOG_ERR("Invalid bandwidth");
return -EAGAIN;
Copy link
Contributor

@jerome-pouiller jerome-pouiller Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably -EINVAL is better suited.

I am not sure LOG_ERR() is useful (in fact, I don't know what policy we should have for the the logs).

@@ -14,6 +14,8 @@
#include "sl_si91x_types.h"
#include "sl_si91x_protocol_types.h"

#define SIWX91X_INTERFACE_MASK (0x03)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, SIWX91X_INTERFACE_MASK is only used in siwx91x_wifi.c. I am not sure it make sense to expose it in the header file.

status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, &sidev->macaddr);
interface = sl_wifi_get_default_interface();
status = sl_wifi_get_mac_address(FIELD_GET(SIWX91X_INTERFACE_MASK, interface),
&sidev->macaddr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what case the original code didn't work?

}
}

ret = sl_wifi_start_ap(SL_WIFI_AP_2_4GHZ_INTERFACE, &configuration);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the reader, it difficult to understand SL_WIFI_AP_2_4GHZ_INTERFACE == SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE. I suggest either:

  • Replace references to SL_WIFI_AP_INTERFACE by FIELD_GET(SIWX91X_INTERFACE_MASK, SL_WIFI_AP_2_4GHZ_INTERFACE)
  • Replace reference to SL_WIFI_AP_2_4GHZ_INTERFACE by SL_WIFI_AP_INTERFACE | SL_WIFI_2_4GHZ_INTERFACE

}

sl_si91x_set_join_configuration(SL_WIFI_AP_INTERFACE,
SL_SI91X_JOIN_FEAT_MFP_CAPABLE_REQUIRED);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think MFP is orthogonal to the authentication scheme. Probably this configuration should done outside of this switch case.

BTW, WPA2-PSK w/o MFP seems legit. Is it a limitation of Wiseconnect?

I also assume configuration.security = SL_WIFI_WPA3 automatically enables MFP? If ye, we could check params->mfp == WIFI_MFP_REQUIRED.

strncpy(status->ssid, wlan_info.ssid, WIFI_SSID_MAX_LEN);
status->ssid_len = strlen(status->ssid);
memcpy(status->bssid, wlan_info.mac_address, WIFI_MAC_ADDR_LEN);
status->mfp = WIFI_MFP_REQUIRED;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can you be sure?

memcpy(status->bssid, wlan_info.mac_address, WIFI_MAC_ADDR_LEN);
status->mfp = WIFI_MFP_REQUIRED;

if (FIELD_GET(SL_WIFI_2_4GHZ_INTERFACE, interface)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SL_WIFI_2_4GHZ_INTERFACE is not a mask. I would either write:

  • FIELD_GET(SIWX91X_BAND_MASK, interface) == 1
  • interface & SL_WIFI_2_4GHZ_INTERFACE

status->band = WIFI_FREQ_BAND_2_4_GHZ;
}

if (FIELD_GET(SL_WIFI_CLIENT_INTERFACE, interface)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SL_WIFI_CLIENT_INTERFACE is not a mask. I suggest FIELD_GET(SIWX91X_INTERFACE_MASK, interface) == SL_WIFI_CLIENT_INTERFACE.


sl_wifi_get_listen_interval(SL_WIFI_CLIENT_INTERFACE, &listen_interval);
status->beacon_interval = listen_interval.listen_interval;
} else if (FIELD_GET(SL_WIFI_AP_INTERFACE, interface)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this condition be true? oper_mode is always SL_SI91X_CLIENT_MODE. So, I think interface never set SL_WIFI_AP_INTERFACE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have added the support to change oper_mode at runtime #85919

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe #85919 should be a part of this current PR.

sl_wifi_get_listen_interval(SL_WIFI_CLIENT_INTERFACE, &listen_interval);
status->beacon_interval = listen_interval.listen_interval;
} else if (FIELD_GET(SL_WIFI_AP_INTERFACE, interface)) {
sl_wifi_ap_configuration_t conf = { };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ap_cfg or sl_ap_cfg or siwx91x_ap_cfg.

Copy link
Contributor

@jerome-pouiller jerome-pouiller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3 first commits depend on drivers: wifi: siwx91x: Add run time opermode, so you have place it first.

SL_SI91X_TCP_IP_FEAT_BYPASS),
.custom_feature_bit_map = SL_SI91X_CUSTOM_FEAT_EXTENSION_VALID,
.feature_bit_map = SL_SI91X_FEAT_SECURITY_OPEN,
.coex_mode = SL_SI91X_WLAN_ONLY_MODE,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you deal with BLE?

I feel this function is in fact shared with Bluetooth and event with Flash driver. Probably it should be located in soc/silabs/silabs_siwx91x/siwg917/nwp_init.c.


#include "sl_wifi.h"

static inline int get_wifi_device_configuration(sl_wifi_device_configuration_t *net_dev_cfg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this function is defined in the header file?

BTW, prefix the function name with the right prefix (siwg917_nwp_ I think).

NET_BUF_POOL_FIXED_DEFINE(siwx91x_tx_pool, 1, _NET_ETH_MAX_FRAME_SIZE, 0, NULL);

static inline int siwx91x_get_mode(uint8_t z_mode, sl_wifi_interface_t iface, uint16_t *sl_opermode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why inline?

{
sl_status_t status;

status = sl_wifi_deinit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the impact of this on the other services: bluetooth and flash?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Bluetooth is enabled, it will also be deinitialized along with Wi-Fi. I did not find any logic in sl_si91x_host_power_cycle affecting the flash, so I believe there is no impact on it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume any Flash access will also abort because of the reset of a DMA somewhere.

I believe the user do not expect the bluetooth will be impacted. I assume it is very difficult (impossible?) remove this limitation?

At least, we have at least to add a FIXME in the code and a LOG_WARN().

I think we could detect Bluetooth or Flash is in use (typically with an atomic counter, but maybe WiseConnect already provide an API for that). Then we could return an error if Bluetooth/Flash is in use.

Anyway, I believe it make more sense to relocate this function in the "shared" area of the 917 (nwp_init.c). I believe it will be easier if it take the new oper_mode in parameter rather than the whole sl_wifi_device_configuration_t.

case WIFI_STA_MODE:
if (FIELD_GET(SIWX91X_INTERFACE_MASK, iface) == SL_WIFI_CLIENT_INTERFACE) {
return -EALREADY;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this function is bit misleading. Reader does not expect get_mode() does such test. Probably you want one function that return SL_SI91X_CLIENT_MODE / SL_SI91X_ACCESS_POINT_MODE from z_mode and another that return SL_SI91X_CLIENT_MODE / SL_SI91X_ACCESS_POINT_MODE from the sl_wifi_interface_t. Then you can check if nwp_reboot() is required or not.

#include "sl_wifi_callback_framework.h"
#ifdef CONFIG_BT_SILABS_SIWX91X
#include "rsi_ble_common_config.h"
#endif

static int siwg917_nwp_init(void)
int siwg917_nwp_get_configuration(sl_wifi_device_configuration_t *net_dev_cfg)
{
sl_wifi_device_configuration_t network_config = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you find more consistent names, rather than net_dev_cfg and network_config (and cfg).

{
sl_status_t status;

status = sl_wifi_deinit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume any Flash access will also abort because of the reset of a DMA somewhere.

I believe the user do not expect the bluetooth will be impacted. I assume it is very difficult (impossible?) remove this limitation?

At least, we have at least to add a FIXME in the code and a LOG_WARN().

I think we could detect Bluetooth or Flash is in use (typically with an atomic counter, but maybe WiseConnect already provide an API for that). Then we could return an error if Bluetooth/Flash is in use.

Anyway, I believe it make more sense to relocate this function in the "shared" area of the 917 (nwp_init.c). I believe it will be easier if it take the new oper_mode in parameter rather than the whole sl_wifi_device_configuration_t.

}

if (siwx91x_get_mode(mode->mode) < 0) {
return -EINVAL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If siwx91x_get_mode() < 0, it means that we don't have to reboot, so we should return 0, no?

BTW, I believe the following code would be more explicit for the reader:

    int current_mode = siwx91x_get_iface_mode(interface);
    int requested_mode = siwx91x_convert_mode(mode->mode);
    if (current_mode == requested_mode) {
        return 0;
    }
    siwx91x_nwp_reboot(requested_mode);

Copy link
Contributor

@jerome-pouiller jerome-pouiller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code has now a good shape. This is probably the last iteration.

/* FIXME: Calling sl_wifi_deinit() impacts Bluetooth if coexistence is enabled */
if (IS_ENABLED(CONFIG_BT_SILABS_SIWX91X) && oper_mode == WIFI_AP_MODE) {
LOG_WRN("Bluetooth is not supported in AP mode");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it make more sense to make this test in siwg91x_get_nwp_config() / if (wifi_oper_mode == SL_SI91X_ACCESS_POINT_MODE).

ret = siwx91x_nwp_mode_switch(mode->mode);
if (ret) {
return ret;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once siwx91x_nwp_mode_switch() takes a Zephyr mode as argument, the idea was to simplify everything:

static int siwx91x_mode(const struct device *dev, struct wifi_mode_info *mode)
{
	sl_wifi_interface_t interface = sl_wifi_get_default_interface();
	struct siwx91x_dev *sidev = dev->data;
	int cur_mode;
	int ret = 0;

	__ASSERT(mode, "mode cannot be NULL");

	cur_mode = siwx91x_sl_to_z_mode(FIELD_GET(SIWX91X_INTERFACE_MASK, interface));
	if (cur_mode < 0) {
		return -EIO;
	}

	if (mode->oper == WIFI_MGMT_GET) {
		mode->mode = cur_mode;
	} else if (mode->oper == WIFI_MGMT_SET) {
		if (cur_mode != mode->mode) {
			ret = siwx91x_nwp_mode_switch(mode->mode);
			if (ret < 0) {
				return ret;
			}
		}
		sidev->state = WIFI_STATE_INACTIVE;
	}

	return 0;
}

Then, siwx91x_nwp_mode_switch() does not have to check the current status of the interface.

@ArunmaniAlagarsamy2710 ArunmaniAlagarsamy2710 force-pushed the driver/access_point branch 2 times, most recently from 61862ae to 71a08a7 Compare March 7, 2025 10:52
jerome-pouiller
jerome-pouiller previously approved these changes Mar 7, 2025
@ArunmaniAlagarsamy2710
Copy link
Contributor Author

@jhedberg Could you please review it?

Comment on lines 134 to 138
if (siwx91x_security(params->security) < 0) {
return -EINVAL;
}

siwx91x_ap_cfg.security = siwx91x_security(params->security);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another minor thing (sorry, I should have pointed this out in the last review): it seems a bit inefficient to be calling siwx91x_security() twice on the exact same input parameter. Why not just store the return value in a local int sec variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment, we followed this approach to maintain consistency with the style used in the silabs DMA driver.
https://github.com/zephyrproject-rtos/zephyr/blob/658f9357b87ab3e02351a57183743ec70f92cdd7/drivers/dma/dma_silabs_siwx91x.c#L143

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consistency is important, but that doesn't mean that you should not question existing code. The code you pointed to looks also inefficient. Any comment from @smalae? (the author)

@ArunmaniAlagarsamy2710 ArunmaniAlagarsamy2710 changed the title Add Access Point (AP) mode support to siwx91x wifi driver driver: wifi: siwx91x: Add Access Point (AP) mode support to siwx91x wifi driver Mar 10, 2025
jhedberg
jhedberg previously approved these changes Mar 10, 2025
jukkar
jukkar previously approved these changes Mar 13, 2025
@jerome-pouiller
Copy link
Contributor

@ArunmaniAlagarsamy2710 Can you rebase your branch?

This commit enables the device to change its operating mode
at runtime.

Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
This commit introduces Access Point (AP) mode support
It enables the following AP-related commands:
- ap enable: Enable the AP mode.
- ap disable: Disable the AP mode.

Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
This commit adds support the following wifi commands:
- wifi ap disconnect: Disconnect a specific station from the AP.
- wifi ap stations: List connected devices.

Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
This commit adds support for Wi-Fi status and statistics
functionalities:
- wifi status	  : Displays the current mode status.
- wifi statistics : Provides details on the transmitted and
                    received packet counts.

Signed-off-by: Arunmani Alagarsamy <arunmani.a@silabs.com>
@jerome-pouiller
Copy link
Contributor

@jukkar, do you have any other comments about this PR?

@jerome-pouiller jerome-pouiller self-requested a review March 20, 2025 10:07
@carlescufi carlescufi merged commit 601a9fa into zephyrproject-rtos:main Mar 20, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants