qcacmn: Add WLAN IPA RX exception packet to pm queue
Below signature is seen in driver logs. Target is suspended (via send_process_dhcp_ind_cmd_tlv:244) cds_trigger_recovery_handler: critical host timeout trigger fw recovery for reason code 34 Suspend/Resume test is run with SAP started and a ref-client is associated with the SAP. One DHCP-Req packet is received from ref-client before driver completes the resume process. With SAP_DHCP_FW_IND feature enabled, driver will send one WMI cmd to target for such DHCP packets received. With IPA_OFFLOAD enabled, such DHCP packets are received from the RX exception callback from IPA driver. Hence add support to queue these DHCP packets onto pm_queue_head skb queue when WLAN IPA component is still in suspended state. When IPA component is resumed from suspend state, pm_queue_head skb queue will be drained to pass up queued RX exception packets to stack. For QCA_IPA_LL_TX_FLOW_CONTROL enabled platforms, such as WIN chipsets, suspend/resume is not supported. Hence wrap fixes only for !QCA_IPA_LL_TX_FLOW_CONTROL. Change-Id: I823005d9b58d1d62eec2c044621e1c1423aa3537 CRs-Fixed: 3457254
This commit is contained in:
@@ -303,11 +303,13 @@ struct wlan_ipa_rx_hdr {
|
||||
* @exception: Exception packet
|
||||
* @iface_context: Interface context
|
||||
* @ipa_tx_desc: IPA TX descriptor
|
||||
* @send_to_nw: RX exception packet that needs to be passed up to stack
|
||||
*/
|
||||
struct wlan_ipa_pm_tx_cb {
|
||||
bool exception;
|
||||
struct wlan_ipa_iface_context *iface_context;
|
||||
qdf_ipa_rx_data_t *ipa_tx_desc;
|
||||
bool send_to_nw;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -818,6 +818,7 @@ static void wlan_ipa_pm_flush(void *data)
|
||||
struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
|
||||
qdf_nbuf_t skb;
|
||||
uint32_t dequeued = 0;
|
||||
qdf_netdev_t ndev;
|
||||
|
||||
qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
||||
while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
|
||||
@@ -836,6 +837,15 @@ static void wlan_ipa_pm_flush(void *data)
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
} else if (pm_tx_cb->send_to_nw) {
|
||||
ndev = pm_tx_cb->iface_context->dev;
|
||||
|
||||
if (ipa_ctx->send_to_nw && ndev) {
|
||||
ipa_ctx->send_to_nw(skb, ndev);
|
||||
ipa_ctx->ipa_rx_net_send_count++;
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
} else {
|
||||
wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
|
||||
pm_tx_cb->ipa_tx_desc);
|
||||
@@ -1184,6 +1194,109 @@ static int wlan_ipa_send_sta_eapol_to_nw(qdf_nbuf_t skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef QCA_IPA_LL_TX_FLOW_CONTROL
|
||||
|
||||
#ifdef SAP_DHCP_FW_IND
|
||||
/**
|
||||
* wlan_ipa_send_to_nw_sap_dhcp - Check if SAP mode and skb is a DHCP packet
|
||||
* @iface_ctx: IPA per-interface ctx
|
||||
* @skb: socket buffer
|
||||
*
|
||||
* Check if @iface_ctx is SAP and @skb is a DHCP packet.
|
||||
*
|
||||
* When SAP_DHCP_FW_IND feature is enabled, DHCP packets received will be
|
||||
* notified to target via WMI cmd. However if system is suspended, WMI
|
||||
* cmd is not allowed from Host to Target.
|
||||
*
|
||||
* Return: true if iface is SAP mode and skb is a DHCP packet. Otherwise false
|
||||
*/
|
||||
static bool
|
||||
wlan_ipa_send_to_nw_sap_dhcp(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
if (iface_ctx->device_mode == QDF_SAP_MODE &&
|
||||
qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#else /* !SAP_DHCP_FW_IND */
|
||||
static inline bool
|
||||
wlan_ipa_send_to_nw_sap_dhcp(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* SAP_DHCP_FW_IND */
|
||||
|
||||
/**
|
||||
* wlan_ipa_send_to_nw_defer - Check if skb needs to deferred to network stack
|
||||
* @iface_ctx: IPA per-interface ctx
|
||||
* @skb: socket buffer
|
||||
*
|
||||
* Check if @skb received on @iface_ctx needs to be deferred to be passed
|
||||
* up to network stack.
|
||||
*
|
||||
* Return: true if needs to be deferred, otherwise false
|
||||
*/
|
||||
static bool wlan_ipa_send_to_nw_defer(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
struct wlan_ipa_priv *ipa_ctx = iface_ctx->ipa_ctx;
|
||||
|
||||
qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
||||
if (!ipa_ctx->suspended) {
|
||||
qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
||||
return false;
|
||||
}
|
||||
qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
||||
|
||||
return wlan_ipa_send_to_nw_sap_dhcp(iface_ctx, skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_send_to_nw_queue - Add skb to pm_queue_head if deferred
|
||||
* @iface_ctx: IPA per-interface ctx
|
||||
* @skb: socket buffer
|
||||
*
|
||||
* Add @skb to pm_queue_head to defer passing up to network stack due to
|
||||
* system suspended.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_ipa_send_to_nw_queue(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
struct wlan_ipa_priv *ipa_ctx = iface_ctx->ipa_ctx;
|
||||
struct wlan_ipa_pm_tx_cb *pm_cb;
|
||||
|
||||
qdf_mem_zero(skb->cb, sizeof(skb->cb));
|
||||
pm_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
|
||||
|
||||
pm_cb->send_to_nw = true;
|
||||
pm_cb->iface_context = iface_ctx;
|
||||
|
||||
qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
||||
qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
|
||||
qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
||||
|
||||
ipa_ctx->stats.num_tx_queued++;
|
||||
}
|
||||
#else /* QCA_IPA_LL_TX_FLOW_CONTROL */
|
||||
static inline bool
|
||||
wlan_ipa_send_to_nw_defer(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wlan_ipa_send_to_nw_queue(struct wlan_ipa_iface_context *iface_ctx,
|
||||
qdf_nbuf_t skb)
|
||||
{
|
||||
}
|
||||
#endif /* QCA_IPA_LL_TX_FLOW_CONTROL */
|
||||
|
||||
/**
|
||||
* wlan_ipa_send_skb_to_network() - Send skb to kernel
|
||||
* @skb: network buffer
|
||||
@@ -1211,10 +1324,14 @@ wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
|
||||
|
||||
skb->destructor = wlan_ipa_uc_rt_debug_destructor;
|
||||
|
||||
if (ipa_ctx->send_to_nw)
|
||||
ipa_ctx->send_to_nw(skb, iface_ctx->dev);
|
||||
if (wlan_ipa_send_to_nw_defer(iface_ctx, skb)) {
|
||||
wlan_ipa_send_to_nw_queue(iface_ctx, skb);
|
||||
} else {
|
||||
if (ipa_ctx->send_to_nw)
|
||||
ipa_ctx->send_to_nw(skb, iface_ctx->dev);
|
||||
|
||||
ipa_ctx->ipa_rx_net_send_count++;
|
||||
ipa_ctx->ipa_rx_net_send_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4199,7 +4316,7 @@ void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
|
||||
|
||||
pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
|
||||
|
||||
if (pm_tx_cb->exception) {
|
||||
if (pm_tx_cb->exception || pm_tx_cb->send_to_nw) {
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
if (pm_tx_cb->ipa_tx_desc)
|
||||
|
Reference in New Issue
Block a user