From 693b535094caf0b079efae03fbb2c059aac7774a Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Thu, 17 Jan 2019 10:00:31 -0800 Subject: [PATCH] qcacld-3.0: Integrate DSC (vdev create/destroy) The Driver Synchronization Core (DSC) is a set of synchronization primitives for use by the driver's orchestration layer. It provides APIs for ensuring safe state transitions (including bring up and tear down) of major driver objects: a single driver, associated psocs, and their associated vdevs. As part of integrating the DSC APIs into HDD, protect vdev create and destroy. Change-Id: I005589da96ed0cdd5f9026ad86dc18a4898b7cdf CRs-Fixed: 2388123 --- core/hdd/src/wlan_hdd_dsc.c | 3 +- core/hdd/src/wlan_hdd_main.c | 297 +++++++++++++++++++---------------- core/hdd/src/wlan_hdd_p2p.c | 106 +++++++------ 3 files changed, 219 insertions(+), 187 deletions(-) diff --git a/core/hdd/src/wlan_hdd_dsc.c b/core/hdd/src/wlan_hdd_dsc.c index f64f2c32351e..793e77910bdc 100644 --- a/core/hdd/src/wlan_hdd_dsc.c +++ b/core/hdd/src/wlan_hdd_dsc.c @@ -212,7 +212,8 @@ struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev) hdd_vdev_sync_lock(); vdev_sync = hdd_vdev_sync_lookup(net_dev); - vdev_sync->net_dev = NULL; + if (vdev_sync) + vdev_sync->net_dev = NULL; hdd_vdev_sync_unlock(); return vdev_sync; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fae26fca45ae..3dbb5807563b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5274,13 +5274,21 @@ void hdd_close_adapter(struct hdd_context *hdd_ctx, void hdd_close_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held) { struct hdd_adapter *adapter; + struct hdd_vdev_sync *vdev_sync; hdd_enter(); while (QDF_IS_STATUS_SUCCESS(hdd_remove_front_adapter(hdd_ctx, &adapter))) { + vdev_sync = hdd_vdev_sync_unregister(adapter->dev); + if (vdev_sync) + hdd_vdev_sync_wait_for_ops(vdev_sync); + wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes); __hdd_close_adapter(hdd_ctx, adapter, rtnl_held); + + if (vdev_sync) + hdd_vdev_sync_destroy(vdev_sync); } hdd_exit(); @@ -9284,21 +9292,14 @@ static void hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx) int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx) { struct hdd_psoc *hdd_psoc = hdd_ctx->hdd_psoc; - QDF_STATUS status; int errno; - status = dsc_psoc_trans_start_wait(hdd_psoc->dsc_psoc, "idle restart"); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_info("unable to start 'idle restart'; status:%u", status); - return qdf_status_to_os_return(status); - } + QDF_BUG(rtnl_is_locked()); errno = hdd_wlan_start_modules(hdd_ctx, false); if (!errno) hdd_psoc->state = psoc_state_active; - dsc_psoc_trans_stop(hdd_psoc->dsc_psoc); - return errno; } @@ -9610,114 +9611,6 @@ err_out: return ERR_PTR(ret); } -#ifdef WLAN_OPEN_P2P_INTERFACE -/** - * hdd_open_p2p_interface - Open P2P interface - * @hdd_ctx: HDD context - * - * Return: QDF_STATUS - */ -static QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx) -{ - struct hdd_adapter *adapter; - bool p2p_dev_addr_admin; - bool is_p2p_locally_administered = false; - - cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin); - - if (p2p_dev_addr_admin) { - if (hdd_ctx->num_provisioned_addr && - !(hdd_ctx->provisioned_mac_addr[0].bytes[0] & 0x02)) { - hdd_ctx->p2p_device_address = - hdd_ctx->provisioned_mac_addr[0]; - - /* - * Generate the P2P Device Address. This consists of - * the device's primary MAC address with the locally - * administered bit set. - */ - - hdd_ctx->p2p_device_address.bytes[0] |= 0x02; - is_p2p_locally_administered = true; - } else if (!(hdd_ctx->derived_mac_addr[0].bytes[0] & 0x02)) { - hdd_ctx->p2p_device_address = - hdd_ctx->derived_mac_addr[0]; - /* - * Generate the P2P Device Address. This consists of - * the device's primary MAC address with the locally - * administered bit set. - */ - hdd_ctx->p2p_device_address.bytes[0] |= 0x02; - is_p2p_locally_administered = true; - } - } - if (!is_p2p_locally_administered) { - uint8_t *p2p_dev_addr; - - p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx, - QDF_P2P_DEVICE_MODE); - if (!p2p_dev_addr) { - hdd_err("Failed to get MAC address for new p2p device"); - return QDF_STATUS_E_INVAL; - } - - qdf_mem_copy(hdd_ctx->p2p_device_address.bytes, - p2p_dev_addr, QDF_MAC_ADDR_SIZE); - } - - adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d", - hdd_ctx->p2p_device_address.bytes, - NET_NAME_UNKNOWN, true); - if (!adapter) { - hdd_err("Failed to open p2p interface"); - return QDF_STATUS_E_INVAL; - } - - return QDF_STATUS_SUCCESS; -} -#else -static inline QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx) -{ - return QDF_STATUS_SUCCESS; -} -#endif - -static QDF_STATUS hdd_open_ocb_interface(struct hdd_context *hdd_ctx) -{ - struct hdd_adapter *adapter; - - adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d", - wlan_hdd_get_intf_addr(hdd_ctx, - QDF_OCB_MODE), - NET_NAME_UNKNOWN, true); - if (!adapter) { - hdd_err("Failed to open 802.11p interface"); - return QDF_STATUS_E_INVAL; - } - - return QDF_STATUS_SUCCESS; -} - -static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx) -{ - struct hdd_adapter *adapter; - - if (qdf_str_eq(hdd_ctx->config->enable_concurrent_sta, "")) - return QDF_STATUS_SUCCESS; - - adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, - hdd_ctx->config->enable_concurrent_sta, - wlan_hdd_get_intf_addr(hdd_ctx, - QDF_STA_MODE), - NET_NAME_UNKNOWN, true); - if (!adapter) { - hdd_err("Failed to open concurrent station interface"); - return QDF_STATUS_E_INVAL; - } - - return QDF_STATUS_SUCCESS; -} - /** * hdd_start_station_adapter()- Start the Station Adapter * @adapter: HDD adapter @@ -11747,12 +11640,151 @@ static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx) } #endif +static QDF_STATUS hdd_open_adapter_no_trans(struct hdd_context *hdd_ctx, + enum QDF_OPMODE op_mode, + const char *iface_name, + uint8_t *mac_addr_bytes) +{ + struct hdd_vdev_sync *vdev_sync; + struct hdd_adapter *adapter; + QDF_STATUS status; + int errno; + + QDF_BUG(rtnl_is_locked()); + dsc_psoc_assert_trans_protected(hdd_ctx->hdd_psoc->dsc_psoc); + + errno = hdd_vdev_sync_create(hdd_ctx->wiphy, &vdev_sync); + if (errno) + return qdf_status_from_os_return(errno); + + adapter = hdd_open_adapter(hdd_ctx, op_mode, iface_name, + mac_addr_bytes, NET_NAME_UNKNOWN, true); + if (!adapter) { + status = QDF_STATUS_E_INVAL; + goto destroy_sync; + } + + hdd_vdev_sync_register(adapter->dev, vdev_sync); + + return QDF_STATUS_SUCCESS; + +destroy_sync: + hdd_vdev_sync_destroy(vdev_sync); + + return status; +} + +#ifdef WLAN_OPEN_P2P_INTERFACE +/** + * hdd_open_p2p_interface - Open P2P interface + * @hdd_ctx: HDD context + * + * Return: QDF_STATUS + */ +static QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + bool p2p_dev_addr_admin; + bool is_p2p_locally_administered = false; + + cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin); + + if (p2p_dev_addr_admin) { + if (hdd_ctx->num_provisioned_addr && + !(hdd_ctx->provisioned_mac_addr[0].bytes[0] & 0x02)) { + hdd_ctx->p2p_device_address = + hdd_ctx->provisioned_mac_addr[0]; + + /* + * Generate the P2P Device Address. This consists of + * the device's primary MAC address with the locally + * administered bit set. + */ + + hdd_ctx->p2p_device_address.bytes[0] |= 0x02; + is_p2p_locally_administered = true; + } else if (!(hdd_ctx->derived_mac_addr[0].bytes[0] & 0x02)) { + hdd_ctx->p2p_device_address = + hdd_ctx->derived_mac_addr[0]; + /* + * Generate the P2P Device Address. This consists of + * the device's primary MAC address with the locally + * administered bit set. + */ + hdd_ctx->p2p_device_address.bytes[0] |= 0x02; + is_p2p_locally_administered = true; + } + } + if (!is_p2p_locally_administered) { + uint8_t *p2p_dev_addr; + + p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx, + QDF_P2P_DEVICE_MODE); + if (!p2p_dev_addr) { + hdd_err("Failed to get MAC address for new p2p device"); + return QDF_STATUS_E_INVAL; + } + + qdf_mem_copy(hdd_ctx->p2p_device_address.bytes, + p2p_dev_addr, QDF_MAC_ADDR_SIZE); + } + + status = hdd_open_adapter_no_trans(hdd_ctx, QDF_P2P_DEVICE_MODE, + "p2p%d", + hdd_ctx->p2p_device_address.bytes); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to open p2p interface"); + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +static QDF_STATUS hdd_open_ocb_interface(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + uint8_t *mac_addr; + + mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_OCB_MODE); + status = hdd_open_adapter_no_trans(hdd_ctx, QDF_OCB_MODE, + "wlanocb%d", mac_addr); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to open 802.11p interface"); + + return status; +} + +static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + const char *iface_name; + uint8_t *mac_addr; + + if (qdf_str_eq(hdd_ctx->config->enable_concurrent_sta, "")) + return QDF_STATUS_SUCCESS; + + iface_name = hdd_ctx->config->enable_concurrent_sta; + mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE); + status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, + iface_name, mac_addr); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to open concurrent station interface"); + + return status; +} + static QDF_STATUS hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx) { - struct hdd_adapter *adapter; enum dot11p_mode dot11p_mode; QDF_STATUS status; + uint8_t *mac_addr; ucfg_mlme_get_dot11p_mode(hdd_ctx->psoc, &dot11p_mode); @@ -11760,12 +11792,11 @@ hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx) if (dot11p_mode == CFG_11P_STANDALONE) return hdd_open_ocb_interface(hdd_ctx); - adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx, - QDF_STA_MODE), - NET_NAME_UNKNOWN, true); - if (!adapter) - return QDF_STATUS_E_INVAL; + mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE); + status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, + "wlan%d", mac_addr); + if (QDF_IS_STATUS_ERROR(status)) + return status; /* opening concurrent STA is best effort, continue on error */ hdd_open_concurrent_interface(hdd_ctx); @@ -11791,27 +11822,19 @@ err_close_adapters: static QDF_STATUS hdd_open_adapters_for_ftm_mode(struct hdd_context *hdd_ctx) { - struct hdd_adapter *adapter; + uint8_t *mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_FTM_MODE); - adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx, - QDF_FTM_MODE), - NET_NAME_UNKNOWN, true); - - return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL; + return hdd_open_adapter_no_trans(hdd_ctx, QDF_FTM_MODE, + "wlan%d", mac_addr); } static QDF_STATUS hdd_open_adapters_for_monitor_mode(struct hdd_context *hdd_ctx) { - struct hdd_adapter *adapter; + uint8_t *mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_MONITOR_MODE); - adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx, - QDF_MONITOR_MODE), - NET_NAME_UNKNOWN, true); - - return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL; + return hdd_open_adapter_no_trans(hdd_ctx, QDF_MONITOR_MODE, + "wlan%d", mac_addr); } static QDF_STATUS hdd_open_adapters_for_epping_mode(struct hdd_context *hdd_ctx) diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 242a150a0019..7d34dc7738a2 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -24,6 +24,7 @@ * */ +#include "wlan_hdd_dsc.h" #include #include #include @@ -739,6 +740,42 @@ close_adapter: return ERR_PTR(-EINVAL); } +static struct wireless_dev * +_wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct wireless_dev *wdev; + struct hdd_vdev_sync *vdev_sync; + int errno; + + errno = hdd_vdev_sync_create_with_trans(wiphy, &vdev_sync); + if (errno) + return ERR_PTR(errno); + + cds_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, flags, params); + cds_ssr_unprotect(__func__); + + if (IS_ERR_OR_NULL(wdev)) + goto destroy_sync; + + hdd_vdev_sync_register(wdev->netdev, vdev_sync); + hdd_vdev_sync_trans_stop(vdev_sync); + + return wdev; + +destroy_sync: + hdd_vdev_sync_trans_stop(vdev_sync); + hdd_vdev_sync_destroy(vdev_sync); + + return wdev; +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, const char *name, @@ -746,27 +783,10 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, enum nl80211_iftype type, struct vif_params *params) { - struct wireless_dev *wdev; - - cds_ssr_protect(__func__); - wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, - type, ¶ms->flags, params); - cds_ssr_unprotect(__func__); - - return wdev; + return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, ¶ms->flags, params); } #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS) -/** - * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper - * @wiphy: wiphy pointer - * @name: User-visible name of the interface - * @name_assign_type: the name of assign type of the netdev - * @nl80211_iftype: (virtual) interface types - * @flags: monitor mode configuration flags (not used) - * @vif_params: virtual interface parameters (not used) - * - * Return: the pointer of wireless dev, otherwise ERR_PTR. - */ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, @@ -774,41 +794,18 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, u32 *flags, struct vif_params *params) { - struct wireless_dev *wdev; - - cds_ssr_protect(__func__); - wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, - type, flags, params); - cds_ssr_unprotect(__func__); - return wdev; - + return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, flags, params); } #else -/** - * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper - * @wiphy: wiphy pointer - * @name: User-visible name of the interface - * @nl80211_iftype: (virtual) interface types - * @flags: monitor mode configuration flags (not used) - * @vif_params: virtual interface parameters (not used) - * - * Return: the pointer of wireless dev, otherwise ERR_PTR. - */ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, const char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct wireless_dev *wdev; - unsigned char name_assign_type = 0; - - cds_ssr_protect(__func__); - wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, - type, flags, params); - cds_ssr_unprotect(__func__); - return wdev; - + return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, flags, params); } #endif @@ -866,13 +863,24 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) { - int ret; + int errno; + struct hdd_vdev_sync *vdev_sync; + + errno = hdd_vdev_sync_trans_start_wait(wdev->netdev, &vdev_sync); + if (errno) + return errno; + + hdd_vdev_sync_unregister(wdev->netdev); + hdd_vdev_sync_wait_for_ops(vdev_sync); cds_ssr_protect(__func__); - ret = __wlan_hdd_del_virtual_intf(wiphy, wdev); + errno = __wlan_hdd_del_virtual_intf(wiphy, wdev); cds_ssr_unprotect(__func__); - return ret; + hdd_vdev_sync_trans_stop(vdev_sync); + hdd_vdev_sync_destroy(vdev_sync); + + return errno; } /**