|
@@ -275,6 +275,115 @@ static void wlan_ipa_send_pkt_to_tl(
|
|
|
iface_context->stats.num_tx++;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * wlan_ipa_forward() - handle packet forwarding to wlan tx
|
|
|
+ * @ipa_ctx: pointer to ipa ipa context
|
|
|
+ * @iface_ctx: interface context
|
|
|
+ * @skb: data pointer
|
|
|
+ *
|
|
|
+ * if exception packet has set forward bit, copied new packet should be
|
|
|
+ * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
|
|
|
+ * put into pm queue and tx procedure will be differed
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
|
|
|
+ struct wlan_ipa_iface_context *iface_ctx,
|
|
|
+ qdf_nbuf_t skb)
|
|
|
+{
|
|
|
+ struct wlan_ipa_pm_tx_cb *pm_tx_cb;
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
|
|
+
|
|
|
+ /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
|
|
|
+ qdf_nbuf_ipa_owned_set(skb);
|
|
|
+
|
|
|
+ /* WLAN subsystem is in suspend, put in queue */
|
|
|
+ if (ipa_ctx->suspended) {
|
|
|
+ qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
|
|
+ ipa_info_rl("Tx in suspend, put in queue");
|
|
|
+ qdf_mem_zero(skb->cb, sizeof(skb->cb));
|
|
|
+ pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
|
|
|
+ pm_tx_cb->exception = true;
|
|
|
+ pm_tx_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 {
|
|
|
+ /* Resume, put packet into WLAN TX */
|
|
|
+ qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
|
|
+
|
|
|
+ if (ipa_ctx->softap_xmit) {
|
|
|
+ if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
|
|
|
+ ipa_err_rl("packet Tx fail");
|
|
|
+ ipa_ctx->stats.num_tx_fwd_err++;
|
|
|
+ } else {
|
|
|
+ ipa_ctx->stats.num_tx_fwd_ok++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wlan_ipa_intrabss_forward() - Forward intra bss packets.
|
|
|
+ * @ipa_ctx: pointer to IPA IPA struct
|
|
|
+ * @iface_ctx: ipa interface context
|
|
|
+ * @desc: Firmware descriptor
|
|
|
+ * @skb: Data buffer
|
|
|
+ *
|
|
|
+ * Return:
|
|
|
+ * WLAN_IPA_FORWARD_PKT_NONE
|
|
|
+ * WLAN_IPA_FORWARD_PKT_DISCARD
|
|
|
+ * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
|
|
|
+ struct wlan_ipa_priv *ipa_ctx,
|
|
|
+ struct wlan_ipa_iface_context *iface_ctx,
|
|
|
+ uint8_t desc,
|
|
|
+ qdf_nbuf_t skb)
|
|
|
+{
|
|
|
+ int ret = WLAN_IPA_FORWARD_PKT_NONE;
|
|
|
+ void *soc = cds_get_context(QDF_MODULE_ID_SOC);
|
|
|
+ void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
|
|
+
|
|
|
+ if ((desc & FW_RX_DESC_FORWARD_M)) {
|
|
|
+ void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
|
|
|
+ iface_ctx->session_id);
|
|
|
+ if (cdp_tx_desc_thresh_reached(soc, vdev)) {
|
|
|
+ /* Drop the packet*/
|
|
|
+ ipa_ctx->stats.num_tx_fwd_err++;
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ ret = WLAN_IPA_FORWARD_PKT_DISCARD;
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
|
|
|
+ ipa_ctx->ipa_tx_forward++;
|
|
|
+
|
|
|
+ if ((desc & FW_RX_DESC_DISCARD_M)) {
|
|
|
+ wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
|
|
|
+ ipa_ctx->ipa_rx_internal_drop_count++;
|
|
|
+ ipa_ctx->ipa_rx_discard++;
|
|
|
+ ret = WLAN_IPA_FORWARD_PKT_DISCARD;
|
|
|
+ } else {
|
|
|
+ struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
|
|
|
+
|
|
|
+ if (cloned_skb)
|
|
|
+ wlan_ipa_forward(ipa_ctx, iface_ctx,
|
|
|
+ cloned_skb);
|
|
|
+ else
|
|
|
+ ipa_err_rl("tx skb alloc failed");
|
|
|
+ ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_IPA_WDI_UNIFIED_API
|
|
|
/*
|
|
|
* TODO: Get WDI version through FW capabilities
|
|
@@ -474,6 +583,40 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
|
|
|
return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
|
|
|
}
|
|
|
|
|
|
+static enum wlan_ipa_forward_type
|
|
|
+wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
|
|
|
+ struct wlan_ipa_iface_context *iface_ctx,
|
|
|
+ qdf_nbuf_t nbuf)
|
|
|
+{
|
|
|
+ uint8_t fw_desc = 0;
|
|
|
+ bool fwd_success;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
|
|
|
+ if (ipa_ctx->wdi_version != IPA_WDI_3) {
|
|
|
+ fw_desc = (uint8_t)nbuf->cb[1];
|
|
|
+ return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
|
|
|
+ nbuf);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
|
|
|
+ nbuf, &fwd_success)) {
|
|
|
+ ipa_ctx->ipa_rx_internal_drop_count++;
|
|
|
+ ipa_ctx->ipa_rx_discard++;
|
|
|
+
|
|
|
+ ret = WLAN_IPA_FORWARD_PKT_DISCARD;
|
|
|
+ } else {
|
|
|
+ ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fwd_success)
|
|
|
+ ipa_ctx->stats.num_tx_fwd_ok++;
|
|
|
+ else
|
|
|
+ ipa_ctx->stats.num_tx_fwd_err++;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
#else /* CONFIG_IPA_WDI_UNIFIED_API */
|
|
|
|
|
|
static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
|
|
@@ -608,6 +751,18 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
|
|
|
return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
|
|
|
}
|
|
|
|
|
|
+static enum wlan_ipa_forward_type
|
|
|
+wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
|
|
|
+ struct wlan_ipa_iface_context *iface_ctx,
|
|
|
+ qdf_nbuf_t nbuf)
|
|
|
+{
|
|
|
+ uint8_t fw_desc;
|
|
|
+
|
|
|
+ fw_desc = (uint8_t)nbuf->cb[1];
|
|
|
+
|
|
|
+ return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
|
|
|
+}
|
|
|
+
|
|
|
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
|
|
|
|
|
/**
|
|
@@ -641,115 +796,6 @@ wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
|
|
|
ipa_ctx->ipa_rx_net_send_count++;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * wlan_ipa_forward() - handle packet forwarding to wlan tx
|
|
|
- * @ipa_ctx: pointer to ipa ipa context
|
|
|
- * @iface_ctx: interface context
|
|
|
- * @skb: data pointer
|
|
|
- *
|
|
|
- * if exception packet has set forward bit, copied new packet should be
|
|
|
- * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
|
|
|
- * put into pm queue and tx procedure will be differed
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- */
|
|
|
-static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
|
|
|
- struct wlan_ipa_iface_context *iface_ctx,
|
|
|
- qdf_nbuf_t skb)
|
|
|
-{
|
|
|
- struct wlan_ipa_pm_tx_cb *pm_tx_cb;
|
|
|
-
|
|
|
- qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
|
|
-
|
|
|
- /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
|
|
|
- qdf_nbuf_ipa_owned_set(skb);
|
|
|
-
|
|
|
- /* WLAN subsystem is in suspend, put in queue */
|
|
|
- if (ipa_ctx->suspended) {
|
|
|
- qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
|
|
- ipa_info_rl("Tx in suspend, put in queue");
|
|
|
- qdf_mem_zero(skb->cb, sizeof(skb->cb));
|
|
|
- pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
|
|
|
- pm_tx_cb->exception = true;
|
|
|
- pm_tx_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 {
|
|
|
- /* Resume, put packet into WLAN TX */
|
|
|
- qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
|
|
-
|
|
|
- if (ipa_ctx->softap_xmit) {
|
|
|
- if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
|
|
|
- ipa_err_rl("packet Tx fail");
|
|
|
- ipa_ctx->stats.num_tx_fwd_err++;
|
|
|
- } else {
|
|
|
- ipa_ctx->stats.num_tx_fwd_ok++;
|
|
|
- }
|
|
|
- } else {
|
|
|
- dev_kfree_skb_any(skb);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wlan_ipa_intrabss_forward() - Forward intra bss packets.
|
|
|
- * @ipa_ctx: pointer to IPA IPA struct
|
|
|
- * @iface_ctx: ipa interface context
|
|
|
- * @desc: Firmware descriptor
|
|
|
- * @skb: Data buffer
|
|
|
- *
|
|
|
- * Return:
|
|
|
- * WLAN_IPA_FORWARD_PKT_NONE
|
|
|
- * WLAN_IPA_FORWARD_PKT_DISCARD
|
|
|
- * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
|
|
|
- struct wlan_ipa_priv *ipa_ctx,
|
|
|
- struct wlan_ipa_iface_context *iface_ctx,
|
|
|
- uint8_t desc,
|
|
|
- qdf_nbuf_t skb)
|
|
|
-{
|
|
|
- int ret = WLAN_IPA_FORWARD_PKT_NONE;
|
|
|
- void *soc = cds_get_context(QDF_MODULE_ID_SOC);
|
|
|
- void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
|
|
-
|
|
|
- if ((desc & FW_RX_DESC_FORWARD_M)) {
|
|
|
- void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
|
|
|
- iface_ctx->session_id);
|
|
|
- if (cdp_tx_desc_thresh_reached(soc, vdev)) {
|
|
|
- /* Drop the packet*/
|
|
|
- ipa_ctx->stats.num_tx_fwd_err++;
|
|
|
- dev_kfree_skb_any(skb);
|
|
|
- ret = WLAN_IPA_FORWARD_PKT_DISCARD;
|
|
|
- return ret;
|
|
|
- }
|
|
|
- ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
|
|
|
- ipa_ctx->ipa_tx_forward++;
|
|
|
-
|
|
|
- if ((desc & FW_RX_DESC_DISCARD_M)) {
|
|
|
- wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
|
|
|
- ipa_ctx->ipa_rx_internal_drop_count++;
|
|
|
- ipa_ctx->ipa_rx_discard++;
|
|
|
- ret = WLAN_IPA_FORWARD_PKT_DISCARD;
|
|
|
- } else {
|
|
|
- struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
|
|
|
-
|
|
|
- if (cloned_skb)
|
|
|
- wlan_ipa_forward(ipa_ctx, iface_ctx,
|
|
|
- cloned_skb);
|
|
|
- else
|
|
|
- ipa_err_rl("tx skb alloc failed");
|
|
|
- ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
|
|
|
* @priv: pointer to private data registered with IPA (we register a
|
|
@@ -767,7 +813,6 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
|
|
|
uint8_t iface_id;
|
|
|
uint8_t session_id = 0xff;
|
|
|
struct wlan_ipa_iface_context *iface_context;
|
|
|
- uint8_t fw_desc;
|
|
|
|
|
|
ipa_ctx = (struct wlan_ipa_priv *)priv;
|
|
|
if (!ipa_ctx) {
|
|
@@ -827,10 +872,9 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
|
|
|
* set, and forward to Tx. Then copy to kernel stack
|
|
|
* only when DISCARD bit is not set.
|
|
|
*/
|
|
|
- fw_desc = (uint8_t)skb->cb[1];
|
|
|
if (WLAN_IPA_FORWARD_PKT_DISCARD ==
|
|
|
- wlan_ipa_intrabss_forward(ipa_ctx, iface_context,
|
|
|
- fw_desc, skb))
|
|
|
+ wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
|
|
|
+ skb))
|
|
|
break;
|
|
|
} else {
|
|
|
ipa_debug_rl("Intra-BSS forwarding is disabled");
|