qcacld-3.0: iface connection/disconnection mgmt in IPA

Debug change to crash if there is a mismatch in number of
connections and disconnections

Change-Id: I1bb9cac331c0cb491a0ba761a78969537185e414
CRs-Fixed: 2870628
This commit is contained in:
Vevek Venkatesan 2021-01-18 16:33:38 +05:30 • committed by snandini
commit 6d5575e828
2 changed files with 86 additions and 34 deletions

View file

@ -334,6 +334,9 @@ struct wlan_ipa_iface_context {
uint8_t iface_id; /* This iface ID */
qdf_netdev_t dev;
enum QDF_OPMODE device_mode;
uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
qdf_atomic_t conn_count;
qdf_atomic_t disconn_count;
uint8_t session_id;
qdf_spinlock_t interface_lock;
uint32_t ifa_address;

View file

@ -1453,26 +1453,48 @@ static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
*
* Return: None
*/
static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context,
uint8_t *mac_addr)
{
struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
ipa_debug("enter");
ipa_err("net:%pK mode:%d MAC:"QDF_MAC_ADDR_FMT" id:%d",
iface_context->dev, iface_context->device_mode,
QDF_MAC_ADDR_REF(mac_addr), iface_context->session_id);
if (iface_context->session_id == WLAN_IPA_MAX_SESSION)
return;
cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
iface_context->dev->name,
wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
if (mac_addr && qdf_mem_cmp(iface_context->mac_addr,
mac_addr, QDF_MAC_ADDR_SIZE)) {
ipa_err("MAC mismatch "QDF_MAC_ADDR_FMT":"QDF_MAC_ADDR_FMT"",
QDF_MAC_ADDR_REF(mac_addr),
QDF_MAC_ADDR_REF(iface_context->mac_addr));
}
if (cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
iface_context->dev->name,
wlan_ipa_is_ipv6_enabled(ipa_ctx->config))) {
ipa_err("ipa_cleanup_iface failed");
}
if (iface_context->device_mode == QDF_SAP_MODE)
ipa_ctx->num_sap_connected--;
qdf_spin_lock_bh(&iface_context->interface_lock);
if (qdf_atomic_read(&iface_context->disconn_count) ==
qdf_atomic_read(&iface_context->conn_count) - 1) {
qdf_atomic_inc(&iface_context->disconn_count);
} else {
ipa_err("connect/disconnect out of sync");
QDF_BUG(0);
}
iface_context->dev = NULL;
iface_context->device_mode = QDF_MAX_NO_OF_MODE;
iface_context->session_id = WLAN_IPA_MAX_SESSION;
qdf_mem_set(iface_context->mac_addr, QDF_MAC_ADDR_SIZE, 0);
qdf_spin_unlock_bh(&iface_context->interface_lock);
iface_context->ifa_address = 0;
if (!iface_context->ipa_ctx->num_iface) {
@ -1552,42 +1574,55 @@ static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
* @device_mode: Net interface device mode
* @adapter: Interface upon which IPA is being setup
* @session_id: Station ID of the API instance
* @mac_addr: MAC addr of the API instance
*
* Return: QDF STATUS
*/
static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
qdf_netdev_t net_dev,
uint8_t device_mode,
uint8_t session_id)
uint8_t session_id,
uint8_t *mac_addr)
{
struct wlan_ipa_iface_context *iface_context = NULL;
int i;
QDF_STATUS status;
/* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
* channel change indication. Since these indications are sent by lower
* layer as SAP updates and IPA doesn't have to do anything for these
* updates so ignoring!
*/
if (device_mode == QDF_SAP_MODE) {
for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
iface_context = &(ipa_ctx->iface_context[i]);
if (iface_context->dev == net_dev) {
if (iface_context->device_mode ==
device_mode) {
ipa_err("net:%pK mode:%d MAC:"QDF_MAC_ADDR_FMT" id:%d",
net_dev, device_mode, QDF_MAC_ADDR_REF(mac_addr), session_id);
for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
iface_context = &(ipa_ctx->iface_context[i]);
if (iface_context->dev == net_dev) {
if (iface_context->device_mode == device_mode) {
/**
* Lower layer may send multiple START_BSS_EVENT
* in DFS mode or during channel change.
* Since these indications are sent by lower
* layer as SAP updates and IPA doesn't have to
* do anything for these updates so ignoring!
*/
if (device_mode == QDF_SAP_MODE) {
ipa_debug("found iface %u device_mode %u",
i, device_mode);
return QDF_STATUS_SUCCESS;
} else if (device_mode == QDF_STA_MODE &&
qdf_mem_cmp(
iface_context->mac_addr,
mac_addr,
QDF_MAC_ADDR_SIZE) == 0) {
ipa_err("same STA iface already connected");
}
ipa_err("Obsolete iface %u found, device_mode %u, will remove it.",
i, iface_context->device_mode);
wlan_ipa_cleanup_iface(iface_context);
} else if (iface_context->session_id == session_id) {
ipa_err("Obsolete iface %u found, net_dev %pK, will remove it.",
i, iface_context->dev);
wlan_ipa_cleanup_iface(iface_context);
}
ipa_err("Obsolete iface %u found, device_mode %u, will remove it.",
i, iface_context->device_mode);
wlan_ipa_cleanup_iface(iface_context, NULL);
} else if (iface_context->session_id == session_id) {
ipa_err("Obsolete iface %u found, net_dev %pK, will remove it.",
i, iface_context->dev);
wlan_ipa_cleanup_iface(iface_context, NULL);
}
}
@ -1613,9 +1648,20 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
goto end;
}
qdf_spin_lock_bh(&iface_context->interface_lock);
if (qdf_atomic_read(&iface_context->conn_count) ==
qdf_atomic_read(&iface_context->disconn_count)) {
qdf_atomic_inc(&iface_context->conn_count);
} else {
ipa_err("connect/disconnect out of sync");
QDF_BUG(0);
}
iface_context->dev = net_dev;
iface_context->device_mode = device_mode;
iface_context->session_id = session_id;
qdf_mem_copy(iface_context->mac_addr, mac_addr, QDF_MAC_ADDR_SIZE);
qdf_spin_unlock_bh(&iface_context->interface_lock);
status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
net_dev->dev_addr,
@ -1640,7 +1686,7 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
end:
if (iface_context)
wlan_ipa_cleanup_iface(iface_context);
wlan_ipa_cleanup_iface(iface_context, mac_addr);
return status;
}
@ -2182,7 +2228,8 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
iface_ctx = &ipa_ctx->iface_context[i];
if (iface_ctx->dev == net_dev) {
wlan_ipa_cleanup_iface(
iface_ctx);
iface_ctx,
mac_addr);
break;
}
}
@ -2218,7 +2265,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
ipa_ctx, net_dev, QDF_STA_MODE);
if (iface_ctx) {
ipa_ctx->sta_connected--;
wlan_ipa_cleanup_iface(iface_ctx);
wlan_ipa_cleanup_iface(iface_ctx, NULL);
}
status = wlan_ipa_send_msg(net_dev,
QDF_IPA_STA_DISCONNECT,
@ -2232,7 +2279,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
}
status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
session_id);
session_id, mac_addr);
if (status != QDF_STATUS_SUCCESS) {
ipa_err("wlan_ipa_setup_iface failed %u", status);
qdf_mutex_release(&ipa_ctx->event_lock);
@ -2303,7 +2350,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
}
status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
session_id);
session_id, mac_addr);
if (status != QDF_STATUS_SUCCESS) {
qdf_mutex_release(&ipa_ctx->event_lock);
ipa_err("%s: Evt: %d, Interface setup failed",
@ -2347,7 +2394,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
net_dev,
QDF_STA_MODE);
if (iface)
wlan_ipa_cleanup_iface(iface);
wlan_ipa_cleanup_iface(iface, mac_addr);
return QDF_STATUS_E_INVAL;
}
@ -2404,7 +2451,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
net_dev,
QDF_STA_MODE);
if (iface_ctx)
wlan_ipa_cleanup_iface(iface_ctx);
wlan_ipa_cleanup_iface(iface_ctx, mac_addr);
if (qdf_ipa_get_lan_rx_napi() && ipa_ctx->sap_num_connected_sta)
ipa_set_rps_per_vdev(ipa_ctx, session_id, false);
@ -2455,7 +2502,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
iface_ctx = &ipa_ctx->iface_context[i];
if (iface_ctx->dev == net_dev) {
wlan_ipa_cleanup_iface(iface_ctx);
wlan_ipa_cleanup_iface(iface_ctx, mac_addr);
break;
}
}
@ -3213,6 +3260,8 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
iface_context->dev = NULL;
iface_context->device_mode = QDF_MAX_NO_OF_MODE;
iface_context->session_id = WLAN_IPA_MAX_SESSION;
qdf_atomic_init(&iface_context->conn_count);
qdf_atomic_init(&iface_context->disconn_count);
qdf_spinlock_create(&iface_context->interface_lock);
}
@ -3870,7 +3919,7 @@ void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx,
iface_ctx->dev && iface_ctx->dev == net_dev) {
wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
net_dev->dev_addr);
wlan_ipa_cleanup_iface(iface_ctx);
wlan_ipa_cleanup_iface(iface_ctx, NULL);
}
}
@ -3906,7 +3955,7 @@ void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
iface_ctx = &ipa_ctx->iface_context[i];
if (iface_ctx->dev == net_dev) {
wlan_ipa_cleanup_iface(iface_ctx);
wlan_ipa_cleanup_iface(iface_ctx, NULL);
break;
}
}
@ -3930,7 +3979,7 @@ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
wlan_ipa_uc_send_evt(iface->dev,
QDF_IPA_STA_DISCONNECT,
iface->dev->dev_addr);
wlan_ipa_cleanup_iface(iface);
wlan_ipa_cleanup_iface(iface, NULL);
}
}
}