|
@@ -1325,35 +1325,41 @@ static void hdd_runtime_suspend_context_deinit(struct hdd_context *hdd_ctx) {}
|
|
|
|
|
|
#define INTF_MACADDR_MASK 0x7
|
|
|
|
|
|
-/**
|
|
|
- * hdd_update_macaddr() - update mac address
|
|
|
- * @config: hdd configuration
|
|
|
- * @hw_macaddr: mac address
|
|
|
- *
|
|
|
- * Mac address for multiple virtual interface is found as following
|
|
|
- * i) The mac address of the first interface is just the actual hw mac address.
|
|
|
- * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
|
|
|
- * define the mac address for the remaining interfaces and locally
|
|
|
- * admistered bit is set. INTF_MACADDR_MASK is based on the number of
|
|
|
- * supported virtual interfaces, right now this is 0x07 (meaning 8
|
|
|
- * interface).
|
|
|
- * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
|
|
|
- * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- */
|
|
|
-void hdd_update_macaddr(struct hdd_config *config,
|
|
|
- struct qdf_mac_addr hw_macaddr)
|
|
|
+void hdd_update_macaddr(struct hdd_context *hdd_ctx,
|
|
|
+ struct qdf_mac_addr hw_macaddr, bool generate_mac_auto)
|
|
|
{
|
|
|
int8_t i;
|
|
|
uint8_t macaddr_b3, tmp_br3;
|
|
|
|
|
|
- qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
|
|
|
- QDF_MAC_ADDR_SIZE);
|
|
|
- for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
|
|
|
- qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
|
|
|
+ /*
|
|
|
+ * If "generate_mac_auto" is true, it indicates that all the
|
|
|
+ * addresses are derived addresses, else the first addresses
|
|
|
+ * is not derived address (It is provided by fw).
|
|
|
+ */
|
|
|
+ if (!generate_mac_auto) {
|
|
|
+ qdf_mem_copy(hdd_ctx->provisioned_mac_addr[0].bytes,
|
|
|
+ hw_macaddr.bytes, QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_ctx->num_provisioned_addr++;
|
|
|
+ hdd_info("hdd_ctx->provisioned_mac_addr[0]: "
|
|
|
+ MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(hdd_ctx->
|
|
|
+ provisioned_mac_addr[0].bytes));
|
|
|
+ } else {
|
|
|
+ qdf_mem_copy(hdd_ctx->derived_mac_addr[0].bytes,
|
|
|
+ hw_macaddr.bytes,
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_ctx->num_derived_addr++;
|
|
|
+ hdd_info("hdd_ctx->derived_mac_addr[0]: "
|
|
|
+ MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(hdd_ctx->derived_mac_addr[0].bytes));
|
|
|
+ }
|
|
|
+ for (i = hdd_ctx->num_derived_addr; i < (QDF_MAX_CONCURRENCY_PERSONA -
|
|
|
+ hdd_ctx->num_provisioned_addr);
|
|
|
+ i++) {
|
|
|
+ qdf_mem_copy(hdd_ctx->derived_mac_addr[i].bytes,
|
|
|
+ hw_macaddr.bytes,
|
|
|
QDF_MAC_ADDR_SIZE);
|
|
|
- macaddr_b3 = config->intfMacAddr[i].bytes[3];
|
|
|
+ macaddr_b3 = hdd_ctx->derived_mac_addr[i].bytes[3];
|
|
|
tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
|
|
|
INTF_MACADDR_MASK;
|
|
|
macaddr_b3 += tmp_br3;
|
|
@@ -1364,11 +1370,12 @@ void hdd_update_macaddr(struct hdd_config *config,
|
|
|
macaddr_b3 ^= (1 << 7);
|
|
|
|
|
|
/* Set locally administered bit */
|
|
|
- config->intfMacAddr[i].bytes[0] |= 0x02;
|
|
|
- config->intfMacAddr[i].bytes[3] = macaddr_b3;
|
|
|
- hdd_debug("config->intfMacAddr[%d]: "
|
|
|
- MAC_ADDRESS_STR, i,
|
|
|
- MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
|
|
|
+ hdd_ctx->derived_mac_addr[i].bytes[0] |= 0x02;
|
|
|
+ hdd_ctx->derived_mac_addr[i].bytes[3] = macaddr_b3;
|
|
|
+ hdd_info("hdd_ctx->derived_mac_addr[%d]: "
|
|
|
+ MAC_ADDRESS_STR, i,
|
|
|
+ MAC_ADDR_ARRAY(hdd_ctx->derived_mac_addr[i].bytes));
|
|
|
+ hdd_ctx->num_derived_addr++;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1851,7 +1858,7 @@ static int hdd_generate_macaddr_auto(struct hdd_context *hdd_ctx)
|
|
|
mac_addr.bytes[4] = (serialno >> 8) & 0xff;
|
|
|
mac_addr.bytes[5] = serialno & 0xff;
|
|
|
|
|
|
- hdd_update_macaddr(hdd_ctx->config, mac_addr);
|
|
|
+ hdd_update_macaddr(hdd_ctx, mac_addr, true);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2003,28 +2010,11 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
|
|
|
|
|
|
/* This can be extended to other configurations like ht, vht cap... */
|
|
|
|
|
|
- if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
|
|
|
- hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
|
|
|
- hdd_ctx->update_mac_addr_to_fw = false;
|
|
|
- } else {
|
|
|
- static struct qdf_mac_addr default_mac_addr = {
|
|
|
- {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
|
|
|
- };
|
|
|
- if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
|
|
|
- &default_mac_addr)) {
|
|
|
- if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
|
|
|
- hdd_err("Fail to auto-generate MAC, using MAC from ini file "
|
|
|
- MAC_ADDRESS_STR,
|
|
|
- MAC_ADDR_ARRAY(hdd_ctx->config->
|
|
|
- intfMacAddr[0].bytes));
|
|
|
- } else {
|
|
|
- hdd_err("Invalid MAC passed from target, using MAC from ini file "
|
|
|
- MAC_ADDRESS_STR,
|
|
|
- MAC_ADDR_ARRAY(hdd_ctx->config->
|
|
|
- intfMacAddr[0].bytes));
|
|
|
- }
|
|
|
- hdd_ctx->update_mac_addr_to_fw = true;
|
|
|
- }
|
|
|
+ if (!qdf_is_macaddr_zero(&cfg->hw_macaddr))
|
|
|
+ qdf_mem_copy(&hdd_ctx->hw_macaddr, &cfg->hw_macaddr,
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ else
|
|
|
+ hdd_info("hw_mac is zero");
|
|
|
|
|
|
hdd_ctx->target_fw_version = cfg->target_fw_version;
|
|
|
hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
|
|
@@ -3470,10 +3460,11 @@ void hdd_update_dynamic_mac(struct hdd_context *hdd_ctx,
|
|
|
hdd_enter();
|
|
|
|
|
|
for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
|
|
|
- if (!qdf_mem_cmp(curr_mac_addr->bytes,
|
|
|
- &hdd_ctx->dynamic_mac_list[i].bytes[0],
|
|
|
+ if (!qdf_mem_cmp(
|
|
|
+ curr_mac_addr->bytes,
|
|
|
+ &hdd_ctx->dynamic_mac_list[i].dynamic_mac.bytes[0],
|
|
|
sizeof(struct qdf_mac_addr))) {
|
|
|
- qdf_mem_copy(&hdd_ctx->dynamic_mac_list[i],
|
|
|
+ qdf_mem_copy(&hdd_ctx->dynamic_mac_list[i].dynamic_mac,
|
|
|
new_mac_addr->bytes,
|
|
|
sizeof(struct qdf_mac_addr));
|
|
|
break;
|
|
@@ -3563,35 +3554,129 @@ static int hdd_set_mac_address(struct net_device *dev, void *addr)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-uint8_t *wlan_hdd_get_intf_addr(struct hdd_context *hdd_ctx)
|
|
|
+static uint8_t *wlan_hdd_get_derived_intf_addr(struct hdd_context *hdd_ctx)
|
|
|
{
|
|
|
- int i;
|
|
|
+ int i, j;
|
|
|
|
|
|
- i = qdf_ffz(hdd_ctx->config->intfAddrMask);
|
|
|
- if (i < 0 || i >= QDF_MAX_CONCURRENCY_PERSONA)
|
|
|
+ i = qdf_ffz(hdd_ctx->derived_intf_addr_mask);
|
|
|
+ if (i < 0 || i >= hdd_ctx->num_derived_addr)
|
|
|
+ return NULL;
|
|
|
+ qdf_atomic_set_bit(i, &hdd_ctx->derived_intf_addr_mask);
|
|
|
+ hdd_info("Assigning MAC from derived list" MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(hdd_ctx->derived_mac_addr[i].bytes));
|
|
|
+
|
|
|
+ /* Copy the mac in dynamic mac list at first free position */
|
|
|
+ for (j = 0; j < QDF_MAX_CONCURRENCY_PERSONA; j++) {
|
|
|
+ if (qdf_is_macaddr_zero(&hdd_ctx->
|
|
|
+ dynamic_mac_list[j].dynamic_mac))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (j == QDF_MAX_CONCURRENCY_PERSONA) {
|
|
|
+ hdd_err("Max interfaces are up");
|
|
|
return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_mem_copy(&hdd_ctx->dynamic_mac_list[j].dynamic_mac.bytes,
|
|
|
+ &hdd_ctx->derived_mac_addr[i].bytes,
|
|
|
+ sizeof(struct qdf_mac_addr));
|
|
|
+ hdd_ctx->dynamic_mac_list[j].is_provisioned_mac = false;
|
|
|
+ hdd_ctx->dynamic_mac_list[j].bit_position = i;
|
|
|
+
|
|
|
+ return hdd_ctx->derived_mac_addr[i].bytes;
|
|
|
+}
|
|
|
+
|
|
|
+static uint8_t *wlan_hdd_get_provisioned_intf_addr(struct hdd_context *hdd_ctx)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
|
|
|
- hdd_ctx->config->intfAddrMask |= (1 << i);
|
|
|
+ i = qdf_ffz(hdd_ctx->provisioned_intf_addr_mask);
|
|
|
+ if (i < 0 || i >= hdd_ctx->num_provisioned_addr)
|
|
|
+ return NULL;
|
|
|
+ qdf_atomic_set_bit(i, &hdd_ctx->provisioned_intf_addr_mask);
|
|
|
+ hdd_info("Assigning MAC from provisioned list" MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(hdd_ctx->provisioned_mac_addr[i].bytes));
|
|
|
+
|
|
|
+ /* Copy the mac in dynamic mac list at first free position */
|
|
|
+ for (j = 0; j < QDF_MAX_CONCURRENCY_PERSONA; j++) {
|
|
|
+ if (qdf_is_macaddr_zero(&hdd_ctx->
|
|
|
+ dynamic_mac_list[j].dynamic_mac))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (j == QDF_MAX_CONCURRENCY_PERSONA) {
|
|
|
+ hdd_err("Max interfaces are up");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
- qdf_mem_copy(&hdd_ctx->dynamic_mac_list[i].bytes,
|
|
|
- &hdd_ctx->config->intfMacAddr[i].bytes,
|
|
|
+ qdf_mem_copy(&hdd_ctx->dynamic_mac_list[j].dynamic_mac.bytes,
|
|
|
+ &hdd_ctx->provisioned_mac_addr[i].bytes,
|
|
|
sizeof(struct qdf_mac_addr));
|
|
|
- return hdd_ctx->config->intfMacAddr[i].bytes;
|
|
|
+ hdd_ctx->dynamic_mac_list[j].is_provisioned_mac = true;
|
|
|
+ hdd_ctx->dynamic_mac_list[j].bit_position = i;
|
|
|
+ return hdd_ctx->provisioned_mac_addr[i].bytes;
|
|
|
+}
|
|
|
+
|
|
|
+uint8_t *wlan_hdd_get_intf_addr(struct hdd_context *hdd_ctx,
|
|
|
+ enum QDF_OPMODE interface_type)
|
|
|
+{
|
|
|
+ uint8_t *mac_addr = NULL;
|
|
|
+
|
|
|
+ if (qdf_atomic_test_bit(interface_type,
|
|
|
+ (unsigned long *)
|
|
|
+ (&hdd_ctx->config->provisioned_intf_pool)))
|
|
|
+ mac_addr = wlan_hdd_get_provisioned_intf_addr(hdd_ctx);
|
|
|
+
|
|
|
+ if ((!mac_addr) &&
|
|
|
+ (qdf_atomic_test_bit(interface_type,
|
|
|
+ (unsigned long *)
|
|
|
+ (&hdd_ctx->config->derived_intf_pool))))
|
|
|
+ mac_addr = wlan_hdd_get_derived_intf_addr(hdd_ctx);
|
|
|
+
|
|
|
+ if (!mac_addr)
|
|
|
+ hdd_err("MAC is not available in both the lists");
|
|
|
+ return mac_addr;
|
|
|
}
|
|
|
|
|
|
void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx,
|
|
|
uint8_t *releaseAddr)
|
|
|
{
|
|
|
int i;
|
|
|
+ int mac_pos_in_mask;
|
|
|
|
|
|
for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
|
|
|
if (!memcmp(releaseAddr,
|
|
|
- hdd_ctx->dynamic_mac_list[i].bytes,
|
|
|
- QDF_MAC_ADDR_SIZE)) {
|
|
|
- hdd_ctx->config->intfAddrMask &= ~(1 << i);
|
|
|
+ hdd_ctx->dynamic_mac_list[i].dynamic_mac.bytes,
|
|
|
+ QDF_MAC_ADDR_SIZE)) {
|
|
|
+ mac_pos_in_mask =
|
|
|
+ hdd_ctx->dynamic_mac_list[i].bit_position;
|
|
|
+ if (hdd_ctx->dynamic_mac_list[i].is_provisioned_mac) {
|
|
|
+ qdf_atomic_clear_bit(
|
|
|
+ mac_pos_in_mask,
|
|
|
+ &hdd_ctx->
|
|
|
+ provisioned_intf_addr_mask);
|
|
|
+ hdd_info("Releasing MAC from provisioned list");
|
|
|
+ hdd_info(
|
|
|
+ MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(releaseAddr));
|
|
|
+ } else {
|
|
|
+ qdf_atomic_clear_bit(
|
|
|
+ mac_pos_in_mask, &hdd_ctx->
|
|
|
+ derived_intf_addr_mask);
|
|
|
+ hdd_info("Releasing MAC from derived list");
|
|
|
+ hdd_info(MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(releaseAddr));
|
|
|
+ }
|
|
|
+ qdf_zero_macaddr(&hdd_ctx->
|
|
|
+ dynamic_mac_list[i].dynamic_mac);
|
|
|
+ hdd_ctx->dynamic_mac_list[i].is_provisioned_mac =
|
|
|
+ false;
|
|
|
+ hdd_ctx->dynamic_mac_list[i].bit_position = 0;
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+ if (i == QDF_MAX_CONCURRENCY_PERSONA)
|
|
|
+ hdd_err("Releasing non existing MAC" MAC_ADDRESS_STR,
|
|
|
+ MAC_ADDR_ARRAY(releaseAddr));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -4984,6 +5069,36 @@ static void hdd_init_completion(struct hdd_adapter *adapter)
|
|
|
init_completion(&adapter->lfr_fw_status.disable_lfr_event);
|
|
|
}
|
|
|
|
|
|
+static void hdd_reset_locally_admin_bit(struct hdd_context *hdd_ctx,
|
|
|
+ tSirMacAddr macAddr)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ /*
|
|
|
+ * Reset locally administered bit for dynamic_mac_list
|
|
|
+ * also as while releasing the MAC address for any
|
|
|
+ * interface mac will be compared with dynamic mac list
|
|
|
+ */
|
|
|
+ for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
|
|
|
+ if (!qdf_mem_cmp(
|
|
|
+ macAddr,
|
|
|
+ &hdd_ctx->
|
|
|
+ dynamic_mac_list[i].dynamic_mac.bytes[0],
|
|
|
+ sizeof(struct qdf_mac_addr))) {
|
|
|
+ WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(
|
|
|
+ hdd_ctx->
|
|
|
+ dynamic_mac_list[i].dynamic_mac.bytes);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Reset locally administered bit if the device mode is
|
|
|
+ * STA
|
|
|
+ */
|
|
|
+ WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
|
|
|
+ hdd_debug("locally administered bit reset in sta mode: "
|
|
|
+ MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* hdd_open_adapter() - open and setup the hdd adatper
|
|
|
* @hdd_ctx: global hdd context
|
|
@@ -5006,7 +5121,6 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
|
|
|
{
|
|
|
struct hdd_adapter *adapter = NULL;
|
|
|
QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
|
|
- uint8_t i;
|
|
|
|
|
|
if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
|
|
|
/*
|
|
@@ -5035,26 +5149,9 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
|
|
|
|
|
|
switch (session_type) {
|
|
|
case QDF_STA_MODE:
|
|
|
- /*
|
|
|
- * Reset locally administered bit for dynamic_mac_list
|
|
|
- * also as while releasing the MAC address for any interface
|
|
|
- * mac will be compared with dynamic mac list
|
|
|
- */
|
|
|
- for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
|
|
|
- if (!qdf_mem_cmp(
|
|
|
- macAddr,
|
|
|
- &hdd_ctx->dynamic_mac_list[i].bytes[0],
|
|
|
- sizeof(struct qdf_mac_addr))) {
|
|
|
- WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(
|
|
|
- hdd_ctx->dynamic_mac_list[i].bytes);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (!hdd_ctx->config->mac_provision)
|
|
|
+ hdd_reset_locally_admin_bit(hdd_ctx, macAddr);
|
|
|
|
|
|
- /* Reset locally administered bit if the device mode is STA */
|
|
|
- WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
|
|
|
- hdd_debug("locally administered bit reset in sta mode: "
|
|
|
- MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
|
|
|
/* fall through */
|
|
|
case QDF_P2P_CLIENT_MODE:
|
|
|
case QDF_P2P_DEVICE_MODE:
|
|
@@ -9380,12 +9477,11 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx)
|
|
|
cfg_get(psoc, CFG_DBS_SCAN_SELECTION),
|
|
|
CFG_DBS_SCAN_PARAM_LENGTH);
|
|
|
config->inform_bss_rssi_raw = cfg_get(psoc, CFG_INFORM_BSS_RSSI_RAW);
|
|
|
- config->intfMacAddr[0] = cfg_get(psoc, CFG_INTF0_MAC_ADDR);
|
|
|
- config->intfMacAddr[1] = cfg_get(psoc, CFG_INTF1_MAC_ADDR);
|
|
|
- config->intfMacAddr[2] = cfg_get(psoc, CFG_INTF2_MAC_ADDR);
|
|
|
- config->intfMacAddr[3] = cfg_get(psoc, CFG_INTF3_MAC_ADDR);
|
|
|
+ config->mac_provision = cfg_get(psoc, CFG_ENABLE_MAC_PROVISION);
|
|
|
+ config->provisioned_intf_pool =
|
|
|
+ cfg_get(psoc, CFG_PROVISION_INTERFACE_POOL);
|
|
|
+ config->derived_intf_pool = cfg_get(psoc, CFG_DERIVED_INTERFACE_POOL);
|
|
|
config->action_oui_enable = cfg_get(psoc, CFG_ENABLE_ACTION_OUI);
|
|
|
-
|
|
|
qdf_str_lcopy(config->action_oui_str[0],
|
|
|
cfg_get(psoc, CFG_ACTION_OUI_CONNECT_1X1),
|
|
|
ACTION_OUI_MAX_STR_LEN);
|
|
@@ -9538,23 +9634,41 @@ 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 &&
|
|
|
- !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
|
|
|
- hdd_ctx->p2p_device_address = hdd_ctx->config->intfMacAddr[0];
|
|
|
+ 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;
|
|
|
- } else {
|
|
|
+ /*
|
|
|
+ * 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);
|
|
|
+ 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;
|
|
@@ -9586,7 +9700,8 @@ 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),
|
|
|
+ wlan_hdd_get_intf_addr(hdd_ctx,
|
|
|
+ QDF_OCB_MODE),
|
|
|
NET_NAME_UNKNOWN, true);
|
|
|
if (!adapter) {
|
|
|
hdd_err("Failed to open 802.11p interface");
|
|
@@ -9605,7 +9720,8 @@ static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx)
|
|
|
|
|
|
adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE,
|
|
|
hdd_ctx->config->enable_concurrent_sta,
|
|
|
- wlan_hdd_get_intf_addr(hdd_ctx),
|
|
|
+ wlan_hdd_get_intf_addr(hdd_ctx,
|
|
|
+ QDF_STA_MODE),
|
|
|
NET_NAME_UNKNOWN, true);
|
|
|
if (!adapter) {
|
|
|
hdd_err("Failed to open concurrent station interface");
|
|
@@ -10166,6 +10282,19 @@ int hdd_pktlog_enable_disable(struct hdd_context *hdd_ctx, bool enable,
|
|
|
}
|
|
|
#endif /* REMOVE_PKT_LOG */
|
|
|
|
|
|
+void hdd_free_mac_address_lists(struct hdd_context *hdd_ctx)
|
|
|
+{
|
|
|
+ hdd_debug("Resetting MAC address lists");
|
|
|
+ qdf_mem_set(hdd_ctx->provisioned_mac_addr,
|
|
|
+ sizeof(hdd_ctx->provisioned_mac_addr), 0);
|
|
|
+ qdf_mem_set(hdd_ctx->derived_mac_addr,
|
|
|
+ sizeof(hdd_ctx->derived_mac_addr), 0);
|
|
|
+ hdd_ctx->num_provisioned_addr = 0;
|
|
|
+ hdd_ctx->num_derived_addr = 0;
|
|
|
+ hdd_ctx->provisioned_intf_addr_mask = 0;
|
|
|
+ hdd_ctx->derived_intf_addr_mask = 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* hdd_get_platform_wlan_mac_buff() - API to query platform driver
|
|
|
* for MAC address
|
|
@@ -10180,6 +10309,20 @@ static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
|
|
|
return pld_get_wlan_mac_address(dev, num);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * hdd_get_platform_wlan_derived_mac_buff() - API to query platform driver
|
|
|
+ * for derived MAC address
|
|
|
+ * @dev: Device Pointer
|
|
|
+ * @num: Number of Valid Mac address
|
|
|
+ *
|
|
|
+ * Return: Pointer to MAC address buffer
|
|
|
+ */
|
|
|
+static uint8_t *hdd_get_platform_wlan_derived_mac_buff(struct device *dev,
|
|
|
+ uint32_t *num)
|
|
|
+{
|
|
|
+ return pld_get_wlan_derived_mac_address(dev, num);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* hdd_populate_random_mac_addr() - API to populate random mac addresses
|
|
|
* @hdd_ctx: HDD Context
|
|
@@ -10191,24 +10334,29 @@ static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
|
|
|
*/
|
|
|
void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num)
|
|
|
{
|
|
|
- uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
|
|
|
+ uint32_t idx = hdd_ctx->num_derived_addr;
|
|
|
uint32_t iter;
|
|
|
- struct hdd_config *ini = hdd_ctx->config;
|
|
|
uint8_t *buf = NULL;
|
|
|
uint8_t macaddr_b3, tmp_br3;
|
|
|
- uint8_t *src = ini->intfMacAddr[0].bytes;
|
|
|
+ /*
|
|
|
+ * Consider first provisioned mac address as source address to derive
|
|
|
+ * remaining addresses
|
|
|
+ */
|
|
|
|
|
|
- for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
|
|
|
- buf = ini->intfMacAddr[iter].bytes;
|
|
|
+ uint8_t *src = hdd_ctx->provisioned_mac_addr[0].bytes;
|
|
|
+
|
|
|
+ for (iter = 0; iter < num; ++iter, ++idx) {
|
|
|
+ buf = hdd_ctx->derived_mac_addr[idx].bytes;
|
|
|
qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
|
|
|
macaddr_b3 = buf[3];
|
|
|
- tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
|
|
|
+ tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + idx) &
|
|
|
INTF_MACADDR_MASK;
|
|
|
macaddr_b3 += tmp_br3;
|
|
|
macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
|
|
|
buf[0] |= 0x02;
|
|
|
buf[3] = macaddr_b3;
|
|
|
hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
|
|
|
+ hdd_ctx->num_derived_addr++;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -10227,14 +10375,17 @@ static int hdd_platform_wlan_mac(struct hdd_context *hdd_ctx)
|
|
|
uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
|
|
|
uint8_t *addr, *buf;
|
|
|
struct device *dev = hdd_ctx->parent_dev;
|
|
|
- struct hdd_config *ini = hdd_ctx->config;
|
|
|
tSirMacAddr mac_addr;
|
|
|
QDF_STATUS status;
|
|
|
|
|
|
addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
|
|
|
|
|
|
- if (no_of_mac_addr == 0 || !addr)
|
|
|
+ if (no_of_mac_addr == 0 || !addr) {
|
|
|
+ hdd_debug("No mac configured from platform driver");
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdd_free_mac_address_lists(hdd_ctx);
|
|
|
|
|
|
if (no_of_mac_addr > max_mac_addr)
|
|
|
no_of_mac_addr = max_mac_addr;
|
|
@@ -10242,19 +10393,46 @@ static int hdd_platform_wlan_mac(struct hdd_context *hdd_ctx)
|
|
|
qdf_mem_copy(&mac_addr, addr, mac_addr_size);
|
|
|
|
|
|
for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
|
|
|
- buf = ini->intfMacAddr[iter].bytes;
|
|
|
+ buf = hdd_ctx->provisioned_mac_addr[iter].bytes;
|
|
|
qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
|
|
|
- hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
|
|
|
+ hdd_info("provisioned MAC Addr [%d]" MAC_ADDRESS_STR, iter,
|
|
|
+ MAC_ADDR_ARRAY(buf));
|
|
|
}
|
|
|
|
|
|
- status = sme_set_custom_mac_addr(mac_addr);
|
|
|
|
|
|
- if (!QDF_IS_STATUS_SUCCESS(status))
|
|
|
- return -EAGAIN;
|
|
|
+ hdd_ctx->num_provisioned_addr = no_of_mac_addr;
|
|
|
+
|
|
|
+ if (hdd_ctx->config->mac_provision) {
|
|
|
+ addr = hdd_get_platform_wlan_derived_mac_buff(dev,
|
|
|
+ &no_of_mac_addr);
|
|
|
|
|
|
+ if (no_of_mac_addr == 0 || !addr)
|
|
|
+ hdd_warn("No derived address from platform driver");
|
|
|
+ else if (no_of_mac_addr >
|
|
|
+ (max_mac_addr - hdd_ctx->num_provisioned_addr))
|
|
|
+ no_of_mac_addr = (max_mac_addr -
|
|
|
+ hdd_ctx->num_provisioned_addr);
|
|
|
+
|
|
|
+ for (iter = 0; iter < no_of_mac_addr; ++iter,
|
|
|
+ addr += mac_addr_size) {
|
|
|
+ buf = hdd_ctx->derived_mac_addr[iter].bytes;
|
|
|
+ qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_debug("derived MAC Addr [%d]" MAC_ADDRESS_STR, iter,
|
|
|
+ MAC_ADDR_ARRAY(buf));
|
|
|
+ }
|
|
|
+ hdd_ctx->num_derived_addr = no_of_mac_addr;
|
|
|
+ }
|
|
|
+
|
|
|
+ no_of_mac_addr = hdd_ctx->num_provisioned_addr +
|
|
|
+ hdd_ctx->num_derived_addr;
|
|
|
if (no_of_mac_addr < max_mac_addr)
|
|
|
hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
|
|
|
no_of_mac_addr);
|
|
|
+
|
|
|
+ status = sme_set_custom_mac_addr(mac_addr);
|
|
|
+ if (!QDF_IS_STATUS_SUCCESS(status))
|
|
|
+ return -EAGAIN;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -10273,9 +10451,14 @@ static int hdd_update_mac_addr_to_fw(struct hdd_context *hdd_ctx)
|
|
|
tSirMacAddr customMacAddr;
|
|
|
QDF_STATUS status;
|
|
|
|
|
|
- qdf_mem_copy(&customMacAddr,
|
|
|
- &hdd_ctx->config->intfMacAddr[0].bytes[0],
|
|
|
- sizeof(tSirMacAddr));
|
|
|
+ if (hdd_ctx->num_provisioned_addr)
|
|
|
+ qdf_mem_copy(&customMacAddr,
|
|
|
+ &hdd_ctx->provisioned_mac_addr[0].bytes[0],
|
|
|
+ sizeof(tSirMacAddr));
|
|
|
+ else
|
|
|
+ qdf_mem_copy(&customMacAddr,
|
|
|
+ &hdd_ctx->derived_mac_addr[0].bytes[0],
|
|
|
+ sizeof(tSirMacAddr));
|
|
|
status = sme_set_custom_mac_addr(customMacAddr);
|
|
|
if (!QDF_IS_STATUS_SUCCESS(status))
|
|
|
return -EAGAIN;
|
|
@@ -10292,30 +10475,50 @@ static int hdd_update_mac_addr_to_fw(struct hdd_context *hdd_ctx)
|
|
|
*
|
|
|
* Return: None
|
|
|
*/
|
|
|
-static void hdd_initialize_mac_address(struct hdd_context *hdd_ctx)
|
|
|
+static int hdd_initialize_mac_address(struct hdd_context *hdd_ctx)
|
|
|
{
|
|
|
QDF_STATUS status;
|
|
|
int ret;
|
|
|
+ bool update_mac_addr_to_fw = true;
|
|
|
|
|
|
ret = hdd_platform_wlan_mac(hdd_ctx);
|
|
|
- if (!ret) {
|
|
|
+ if (hdd_ctx->config->mac_provision || !ret) {
|
|
|
hdd_info("using MAC address from platform driver");
|
|
|
- return;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
status = hdd_update_mac_config(hdd_ctx);
|
|
|
if (QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
hdd_info("using MAC address from wlan_mac.bin");
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
hdd_info("using default MAC address");
|
|
|
|
|
|
- if (hdd_ctx->update_mac_addr_to_fw) {
|
|
|
+ /* Use fw provided MAC */
|
|
|
+ if (!qdf_is_macaddr_zero(&hdd_ctx->hw_macaddr)) {
|
|
|
+ hdd_update_macaddr(hdd_ctx, hdd_ctx->hw_macaddr, false);
|
|
|
+ update_mac_addr_to_fw = false;
|
|
|
+ return 0;
|
|
|
+ } else if (hdd_generate_macaddr_auto(hdd_ctx) != 0) {
|
|
|
+ struct qdf_mac_addr mac_addr;
|
|
|
+
|
|
|
+ hdd_err("MAC failure from device serial no.");
|
|
|
+ cds_rand_get_bytes(0, (uint8_t *)(&mac_addr), sizeof(mac_addr));
|
|
|
+ /*
|
|
|
+ * Reset multicast bit (bit-0) and set
|
|
|
+ * locally-administered bit
|
|
|
+ */
|
|
|
+ mac_addr.bytes[0] = 0x2;
|
|
|
+ hdd_update_macaddr(hdd_ctx, mac_addr, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (update_mac_addr_to_fw) {
|
|
|
ret = hdd_update_mac_addr_to_fw(hdd_ctx);
|
|
|
if (ret)
|
|
|
hdd_err("MAC address out-of-sync, ret:%d", ret);
|
|
|
}
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int hdd_set_smart_chainmask_enabled(struct hdd_context *hdd_ctx)
|
|
@@ -10477,19 +10680,6 @@ static int hdd_pre_enable_configure(struct hdd_context *hdd_ctx)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Set the MAC Address Currently this is used by HAL to add self sta.
|
|
|
- * Remove this once self sta is added as part of session open.
|
|
|
- */
|
|
|
- status = sme_cfg_set_str(hdd_ctx->mac_handle, WNI_CFG_STA_ID,
|
|
|
- hdd_ctx->config->intfMacAddr[0].bytes,
|
|
|
- sizeof(hdd_ctx->config->intfMacAddr[0]));
|
|
|
-
|
|
|
- if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
- hdd_err("Failed to set MAC Address, status %d", status);
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
|
|
|
hdd_init_channel_avoidance(hdd_ctx);
|
|
|
|
|
@@ -11590,7 +11780,8 @@ hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx)
|
|
|
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),
|
|
|
+ wlan_hdd_get_intf_addr(hdd_ctx,
|
|
|
+ QDF_STA_MODE),
|
|
|
NET_NAME_UNKNOWN, true);
|
|
|
if (!adapter)
|
|
|
return QDF_STATUS_E_INVAL;
|
|
@@ -11622,7 +11813,8 @@ static QDF_STATUS hdd_open_adapters_for_ftm_mode(struct hdd_context *hdd_ctx)
|
|
|
struct hdd_adapter *adapter;
|
|
|
|
|
|
adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
|
|
|
- wlan_hdd_get_intf_addr(hdd_ctx),
|
|
|
+ wlan_hdd_get_intf_addr(hdd_ctx,
|
|
|
+ QDF_FTM_MODE),
|
|
|
NET_NAME_UNKNOWN, true);
|
|
|
|
|
|
return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
|
|
@@ -11634,7 +11826,8 @@ hdd_open_adapters_for_monitor_mode(struct hdd_context *hdd_ctx)
|
|
|
struct hdd_adapter *adapter;
|
|
|
|
|
|
adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
|
|
|
- wlan_hdd_get_intf_addr(hdd_ctx),
|
|
|
+ wlan_hdd_get_intf_addr(hdd_ctx,
|
|
|
+ QDF_MONITOR_MODE),
|
|
|
NET_NAME_UNKNOWN, true);
|
|
|
|
|
|
return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
|
|
@@ -11742,7 +11935,11 @@ int hdd_wlan_startup(struct hdd_context *hdd_ctx)
|
|
|
|
|
|
hdd_dp_trace_init(hdd_ctx->config);
|
|
|
|
|
|
- hdd_initialize_mac_address(hdd_ctx);
|
|
|
+ errno = hdd_initialize_mac_address(hdd_ctx);
|
|
|
+ if (errno) {
|
|
|
+ hdd_err("MAC initializtion failed: %d", errno);
|
|
|
+ goto unregister_wiphy;
|
|
|
+ }
|
|
|
|
|
|
errno = register_netdevice_notifier(&hdd_netdev_notifier);
|
|
|
if (errno) {
|