qcacmn: Handle Umac reset for MLO case

1. Add an API to process trigger_umac_recovery T2H message.
2. Synchronize do_pre_reset, do_post_reset_start, do_post_reset_complete
   messages for all the SOCs and then process these messages in the host.
3. Synchronize pre_reset_done, post_reset_start_done,
   post_reset_complete_done for all the SOCs before sending it to FW.
4. Add a new state in host for trigger_umac_recovery message.
   Ignore back to back trigger_umac_recovery messages received from FW.

Change-Id: Id45d326d63e122834090844e83ad6cc7240f96af
CRs-Fixed: 3425833
This commit is contained in:
Pavankumar Nandeshwar
2023-02-20 01:54:25 -08:00
committed by Madan Koyyalamudi
parent ff85561570
commit 80d41dc9b4
12 changed files with 868 additions and 123 deletions

View File

@@ -465,6 +465,17 @@ static inline struct dp_soc_be *dp_get_be_soc_from_dp_soc(struct dp_soc *soc)
return (struct dp_soc_be *)soc; return (struct dp_soc_be *)soc;
} }
/**
* dp_mlo_iter_ptnr_soc() - iterate through mlo soc list and call the callback
* @be_soc: dp_soc_be pointer
* @func: Function to be called for each soc
* @arg: context to be passed to the callback
*
* Return: true if mlo is enabled, false if mlo is disabled
*/
bool dp_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc, dp_ptnr_soc_iter_func func,
void *arg);
#ifdef WLAN_MLO_MULTI_CHIP #ifdef WLAN_MLO_MULTI_CHIP
typedef struct dp_mlo_ctxt *dp_mld_peer_hash_obj_t; typedef struct dp_mlo_ctxt *dp_mld_peer_hash_obj_t;
@@ -509,8 +520,6 @@ void dp_mlo_partner_chips_unmap(struct dp_soc *soc,
typedef void dp_ptnr_vdev_iter_func(struct dp_vdev_be *be_vdev, typedef void dp_ptnr_vdev_iter_func(struct dp_vdev_be *be_vdev,
struct dp_vdev *ptnr_vdev, struct dp_vdev *ptnr_vdev,
void *arg); void *arg);
typedef void dp_ptnr_soc_iter_func(struct dp_soc *ptnr_soc,
void *arg);
/** /**
* dp_mcast_mlo_iter_ptnr_vdev() - API to iterate through ptnr vdev list * dp_mcast_mlo_iter_ptnr_vdev() - API to iterate through ptnr vdev list
@@ -527,17 +536,7 @@ void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
dp_ptnr_vdev_iter_func func, dp_ptnr_vdev_iter_func func,
void *arg, void *arg,
enum dp_mod_id mod_id); enum dp_mod_id mod_id);
/**
* dp_mlo_iter_ptnr_soc() - API to iterate through ptnr soc list
* @be_soc: dp_soc_be pointer
* @func: function to be called for each peer
* @arg: argument need to be passed to func
*
* Return: None
*/
void dp_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
dp_ptnr_soc_iter_func func,
void *arg);
/** /**
* dp_mlo_get_mcast_primary_vdev() - get ref to mcast primary vdev * dp_mlo_get_mcast_primary_vdev() - get ref to mcast primary vdev
* @be_soc: dp_soc_be pointer * @be_soc: dp_soc_be pointer

View File

@@ -24,7 +24,20 @@
#include <dp_internal.h> #include <dp_internal.h>
#include <wlan_cfg.h> #include <wlan_cfg.h>
#include <wlan_mlo_mgr_cmn.h> #include <wlan_mlo_mgr_cmn.h>
#include "dp_umac_reset.h"
#ifdef DP_UMAC_HW_RESET_SUPPORT
/**
* dp_umac_reset_update_partner_map() - Update Umac reset partner map
* @mlo_ctx: mlo soc context
* @chip_id: chip id
* @set: flag indicating whether to set or clear the bit
*
* Return: void
*/
static void dp_umac_reset_update_partner_map(struct dp_mlo_ctxt *mlo_ctx,
int chip_id, bool set);
#endif
/** /**
* dp_mlo_ctxt_attach_wifi3() - Attach DP MLO context * dp_mlo_ctxt_attach_wifi3() - Attach DP MLO context
* @ctrl_ctxt: CDP control context * @ctrl_ctxt: CDP control context
@@ -59,6 +72,7 @@ dp_mlo_ctxt_attach_wifi3(struct cdp_ctrl_mlo_mgr *ctrl_ctxt)
LRO_IPV6_SEED_ARR_SZ)); LRO_IPV6_SEED_ARR_SZ));
qdf_spinlock_create(&mlo_ctxt->ml_soc_list_lock); qdf_spinlock_create(&mlo_ctxt->ml_soc_list_lock);
qdf_spinlock_create(&mlo_ctxt->grp_umac_reset_ctx.grp_ctx_lock);
return dp_mlo_ctx_to_cdp(mlo_ctxt); return dp_mlo_ctx_to_cdp(mlo_ctxt);
} }
@@ -75,6 +89,7 @@ static void dp_mlo_ctxt_detach_wifi3(struct cdp_mlo_ctxt *cdp_ml_ctxt)
if (!cdp_ml_ctxt) if (!cdp_ml_ctxt)
return; return;
qdf_spinlock_destroy(&mlo_ctxt->grp_umac_reset_ctx.grp_ctx_lock);
qdf_spinlock_destroy(&mlo_ctxt->ml_soc_list_lock); qdf_spinlock_destroy(&mlo_ctxt->ml_soc_list_lock);
dp_mlo_peer_find_hash_detach_be(mlo_ctxt); dp_mlo_peer_find_hash_detach_be(mlo_ctxt);
qdf_mem_free(mlo_ctxt); qdf_mem_free(mlo_ctxt);
@@ -103,6 +118,8 @@ static void dp_mlo_set_soc_by_chip_id(struct dp_mlo_ctxt *ml_ctxt,
else else
ml_ctxt->ml_soc_cnt--; ml_ctxt->ml_soc_cnt--;
dp_umac_reset_update_partner_map(ml_ctxt, chip_id, !!soc);
qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock); qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock);
} }
@@ -164,7 +181,7 @@ static QDF_STATUS dp_partner_soc_rx_hw_cc_init(struct dp_mlo_ctxt *mlo_ctxt,
return qdf_status; return qdf_status;
} }
static void dp_mlo_soc_drain_rx_buf(struct dp_soc *soc, void *arg) static void dp_mlo_soc_drain_rx_buf(struct dp_soc *soc, void *arg, int chip_id)
{ {
uint8_t i = 0; uint8_t i = 0;
uint8_t cpu = 0; uint8_t cpu = 0;
@@ -814,25 +831,6 @@ dp_soc_get_by_idle_bm_id(struct dp_soc *soc, uint8_t idle_bm_id)
} }
#ifdef WLAN_MCAST_MLO #ifdef WLAN_MCAST_MLO
void dp_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
dp_ptnr_soc_iter_func func,
void *arg)
{
int i = 0;
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
struct dp_soc *ptnr_soc =
dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
if (!ptnr_soc)
continue;
(*func)(ptnr_soc, arg);
}
}
qdf_export_symbol(dp_mlo_iter_ptnr_soc);
void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc, void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev, struct dp_vdev_be *be_vdev,
dp_ptnr_vdev_iter_func func, dp_ptnr_vdev_iter_func func,
@@ -906,6 +904,37 @@ struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
qdf_export_symbol(dp_mlo_get_mcast_primary_vdev); qdf_export_symbol(dp_mlo_get_mcast_primary_vdev);
#endif #endif
/**
* dp_mlo_iter_ptnr_soc() - iterate through mlo soc list and call the callback
* @be_soc: dp_soc_be pointer
* @func: Function to be called for each soc
* @arg: context to be passed to the callback
*
* Return: true if mlo is enabled, false if mlo is disabled
*/
bool dp_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc, dp_ptnr_soc_iter_func func,
void *arg)
{
int i = 0;
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
if (!be_soc->mlo_enabled || !be_soc->ml_ctxt)
return false;
for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
struct dp_soc *ptnr_soc =
dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
if (!ptnr_soc)
continue;
(*func)(ptnr_soc, arg, i);
}
return true;
}
qdf_export_symbol(dp_mlo_iter_ptnr_soc);
static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev) static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev)
{ {
struct dp_soc *soc; struct dp_soc *soc;
@@ -959,3 +988,272 @@ int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc)
return delta_tqm_mlo_offset; return delta_tqm_mlo_offset;
} }
#ifdef DP_UMAC_HW_RESET_SUPPORT
/**
* dp_umac_reset_update_partner_map() - Update Umac reset partner map
* @mlo_ctx: DP ML context handle
* @chip_id: chip id
* @set: flag indicating whether to set or clear the bit
*
* Return: void
*/
static void dp_umac_reset_update_partner_map(struct dp_mlo_ctxt *mlo_ctx,
int chip_id, bool set)
{
struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx =
&mlo_ctx->grp_umac_reset_ctx;
if (set)
qdf_atomic_set_bit(chip_id, &grp_umac_reset_ctx->partner_map);
else
qdf_atomic_clear_bit(chip_id, &grp_umac_reset_ctx->partner_map);
}
/**
* dp_umac_reset_complete_umac_recovery() - Complete Umac reset session
* @soc: dp soc handle
*
* Return: void
*/
void dp_umac_reset_complete_umac_recovery(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx;
if (!mlo_ctx) {
dp_umac_reset_alert("Umac reset was handled on soc %pK", soc);
return;
}
grp_umac_reset_ctx = &mlo_ctx->grp_umac_reset_ctx;
qdf_spin_lock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
grp_umac_reset_ctx->umac_reset_in_progress = false;
grp_umac_reset_ctx->is_target_recovery = false;
grp_umac_reset_ctx->response_map = 0;
grp_umac_reset_ctx->request_map = 0;
grp_umac_reset_ctx->initiator_chip_id = 0;
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
dp_umac_reset_alert("Umac reset was handled on mlo group ctxt %pK",
mlo_ctx);
}
/**
* dp_umac_reset_initiate_umac_recovery() - Initiate Umac reset session
* @soc: dp soc handle
* @is_target_recovery: Flag to indicate if it is triggered for target recovery
*
* Return: void
*/
void dp_umac_reset_initiate_umac_recovery(struct dp_soc *soc,
bool is_target_recovery)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx;
if (!mlo_ctx)
return;
grp_umac_reset_ctx = &mlo_ctx->grp_umac_reset_ctx;
qdf_spin_lock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
if (grp_umac_reset_ctx->umac_reset_in_progress) {
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
return;
}
grp_umac_reset_ctx->umac_reset_in_progress = true;
grp_umac_reset_ctx->is_target_recovery = is_target_recovery;
/* We don't wait for the 'Umac trigger' message from all socs */
grp_umac_reset_ctx->request_map = grp_umac_reset_ctx->partner_map;
grp_umac_reset_ctx->response_map = grp_umac_reset_ctx->partner_map;
grp_umac_reset_ctx->initiator_chip_id = dp_mlo_get_chip_id(soc);
grp_umac_reset_ctx->umac_reset_count++;
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
}
/**
* dp_umac_reset_handle_action_cb() - Function to call action callback
* @soc: dp soc handle
* @umac_reset_ctx: Umac reset context
* @action: Action to call the callback for
*
* Return: QDF_STATUS status
*/
QDF_STATUS
dp_umac_reset_handle_action_cb(struct dp_soc *soc,
struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_action action)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx;
if (!mlo_ctx) {
dp_umac_reset_debug("MLO context is Null");
goto handle;
}
grp_umac_reset_ctx = &mlo_ctx->grp_umac_reset_ctx;
qdf_spin_lock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
qdf_atomic_set_bit(dp_mlo_get_chip_id(soc),
&grp_umac_reset_ctx->request_map);
dp_umac_reset_debug("partner_map %u request_map %u",
grp_umac_reset_ctx->partner_map,
grp_umac_reset_ctx->request_map);
/* This logic is needed for synchronization between mlo socs */
if ((grp_umac_reset_ctx->partner_map & grp_umac_reset_ctx->request_map)
!= grp_umac_reset_ctx->partner_map) {
struct hif_softc *hif_sc = HIF_GET_SOFTC(soc->hif_handle);
struct hif_umac_reset_ctx *hif_umac_reset_ctx;
if (!hif_sc) {
hif_err("scn is null");
qdf_assert_always(0);
return QDF_STATUS_E_FAILURE;
}
hif_umac_reset_ctx = &hif_sc->umac_reset_ctx;
/* Mark the action as pending */
umac_reset_ctx->pending_action = action;
/* Reschedule the tasklet and exit */
tasklet_hi_schedule(&hif_umac_reset_ctx->intr_tq);
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
return QDF_STATUS_SUCCESS;
}
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
umac_reset_ctx->pending_action = UMAC_RESET_ACTION_NONE;
handle:
if (!umac_reset_ctx->rx_actions.cb[action]) {
dp_umac_reset_err("rx callback is NULL");
return QDF_STATUS_E_FAILURE;
}
return umac_reset_ctx->rx_actions.cb[action](soc);
}
/**
* dp_umac_reset_post_tx_cmd() - Iterate partner socs and post Tx command
* @umac_reset_ctx: UMAC reset context
* @tx_cmd: Tx command to be posted
*
* Return: QDF status of operation
*/
QDF_STATUS
dp_umac_reset_post_tx_cmd(struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_tx_cmd tx_cmd)
{
struct dp_soc *soc = container_of(umac_reset_ctx, struct dp_soc,
umac_reset_ctx);
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx;
if (!mlo_ctx) {
dp_umac_reset_post_tx_cmd_via_shmem(soc, &tx_cmd, 0);
return QDF_STATUS_SUCCESS;
}
grp_umac_reset_ctx = &mlo_ctx->grp_umac_reset_ctx;
qdf_spin_lock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
qdf_atomic_set_bit(dp_mlo_get_chip_id(soc),
&grp_umac_reset_ctx->response_map);
/* This logic is needed for synchronization between mlo socs */
if ((grp_umac_reset_ctx->partner_map & grp_umac_reset_ctx->response_map)
!= grp_umac_reset_ctx->partner_map) {
dp_umac_reset_debug(
"Response(s) pending : expected map %u current map %u",
grp_umac_reset_ctx->partner_map,
grp_umac_reset_ctx->response_map);
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
return QDF_STATUS_SUCCESS;
}
dp_umac_reset_debug(
"All responses received: expected map %u current map %u",
grp_umac_reset_ctx->partner_map,
grp_umac_reset_ctx->response_map);
grp_umac_reset_ctx->response_map = 0;
grp_umac_reset_ctx->request_map = 0;
qdf_spin_unlock_bh(&grp_umac_reset_ctx->grp_ctx_lock);
dp_mlo_iter_ptnr_soc(be_soc, &dp_umac_reset_post_tx_cmd_via_shmem,
&tx_cmd);
if (tx_cmd == UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE)
dp_umac_reset_complete_umac_recovery(soc);
return QDF_STATUS_SUCCESS;
}
/**
* dp_umac_reset_initiator_check() - Check if soc is the Umac reset initiator
* @soc: dp soc handle
*
* Return: true if the soc is initiator or false otherwise
*/
bool dp_umac_reset_initiator_check(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
if (!mlo_ctx)
return true;
return (mlo_ctx->grp_umac_reset_ctx.initiator_chip_id ==
dp_mlo_get_chip_id(soc));
}
/**
* dp_umac_reset_target_recovery_check() - Check if this is for target recovery
* @soc: dp soc handle
*
* Return: true if the session is for target recovery or false otherwise
*/
bool dp_umac_reset_target_recovery_check(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
if (!mlo_ctx)
return false;
return mlo_ctx->grp_umac_reset_ctx.is_target_recovery;
}
/**
* dp_umac_reset_is_soc_ignored() - Check if this soc is to be ignored
* @soc: dp soc handle
*
* Return: true if the soc is ignored or false otherwise
*/
bool dp_umac_reset_is_soc_ignored(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *mlo_ctx = be_soc->ml_ctxt;
if (!mlo_ctx)
return false;
return !qdf_atomic_test_bit(dp_mlo_get_chip_id(soc),
&mlo_ctx->grp_umac_reset_ctx.partner_map);
}
#endif

View File

@@ -46,6 +46,7 @@
* @link_to_pdev_map: link to pdev mapping * @link_to_pdev_map: link to pdev mapping
* @rx_fst: pointer to rx_fst handle * @rx_fst: pointer to rx_fst handle
* @rx_fst_ref_cnt: ref count of rx_fst * @rx_fst_ref_cnt: ref count of rx_fst
* @grp_umac_reset_ctx: UMAC reset context at mlo group level
*/ */
struct dp_mlo_ctxt { struct dp_mlo_ctxt {
struct cdp_ctrl_mlo_mgr *ctrl_ctxt; struct cdp_ctrl_mlo_mgr *ctrl_ctxt;
@@ -64,6 +65,9 @@ struct dp_mlo_ctxt {
uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ]; uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ];
struct dp_pdev_be *link_to_pdev_map[WLAN_MAX_MLO_CHIPS * struct dp_pdev_be *link_to_pdev_map[WLAN_MAX_MLO_CHIPS *
WLAN_MAX_MLO_LINKS_PER_SOC]; WLAN_MAX_MLO_LINKS_PER_SOC];
#ifdef DP_UMAC_HW_RESET_SUPPORT
struct dp_soc_mlo_umac_reset_ctx grp_umac_reset_ctx;
#endif
}; };
/** /**

View File

@@ -2669,6 +2669,74 @@ void dp_reo_desc_freelist_destroy(struct dp_soc *soc);
*/ */
void dp_reset_rx_reo_tid_queue(struct dp_soc *soc, void *hw_qdesc_vaddr, void dp_reset_rx_reo_tid_queue(struct dp_soc *soc, void *hw_qdesc_vaddr,
uint32_t size); uint32_t size);
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
/**
* dp_umac_reset_complete_umac_recovery() - Complete Umac reset session
* @soc: dp soc handle
*
* Return: void
*/
void dp_umac_reset_complete_umac_recovery(struct dp_soc *soc);
/**
* dp_umac_reset_initiate_umac_recovery() - Initiate Umac reset session
* @soc: dp soc handle
* @is_target_recovery: Flag to indicate if it is triggered for target recovery
*
* Return: void
*/
void dp_umac_reset_initiate_umac_recovery(struct dp_soc *soc,
bool is_target_recovery);
/**
* dp_umac_reset_handle_action_cb() - Function to call action callback
* @soc: dp soc handle
* @umac_reset_ctx: Umac reset context
* @action: Action to call the callback for
*
* Return: QDF_STATUS status
*/
QDF_STATUS dp_umac_reset_handle_action_cb(struct dp_soc *soc,
struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_action action);
/**
* dp_umac_reset_post_tx_cmd() - Iterate partner socs and post Tx command
* @umac_reset_ctx: UMAC reset context
* @tx_cmd: Tx command to be posted
*
* Return: QDF status of operation
*/
QDF_STATUS
dp_umac_reset_post_tx_cmd(struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_tx_cmd tx_cmd);
/**
* dp_umac_reset_initiator_check() - Check if soc is the Umac reset initiator
* @soc: dp soc handle
*
* Return: true if the soc is initiator or false otherwise
*/
bool dp_umac_reset_initiator_check(struct dp_soc *soc);
/**
* dp_umac_reset_target_recovery_check() - Check if this is for target recovery
* @soc: dp soc handle
*
* Return: true if the session is for target recovery or false otherwise
*/
bool dp_umac_reset_target_recovery_check(struct dp_soc *soc);
/**
* dp_umac_reset_is_soc_ignored() - Check if this soc is to be ignored
* @soc: dp soc handle
*
* Return: true if the soc is ignored or false otherwise
*/
bool dp_umac_reset_is_soc_ignored(struct dp_soc *soc);
#endif
#endif #endif
QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type,

View File

@@ -267,6 +267,7 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc,
enum hal_ring_type ring_type, enum hal_ring_type ring_type,
int ring_num); int ring_num);
#ifdef DP_UMAC_HW_RESET_SUPPORT #ifdef DP_UMAC_HW_RESET_SUPPORT
static QDF_STATUS dp_umac_reset_action_trigger_recovery(struct dp_soc *soc);
static QDF_STATUS dp_umac_reset_handle_pre_reset(struct dp_soc *soc); static QDF_STATUS dp_umac_reset_handle_pre_reset(struct dp_soc *soc);
static QDF_STATUS dp_umac_reset_handle_post_reset(struct dp_soc *soc); static QDF_STATUS dp_umac_reset_handle_post_reset(struct dp_soc *soc);
static QDF_STATUS dp_umac_reset_handle_post_reset_complete(struct dp_soc *soc); static QDF_STATUS dp_umac_reset_handle_post_reset_complete(struct dp_soc *soc);
@@ -2379,18 +2380,6 @@ static inline bool dp_skip_msi_cfg(struct dp_soc *soc, int ring_type)
#endif /* DP_CON_MON_MSI_ENABLED */ #endif /* DP_CON_MON_MSI_ENABLED */
#endif /* DISABLE_MON_RING_MSI_CFG */ #endif /* DISABLE_MON_RING_MSI_CFG */
#ifdef DP_UMAC_HW_RESET_SUPPORT
static bool dp_check_umac_reset_in_progress(struct dp_soc *soc)
{
return !!soc->umac_reset_ctx.intr_ctx_bkp;
}
#else
static bool dp_check_umac_reset_in_progress(struct dp_soc *soc)
{
return false;
}
#endif
QDF_STATUS dp_srng_init_idx(struct dp_soc *soc, struct dp_srng *srng, QDF_STATUS dp_srng_init_idx(struct dp_soc *soc, struct dp_srng *srng,
int ring_type, int ring_num, int mac_id, int ring_type, int ring_num, int mac_id,
uint32_t idx) uint32_t idx)
@@ -6877,6 +6866,10 @@ void dp_soc_txrx_peer_setup(enum wlan_op_mode vdev_opmode, struct dp_soc *soc,
#ifdef DP_UMAC_HW_RESET_SUPPORT #ifdef DP_UMAC_HW_RESET_SUPPORT
static void dp_register_umac_reset_handlers(struct dp_soc *soc) static void dp_register_umac_reset_handlers(struct dp_soc *soc)
{ {
dp_umac_reset_register_rx_action_callback(soc,
dp_umac_reset_action_trigger_recovery,
UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY);
dp_umac_reset_register_rx_action_callback(soc, dp_umac_reset_register_rx_action_callback(soc,
dp_umac_reset_handle_pre_reset, UMAC_RESET_ACTION_DO_PRE_RESET); dp_umac_reset_handle_pre_reset, UMAC_RESET_ACTION_DO_PRE_RESET);
@@ -13680,7 +13673,8 @@ static void dp_restore_interrupt_ring_masks(struct dp_soc *soc)
int num_ctxt = wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); int num_ctxt = wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx);
int i; int i;
qdf_assert_always(intr_bkp); if (!intr_bkp)
return;
for (i = 0; i < num_ctxt; i++) { for (i = 0; i < num_ctxt; i++) {
intr_ctx = &soc->intr_ctx[i]; intr_ctx = &soc->intr_ctx[i];
@@ -13892,6 +13886,19 @@ static void dp_reinit_rings(struct dp_soc *soc)
dp_soc_srng_init(soc); dp_soc_srng_init(soc);
} }
/**
* dp_umac_reset_action_trigger_recovery() - Handle FW Umac recovery trigger
* @soc: dp soc handle
*
* Return: QDF_STATUS
*/
static QDF_STATUS dp_umac_reset_action_trigger_recovery(struct dp_soc *soc)
{
enum umac_reset_action action = UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY;
return dp_umac_reset_notify_action_completion(soc, action);
}
/** /**
* dp_umac_reset_handle_pre_reset() - Handle Umac prereset interrupt from FW * dp_umac_reset_handle_pre_reset() - Handle Umac prereset interrupt from FW
* @soc: dp soc handle * @soc: dp soc handle
@@ -13975,9 +13982,12 @@ static QDF_STATUS dp_umac_reset_handle_post_reset_complete(struct dp_soc *soc)
nbuf_list = nbuf; nbuf_list = nbuf;
} }
dp_umac_reset_info("Umac reset done on soc %pK\n prereset : %u us\n" dp_umac_reset_info("Umac reset done on soc %pK\n trigger start : %u us "
"trigger done : %u us prereset : %u us\n"
"postreset : %u us \n postreset complete: %u us \n", "postreset : %u us \n postreset complete: %u us \n",
soc, soc,
soc->umac_reset_ctx.ts.trigger_done -
soc->umac_reset_ctx.ts.trigger_start,
soc->umac_reset_ctx.ts.pre_reset_done - soc->umac_reset_ctx.ts.pre_reset_done -
soc->umac_reset_ctx.ts.pre_reset_start, soc->umac_reset_ctx.ts.pre_reset_start,
soc->umac_reset_ctx.ts.post_reset_done - soc->umac_reset_ctx.ts.post_reset_done -

View File

@@ -176,6 +176,9 @@
(comb_peer_id_tid & DP_PEER_REO_STATS_PEER_ID_MASK) (comb_peer_id_tid & DP_PEER_REO_STATS_PEER_ID_MASK)
#endif #endif
typedef void dp_ptnr_soc_iter_func(struct dp_soc *ptnr_soc, void *arg,
int chip_id);
enum rx_pktlog_mode { enum rx_pktlog_mode {
DP_RX_PKTLOG_DISABLED = 0, DP_RX_PKTLOG_DISABLED = 0,
DP_RX_PKTLOG_FULL, DP_RX_PKTLOG_FULL,

View File

@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <dp_types.h> #include <dp_internal.h>
#include <wlan_cfg.h> #include <wlan_cfg.h>
#include <hif.h> #include <hif.h>
#include <dp_htt.h> #include <dp_htt.h>
@@ -107,7 +107,7 @@ QDF_STATUS dp_soc_umac_reset_init(struct dp_soc *soc)
umac_reset_ctx = &soc->umac_reset_ctx; umac_reset_ctx = &soc->umac_reset_ctx;
qdf_mem_zero(umac_reset_ctx, sizeof(*umac_reset_ctx)); qdf_mem_zero(umac_reset_ctx, sizeof(*umac_reset_ctx));
umac_reset_ctx->current_state = UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET; umac_reset_ctx->current_state = UMAC_RESET_STATE_WAIT_FOR_TRIGGER;
umac_reset_ctx->shmem_exp_magic_num = DP_UMAC_RESET_SHMEM_MAGIC_NUM; umac_reset_ctx->shmem_exp_magic_num = DP_UMAC_RESET_SHMEM_MAGIC_NUM;
status = dp_get_umac_reset_intr_ctx(soc, &umac_reset_ctx->intr_offset); status = dp_get_umac_reset_intr_ctx(soc, &umac_reset_ctx->intr_offset);
@@ -155,33 +155,6 @@ QDF_STATUS dp_soc_umac_reset_init(struct dp_soc *soc)
return dp_umac_reset_send_setup_cmd(soc); return dp_umac_reset_send_setup_cmd(soc);
} }
QDF_STATUS dp_soc_umac_reset_deinit(struct cdp_soc_t *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
struct dp_soc_umac_reset_ctx *umac_reset_ctx;
if (!soc) {
dp_umac_reset_err("DP SOC is null");
return QDF_STATUS_E_NULL_VALUE;
}
if (!soc->features.umac_hw_reset_support) {
dp_umac_reset_info("Target doesn't support the UMAC HW reset feature");
return QDF_STATUS_E_NOSUPPORT;
}
dp_umac_reset_interrupt_detach(soc);
umac_reset_ctx = &soc->umac_reset_ctx;
qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
umac_reset_ctx->shmem_size,
umac_reset_ctx->shmem_vaddr_unaligned,
umac_reset_ctx->shmem_paddr_unaligned,
0);
return QDF_STATUS_SUCCESS;
}
/** /**
* dp_umac_reset_get_rx_event_from_shmem() - Extract the Rx event from the * dp_umac_reset_get_rx_event_from_shmem() - Extract the Rx event from the
* shared memory * shared memory
@@ -219,6 +192,16 @@ dp_umac_reset_get_rx_event_from_shmem(
rx_event = UMAC_RESET_RX_EVENT_NONE; rx_event = UMAC_RESET_RX_EVENT_NONE;
if (HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_INITIATE_UMAC_RECOVERY_GET(t2h_msg)) {
rx_event |= UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY;
num_events++;
}
if (HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_INITIATE_TARGET_RECOVERY_SYNC_USING_UMAC_GET(t2h_msg)) {
rx_event |= UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC;
num_events++;
}
if (HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_DO_PRE_RESET_GET(t2h_msg)) { if (HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_DO_PRE_RESET_GET(t2h_msg)) {
rx_event |= UMAC_RESET_RX_EVENT_DO_PRE_RESET; rx_event |= UMAC_RESET_RX_EVENT_DO_PRE_RESET;
num_events++; num_events++;
@@ -247,6 +230,36 @@ err:
return UMAC_RESET_RX_EVENT_ERROR; return UMAC_RESET_RX_EVENT_ERROR;
} }
/**
* dp_umac_reset_peek_rx_event_from_shmem() - Peek the Rx event from the
* shared memory without clearing the bit
* @umac_reset_ctx: UMAC reset context
*
* Return: true if the shared memory has any valid bits set
*/
static inline bool dp_umac_reset_peek_rx_event_from_shmem(
struct dp_soc_umac_reset_ctx *umac_reset_ctx)
{
htt_umac_hang_recovery_msg_shmem_t *shmem_vaddr;
shmem_vaddr = umac_reset_ctx->shmem_vaddr_aligned;
if (!shmem_vaddr) {
dp_umac_reset_debug("Shared memory address is NULL");
goto err;
}
if (shmem_vaddr->magic_num != umac_reset_ctx->shmem_exp_magic_num) {
dp_umac_reset_debug("Shared memory got corrupted");
goto err;
}
/* Read the shared memory into a local variable */
return !!shmem_vaddr->t2h_msg;
err:
return false;
}
/** /**
* dp_umac_reset_get_rx_event() - Extract the Rx event * dp_umac_reset_get_rx_event() - Extract the Rx event
* @umac_reset_ctx: UMAC reset context * @umac_reset_ctx: UMAC reset context
@@ -280,7 +293,11 @@ dp_umac_reset_validate_n_update_state_machine_on_rx(
dp_umac_reset_err("state machine validation failed on rx event: %d, current state is %d", dp_umac_reset_err("state machine validation failed on rx event: %d, current state is %d",
rx_event, rx_event,
umac_reset_ctx->current_state); umac_reset_ctx->current_state);
qdf_assert_always(0);
if ((rx_event != UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY) &&
(rx_event != UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC))
qdf_assert_always(0);
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
@@ -289,6 +306,125 @@ dp_umac_reset_validate_n_update_state_machine_on_rx(
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
static bool dp_umac_reset_peek_rx_event(void *dp_ctx)
{
struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx;
struct dp_soc *soc = int_ctx->soc;
struct dp_soc_umac_reset_ctx *umac_reset_ctx = &soc->umac_reset_ctx;
return dp_umac_reset_peek_rx_event_from_shmem(umac_reset_ctx);
}
/**
* dp_check_umac_reset_in_progress() - Check if Umac reset is in progress
* @soc: dp soc handle
*
* Return: true if Umac reset is in progress or false otherwise
*/
bool dp_check_umac_reset_in_progress(struct dp_soc *soc)
{
return !!soc->umac_reset_ctx.intr_ctx_bkp;
}
#if !defined(WLAN_FEATURE_11BE_MLO) || !defined(WLAN_MLO_MULTI_CHIP)
/**
* dp_umac_reset_initiate_umac_recovery() - Initiate Umac reset session
* @soc: dp soc handle
* @is_target_recovery: Flag to indicate if it is triggered for target recovery
*
* Return: void
*/
static void dp_umac_reset_initiate_umac_recovery(struct dp_soc *soc,
bool is_target_recovery)
{
}
/**
* dp_umac_reset_complete_umac_recovery() - Complete Umac reset session
* @soc: dp soc handle
*
* Return: void
*/
static void dp_umac_reset_complete_umac_recovery(struct dp_soc *soc)
{
dp_umac_reset_alert("Umac reset was handled successfully on soc %pK",
soc);
}
/**
* dp_umac_reset_handle_action_cb() - Function to call action callback
* @soc: dp soc handle
* @umac_reset_ctx: Umac reset context
* @action: Action to call the callback for
*
* Return: QDF_STATUS status
*/
static QDF_STATUS dp_umac_reset_handle_action_cb(struct dp_soc *soc,
struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_action action)
{
if (!umac_reset_ctx->rx_actions.cb[action]) {
dp_umac_reset_err("rx callback is NULL");
return QDF_STATUS_E_FAILURE;
}
status = umac_reset_ctx->rx_actions.cb[action](soc);
return QDF_STATUS_SUCCESS;
}
/**
* dp_umac_reset_post_tx_cmd() - Iterate partner socs and post Tx command
* @umac_reset_ctx: UMAC reset context
* @tx_cmd: Tx command to be posted
*
* Return: QDF status of operation
*/
static QDF_STATUS
dp_umac_reset_post_tx_cmd(struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_tx_cmd tx_cmd)
{
struct dp_soc *soc = container_of(umac_reset_ctx, struct dp_soc,
umac_reset_ctx);
dp_umac_reset_post_tx_cmd_via_shmem(soc, &tx_cmd, 0);
return QDF_STATUS_SUCCESS;
}
/**
* dp_umac_reset_initiator_check() - Check if soc is the Umac reset initiator
* @soc: dp soc handle
*
* Return: true if the soc is initiator or false otherwise
*/
static bool dp_umac_reset_initiator_check(struct dp_soc *soc)
{
return true;
}
/**
* dp_umac_reset_target_recovery_check() - Check if this is for target recovery
* @soc: dp soc handle
*
* Return: true if the session is for target recovery or false otherwise
*/
static bool dp_umac_reset_target_recovery_check(struct dp_soc *soc)
{
return false;
}
/**
* dp_umac_reset_is_soc_ignored() - Check if this soc is to be ignored
* @soc: dp soc handle
*
* Return: true if the soc is ignored or false otherwise
*/
static bool dp_umac_reset_is_soc_ignored(struct dp_soc *soc)
{
return false;
}
#endif
/** /**
* dp_umac_reset_rx_event_handler() - Main Rx event handler for UMAC reset * dp_umac_reset_rx_event_handler() - Main Rx event handler for UMAC reset
* @dp_ctx: Interrupt context corresponding to UMAC reset * @dp_ctx: Interrupt context corresponding to UMAC reset
@@ -302,7 +438,8 @@ static int dp_umac_reset_rx_event_handler(void *dp_ctx)
struct dp_soc_umac_reset_ctx *umac_reset_ctx; struct dp_soc_umac_reset_ctx *umac_reset_ctx;
enum umac_reset_rx_event rx_event; enum umac_reset_rx_event rx_event;
QDF_STATUS status = QDF_STATUS_E_INVAL; QDF_STATUS status = QDF_STATUS_E_INVAL;
enum umac_reset_action action; enum umac_reset_action action = UMAC_RESET_ACTION_NONE;
bool target_recovery = false;
if (!soc) { if (!soc) {
dp_umac_reset_err("DP SOC is null"); dp_umac_reset_err("DP SOC is null");
@@ -314,43 +451,79 @@ static int dp_umac_reset_rx_event_handler(void *dp_ctx)
dp_umac_reset_debug("enter"); dp_umac_reset_debug("enter");
rx_event = dp_umac_reset_get_rx_event(umac_reset_ctx); rx_event = dp_umac_reset_get_rx_event(umac_reset_ctx);
if (umac_reset_ctx->pending_action) {
if (rx_event != UMAC_RESET_RX_EVENT_NONE) {
dp_umac_reset_err("Invalid value(%u) for Rx event when "
"action %u is pending\n", rx_event,
umac_reset_ctx->pending_action);
qdf_assert_always(0);
}
}
switch (rx_event) { switch (rx_event) {
case UMAC_RESET_RX_EVENT_NONE: case UMAC_RESET_RX_EVENT_NONE:
/* This interrupt is not meant for us, so exit */ if (umac_reset_ctx->pending_action)
dp_umac_reset_debug("Not a UMAC reset event"); action = umac_reset_ctx->pending_action;
else
dp_umac_reset_err("Not a UMAC reset event!!");
status = QDF_STATUS_SUCCESS; status = QDF_STATUS_SUCCESS;
goto exit; break;
case UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC:
target_recovery = true;
/* Fall through */
case UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY:
status = dp_umac_reset_validate_n_update_state_machine_on_rx(
umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_TRIGGER,
UMAC_RESET_STATE_DO_TRIGGER_RECEIVED);
if (status == QDF_STATUS_E_FAILURE)
goto exit;
umac_reset_ctx->ts.trigger_start =
qdf_get_log_timestamp_usecs();
action = UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY;
dp_umac_reset_initiate_umac_recovery(soc, target_recovery);
break;
case UMAC_RESET_RX_EVENT_DO_PRE_RESET: case UMAC_RESET_RX_EVENT_DO_PRE_RESET:
umac_reset_ctx->ts.pre_reset_start =
qdf_get_log_timestamp_usecs();
status = dp_umac_reset_validate_n_update_state_machine_on_rx( status = dp_umac_reset_validate_n_update_state_machine_on_rx(
umac_reset_ctx, rx_event, umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET, UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET,
UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED); UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED);
umac_reset_ctx->ts.pre_reset_start =
qdf_get_log_timestamp_usecs();
action = UMAC_RESET_ACTION_DO_PRE_RESET; action = UMAC_RESET_ACTION_DO_PRE_RESET;
break; break;
case UMAC_RESET_RX_EVENT_DO_POST_RESET_START: case UMAC_RESET_RX_EVENT_DO_POST_RESET_START:
umac_reset_ctx->ts.post_reset_start =
qdf_get_log_timestamp_usecs();
status = dp_umac_reset_validate_n_update_state_machine_on_rx( status = dp_umac_reset_validate_n_update_state_machine_on_rx(
umac_reset_ctx, rx_event, umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_START, UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_START,
UMAC_RESET_STATE_DO_POST_RESET_START_RECEIVED); UMAC_RESET_STATE_DO_POST_RESET_START_RECEIVED);
umac_reset_ctx->ts.post_reset_start =
qdf_get_log_timestamp_usecs();
action = UMAC_RESET_ACTION_DO_POST_RESET_START; action = UMAC_RESET_ACTION_DO_POST_RESET_START;
break; break;
case UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE: case UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE:
umac_reset_ctx->ts.post_reset_complete_start =
qdf_get_log_timestamp_usecs();
status = dp_umac_reset_validate_n_update_state_machine_on_rx( status = dp_umac_reset_validate_n_update_state_machine_on_rx(
umac_reset_ctx, rx_event, umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_COMPLETE, UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_COMPLETE,
UMAC_RESET_STATE_DO_POST_RESET_COMPLETE_RECEIVED); UMAC_RESET_STATE_DO_POST_RESET_COMPLETE_RECEIVED);
umac_reset_ctx->ts.post_reset_complete_start =
qdf_get_log_timestamp_usecs();
action = UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE; action = UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE;
break; break;
@@ -365,12 +538,7 @@ static int dp_umac_reset_rx_event_handler(void *dp_ctx)
/* Call the handler for this event */ /* Call the handler for this event */
if (QDF_IS_STATUS_SUCCESS(status)) { if (QDF_IS_STATUS_SUCCESS(status)) {
if (!umac_reset_ctx->rx_actions.cb[action]) { dp_umac_reset_handle_action_cb(soc, umac_reset_ctx, action);
dp_umac_reset_err("rx callback is NULL");
goto exit;
}
status = umac_reset_ctx->rx_actions.cb[action](soc);
} }
exit: exit:
@@ -432,6 +600,7 @@ QDF_STATUS dp_umac_reset_interrupt_attach(struct dp_soc *soc)
/* Finally register to this IRQ from HIF layer */ /* Finally register to this IRQ from HIF layer */
return hif_register_umac_reset_handler( return hif_register_umac_reset_handler(
soc->hif_handle, soc->hif_handle,
dp_umac_reset_peek_rx_event,
dp_umac_reset_rx_event_handler, dp_umac_reset_rx_event_handler,
&soc->intr_ctx[umac_reset_ctx->intr_offset], &soc->intr_ctx[umac_reset_ctx->intr_offset],
umac_reset_irq); umac_reset_irq);
@@ -465,7 +634,7 @@ QDF_STATUS dp_umac_reset_register_rx_action_callback(
} }
if (!soc->features.umac_hw_reset_support) { if (!soc->features.umac_hw_reset_support) {
dp_umac_reset_info("Target doesn't support the UMAC HW reset feature"); dp_umac_reset_info("Target doesn't support UMAC HW reset");
return QDF_STATUS_E_NOSUPPORT; return QDF_STATUS_E_NOSUPPORT;
} }
@@ -483,25 +652,55 @@ QDF_STATUS dp_umac_reset_register_rx_action_callback(
/** /**
* dp_umac_reset_post_tx_cmd_via_shmem() - Post Tx command using shared memory * dp_umac_reset_post_tx_cmd_via_shmem() - Post Tx command using shared memory
* @umac_reset_ctx: UMAC reset context * @soc: DP soc object
* @tx_cmd: Tx command to be posted * @ctxt: Tx command to be posted
* @chip_id: Chip id of the mlo soc
* *
* Return: QDF status of operation * Return: None
*/ */
static QDF_STATUS void
dp_umac_reset_post_tx_cmd_via_shmem( dp_umac_reset_post_tx_cmd_via_shmem(struct dp_soc *soc, void *ctxt, int chip_id)
struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_tx_cmd tx_cmd)
{ {
enum umac_reset_tx_cmd tx_cmd = *((enum umac_reset_tx_cmd *)ctxt);
htt_umac_hang_recovery_msg_shmem_t *shmem_vaddr; htt_umac_hang_recovery_msg_shmem_t *shmem_vaddr;
struct dp_soc_umac_reset_ctx *umac_reset_ctx = &soc->umac_reset_ctx;
bool initiator;
QDF_STATUS status;
if (dp_umac_reset_is_soc_ignored(soc)) {
dp_umac_reset_debug("Skipping soc (chip id %d)", chip_id);
return;
}
shmem_vaddr = umac_reset_ctx->shmem_vaddr_aligned; shmem_vaddr = umac_reset_ctx->shmem_vaddr_aligned;
if (!shmem_vaddr) { if (!shmem_vaddr) {
dp_umac_reset_err("Shared memory address is NULL"); dp_umac_reset_err("Shared memory address is NULL");
return QDF_STATUS_E_NULL_VALUE; return;
} }
dp_umac_reset_debug("Sending txcmd %u for chip id %u", tx_cmd, chip_id);
switch (tx_cmd) { switch (tx_cmd) {
case UMAC_RESET_TX_CMD_TRIGGER_DONE:
/* Send htt message to the partner soc */
initiator = dp_umac_reset_initiator_check(soc);
status = dp_htt_umac_reset_send_start_pre_reset_cmd(soc,
initiator,
!dp_umac_reset_target_recovery_check(soc));
if (status != QDF_STATUS_SUCCESS)
dp_umac_reset_err("Unable to send Umac trigger");
else
dp_umac_reset_debug("Sent trigger for soc (chip_id %d)",
chip_id);
if (!initiator)
umac_reset_ctx->current_state =
UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET;
umac_reset_ctx->ts.trigger_done = qdf_get_log_timestamp_usecs();
break;
case UMAC_RESET_TX_CMD_PRE_RESET_DONE: case UMAC_RESET_TX_CMD_PRE_RESET_DONE:
HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_PRE_RESET_DONE_SET( HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_PRE_RESET_DONE_SET(
shmem_vaddr->h2t_msg, 1); shmem_vaddr->h2t_msg, 1);
@@ -528,10 +727,10 @@ dp_umac_reset_post_tx_cmd_via_shmem(
default: default:
dp_umac_reset_err("Invalid tx cmd: %d", tx_cmd); dp_umac_reset_err("Invalid tx cmd: %d", tx_cmd);
return QDF_STATUS_E_FAILURE; return;
} }
return QDF_STATUS_SUCCESS; return;
} }
/** /**
@@ -552,6 +751,11 @@ dp_umac_reset_notify_target(struct dp_soc_umac_reset_ctx *umac_reset_ctx)
QDF_STATUS status; QDF_STATUS status;
switch (umac_reset_ctx->current_state) { switch (umac_reset_ctx->current_state) {
case UMAC_RESET_STATE_HOST_TRIGGER_DONE:
tx_cmd = UMAC_RESET_TX_CMD_TRIGGER_DONE;
next_state = UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET;
break;
case UMAC_RESET_STATE_HOST_PRE_RESET_DONE: case UMAC_RESET_STATE_HOST_PRE_RESET_DONE:
tx_cmd = UMAC_RESET_TX_CMD_PRE_RESET_DONE; tx_cmd = UMAC_RESET_TX_CMD_PRE_RESET_DONE;
next_state = UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_START; next_state = UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_START;
@@ -564,7 +768,7 @@ dp_umac_reset_notify_target(struct dp_soc_umac_reset_ctx *umac_reset_ctx)
case UMAC_RESET_STATE_HOST_POST_RESET_COMPLETE_DONE: case UMAC_RESET_STATE_HOST_POST_RESET_COMPLETE_DONE:
tx_cmd = UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE; tx_cmd = UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE;
next_state = UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET; next_state = UMAC_RESET_STATE_WAIT_FOR_TRIGGER;
break; break;
default: default:
@@ -574,7 +778,7 @@ dp_umac_reset_notify_target(struct dp_soc_umac_reset_ctx *umac_reset_ctx)
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
status = dp_umac_reset_post_tx_cmd_via_shmem(umac_reset_ctx, tx_cmd); status = dp_umac_reset_post_tx_cmd(umac_reset_ctx, tx_cmd);
if (QDF_IS_STATUS_ERROR(status)) { if (QDF_IS_STATUS_ERROR(status)) {
dp_umac_reset_err("Couldn't post Tx cmd"); dp_umac_reset_err("Couldn't post Tx cmd");
qdf_assert_always(0); qdf_assert_always(0);
@@ -615,6 +819,21 @@ static QDF_STATUS dp_umac_reset_notify_completion(
return dp_umac_reset_notify_target(umac_reset_ctx); return dp_umac_reset_notify_target(umac_reset_ctx);
} }
static void dp_umac_wait_for_quiescent_state(struct dp_soc *soc)
{
enum umac_reset_state current_state;
do {
msleep(10);
barrier();
current_state = soc->umac_reset_ctx.current_state;
} while ((current_state == UMAC_RESET_STATE_DO_TRIGGER_RECEIVED) ||
(current_state == UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED) ||
(current_state == UMAC_RESET_STATE_DO_POST_RESET_START_RECEIVED) ||
(current_state == UMAC_RESET_STATE_DO_POST_RESET_COMPLETE_RECEIVED));
}
QDF_STATUS dp_umac_reset_notify_action_completion( QDF_STATUS dp_umac_reset_notify_action_completion(
struct dp_soc *soc, struct dp_soc *soc,
enum umac_reset_action action) enum umac_reset_action action)
@@ -632,6 +851,10 @@ QDF_STATUS dp_umac_reset_notify_action_completion(
} }
switch (action) { switch (action) {
case UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY:
next_state = UMAC_RESET_STATE_HOST_TRIGGER_DONE;
break;
case UMAC_RESET_ACTION_DO_PRE_RESET: case UMAC_RESET_ACTION_DO_PRE_RESET:
next_state = UMAC_RESET_STATE_HOST_PRE_RESET_DONE; next_state = UMAC_RESET_STATE_HOST_PRE_RESET_DONE;
break; break;
@@ -644,6 +867,10 @@ QDF_STATUS dp_umac_reset_notify_action_completion(
next_state = UMAC_RESET_STATE_HOST_POST_RESET_COMPLETE_DONE; next_state = UMAC_RESET_STATE_HOST_POST_RESET_COMPLETE_DONE;
break; break;
case UMAC_RESET_ACTION_ABORT:
next_state = UMAC_RESET_STATE_WAIT_FOR_TRIGGER;
break;
default: default:
dp_umac_reset_err("Invalid action"); dp_umac_reset_err("Invalid action");
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
@@ -651,3 +878,56 @@ QDF_STATUS dp_umac_reset_notify_action_completion(
return dp_umac_reset_notify_completion(soc, next_state); return dp_umac_reset_notify_completion(soc, next_state);
} }
/**
* dp_soc_umac_reset_deinit() - Deinitialize the umac reset module
* @txrx_soc: DP soc object
*
* Return: QDF status of operation
*/
QDF_STATUS dp_soc_umac_reset_deinit(struct cdp_soc_t *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
struct dp_soc_umac_reset_ctx *umac_reset_ctx;
qdf_nbuf_t nbuf_list;
if (!soc) {
dp_umac_reset_err("DP SOC is null");
return QDF_STATUS_E_NULL_VALUE;
}
if (!soc->features.umac_hw_reset_support) {
dp_umac_reset_info("No target support for UMAC reset feature");
return QDF_STATUS_E_NOSUPPORT;
}
if (dp_check_umac_reset_in_progress(soc)) {
dp_umac_reset_info("Cleaning up Umac reset context");
dp_umac_wait_for_quiescent_state(soc);
dp_resume_reo_send_cmd(soc);
dp_umac_reset_notify_action_completion(soc,
UMAC_RESET_ACTION_ABORT);
}
nbuf_list = soc->umac_reset_ctx.nbuf_list;
soc->umac_reset_ctx.nbuf_list = NULL;
while (nbuf_list) {
qdf_nbuf_t nbuf = nbuf_list->next;
qdf_nbuf_free(nbuf_list);
nbuf_list = nbuf;
}
dp_umac_reset_interrupt_detach(soc);
umac_reset_ctx = &soc->umac_reset_ctx;
qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
umac_reset_ctx->shmem_size,
umac_reset_ctx->shmem_vaddr_unaligned,
umac_reset_ctx->shmem_paddr_unaligned,
0);
return QDF_STATUS_SUCCESS;
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -22,15 +22,21 @@ struct dp_soc;
/** /**
* enum umac_reset_action - Actions supported by the UMAC reset * enum umac_reset_action - Actions supported by the UMAC reset
* @UMAC_RESET_ACTION_NONE: No action
* @UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY: Trigger umac recovery
* @UMAC_RESET_ACTION_DO_PRE_RESET: DO_PRE_RESET * @UMAC_RESET_ACTION_DO_PRE_RESET: DO_PRE_RESET
* @UMAC_RESET_ACTION_DO_POST_RESET_START: DO_POST_RESET_START * @UMAC_RESET_ACTION_DO_POST_RESET_START: DO_POST_RESET_START
* @UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE: DO_POST_RESET_COMPLETE * @UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE: DO_POST_RESET_COMPLETE
* @UMAC_RESET_ACTION_ABORT: Abort the current Umac reset session
* @UMAC_RESET_ACTION_MAX: Maximum actions * @UMAC_RESET_ACTION_MAX: Maximum actions
*/ */
enum umac_reset_action { enum umac_reset_action {
UMAC_RESET_ACTION_DO_PRE_RESET = 0, UMAC_RESET_ACTION_NONE,
UMAC_RESET_ACTION_DO_POST_RESET_START = 1, UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY,
UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE = 2, UMAC_RESET_ACTION_DO_PRE_RESET,
UMAC_RESET_ACTION_DO_POST_RESET_START,
UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE,
UMAC_RESET_ACTION_ABORT,
UMAC_RESET_ACTION_MAX UMAC_RESET_ACTION_MAX
}; };
@@ -54,6 +60,9 @@ enum umac_reset_action {
/** /**
* enum umac_reset_state - States required by the UMAC reset state machine * enum umac_reset_state - States required by the UMAC reset state machine
* @UMAC_RESET_STATE_WAIT_FOR_TRIGGER: Waiting for trigger event
* @UMAC_RESET_STATE_DO_TRIGGER_RECEIVED: Receivd the DO_TRIGGER event
* @UMAC_RESET_STATE_HOST_TRIGGER_DONE: Host completed handling Trigger event
* @UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET: Waiting for the DO_PRE_RESET event * @UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET: Waiting for the DO_PRE_RESET event
* @UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED: Received the DO_PRE_RESET event * @UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED: Received the DO_PRE_RESET event
* @UMAC_RESET_STATE_HOST_PRE_RESET_DONE: Host has completed handling the * @UMAC_RESET_STATE_HOST_PRE_RESET_DONE: Host has completed handling the
@@ -72,7 +81,11 @@ enum umac_reset_action {
* the DO_POST_RESET_COMPLETE event * the DO_POST_RESET_COMPLETE event
*/ */
enum umac_reset_state { enum umac_reset_state {
UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET = 0, UMAC_RESET_STATE_WAIT_FOR_TRIGGER = 0,
UMAC_RESET_STATE_DO_TRIGGER_RECEIVED,
UMAC_RESET_STATE_HOST_TRIGGER_DONE,
UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET,
UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED, UMAC_RESET_STATE_DO_PRE_RESET_RECEIVED,
UMAC_RESET_STATE_HOST_PRE_RESET_DONE, UMAC_RESET_STATE_HOST_PRE_RESET_DONE,
@@ -88,6 +101,8 @@ enum umac_reset_state {
/** /**
* enum umac_reset_rx_event - Rx events deduced by the UMAC reset * enum umac_reset_rx_event - Rx events deduced by the UMAC reset
* @UMAC_RESET_RX_EVENT_NONE: No event * @UMAC_RESET_RX_EVENT_NONE: No event
* @UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY: ACTION_DO_TRIGGER_RECOVERY event
* @UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC: ACTION_DO_TRIGGER_RECOVERY event
* @UMAC_RESET_RX_EVENT_DO_PRE_RESET: DO_PRE_RESET event * @UMAC_RESET_RX_EVENT_DO_PRE_RESET: DO_PRE_RESET event
* @UMAC_RESET_RX_EVENT_DO_POST_RESET_START: DO_POST_RESET_START event * @UMAC_RESET_RX_EVENT_DO_POST_RESET_START: DO_POST_RESET_START event
* @UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE: DO_POST_RESET_COMPELTE event * @UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE: DO_POST_RESET_COMPELTE event
@@ -95,20 +110,24 @@ enum umac_reset_state {
*/ */
enum umac_reset_rx_event { enum umac_reset_rx_event {
UMAC_RESET_RX_EVENT_NONE = 0x0, UMAC_RESET_RX_EVENT_NONE = 0x0,
UMAC_RESET_RX_EVENT_DO_PRE_RESET = 0x1, UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY,
UMAC_RESET_RX_EVENT_DO_POST_RESET_START = 0x2, UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC,
UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE = 0x4, UMAC_RESET_RX_EVENT_DO_PRE_RESET,
UMAC_RESET_RX_EVENT_DO_POST_RESET_START,
UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE,
UMAC_RESET_RX_EVENT_ERROR = 0xFFFFFFFF, UMAC_RESET_RX_EVENT_ERROR = 0xFFFFFFFF,
}; };
/** /**
* enum umac_reset_tx_cmd: UMAC reset Tx command * enum umac_reset_tx_cmd: UMAC reset Tx command
* @UMAC_RESET_TX_CMD_TRIGGER_DONE: TRIGGER_DONE
* @UMAC_RESET_TX_CMD_PRE_RESET_DONE: PRE_RESET_DONE * @UMAC_RESET_TX_CMD_PRE_RESET_DONE: PRE_RESET_DONE
* @UMAC_RESET_TX_CMD_POST_RESET_START_DONE: POST_RESET_START_DONE * @UMAC_RESET_TX_CMD_POST_RESET_START_DONE: POST_RESET_START_DONE
* @UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE: POST_RESET_COMPLETE_DONE * @UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE: POST_RESET_COMPLETE_DONE
*/ */
enum umac_reset_tx_cmd { enum umac_reset_tx_cmd {
UMAC_RESET_TX_CMD_TRIGGER_DONE,
UMAC_RESET_TX_CMD_PRE_RESET_DONE, UMAC_RESET_TX_CMD_PRE_RESET_DONE,
UMAC_RESET_TX_CMD_POST_RESET_START_DONE, UMAC_RESET_TX_CMD_POST_RESET_START_DONE,
UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE, UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE,
@@ -125,6 +144,8 @@ struct umac_reset_rx_actions {
/** /**
* struct reset_ts - timestamps of for umac reset events for debug * struct reset_ts - timestamps of for umac reset events for debug
* @trigger_start: Umac reset trigger event timestamp
* @trigger_done: Umac reset trigger done timestamp
* @pre_reset_start: Umac prereset start event timestamp * @pre_reset_start: Umac prereset start event timestamp
* @pre_reset_done: Umac prereset done timestamp * @pre_reset_done: Umac prereset done timestamp
* @post_reset_start: Umac postreset start event timestamp * @post_reset_start: Umac postreset start event timestamp
@@ -133,6 +154,8 @@ struct umac_reset_rx_actions {
* @post_reset_complete_done: Umac postreset complete done timestamp * @post_reset_complete_done: Umac postreset complete done timestamp
*/ */
struct reset_ts { struct reset_ts {
uint64_t trigger_start;
uint64_t trigger_done;
uint64_t pre_reset_start; uint64_t pre_reset_start;
uint64_t pre_reset_done; uint64_t pre_reset_done;
uint64_t post_reset_start; uint64_t post_reset_start;
@@ -141,6 +164,30 @@ struct reset_ts {
uint64_t post_reset_complete_done; uint64_t post_reset_complete_done;
}; };
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
/**
* struct dp_soc_mlo_umac_reset_ctx - UMAC reset context at mlo group level
* @partner_map: Partner soc map
* @request_map: Partner soc request map
* @response_map: Partner soc response map
* @grp_ctx_lock: lock for accessing group level umac reset context
* @umac_reset_in_progress: Flag to indicate if umac reset is in progress
* @is_target_recovery: Flag to indicate if this is for target recovery
* @initiator_chip_id: chip id of the Umac reset initiator
* @umac_reset_count: Number of times Umac reset happened on this MLO group
*/
struct dp_soc_mlo_umac_reset_ctx {
unsigned long partner_map;
unsigned long request_map;
unsigned long response_map;
qdf_spinlock_t grp_ctx_lock;
uint8_t umac_reset_in_progress:1,
is_target_recovery:1;
uint8_t initiator_chip_id;
uint32_t umac_reset_count;
};
#endif
/** /**
* struct dp_soc_umac_reset_ctx - UMAC reset context at soc level * struct dp_soc_umac_reset_ctx - UMAC reset context at soc level
* @shmem_paddr_unaligned: Physical address of the shared memory (unaligned) * @shmem_paddr_unaligned: Physical address of the shared memory (unaligned)
@@ -152,6 +199,7 @@ struct reset_ts {
* @current_state: current state of the UMAC reset state machine * @current_state: current state of the UMAC reset state machine
* @shmem_exp_magic_num: Expected magic number in the shared memory * @shmem_exp_magic_num: Expected magic number in the shared memory
* @rx_actions: callbacks for handling UMAC reset actions * @rx_actions: callbacks for handling UMAC reset actions
* @pending_action: Action pending to be executed.
* @intr_ctx_bkp: DP Interrupts ring masks backup * @intr_ctx_bkp: DP Interrupts ring masks backup
* @nbuf_list: skb list for delayed free * @nbuf_list: skb list for delayed free
* @skel_enable: Enable skeleton code for umac reset * @skel_enable: Enable skeleton code for umac reset
@@ -167,6 +215,7 @@ struct dp_soc_umac_reset_ctx {
enum umac_reset_state current_state; enum umac_reset_state current_state;
uint32_t shmem_exp_magic_num; uint32_t shmem_exp_magic_num;
struct umac_reset_rx_actions rx_actions; struct umac_reset_rx_actions rx_actions;
enum umac_reset_rx_event pending_action;
struct dp_intr_bkp *intr_ctx_bkp; struct dp_intr_bkp *intr_ctx_bkp;
qdf_nbuf_t nbuf_list; qdf_nbuf_t nbuf_list;
bool skel_enable; bool skel_enable;
@@ -230,7 +279,31 @@ QDF_STATUS dp_umac_reset_register_rx_action_callback(
QDF_STATUS dp_umac_reset_notify_action_completion( QDF_STATUS dp_umac_reset_notify_action_completion(
struct dp_soc *soc, struct dp_soc *soc,
enum umac_reset_action action); enum umac_reset_action action);
/**
* dp_umac_reset_post_tx_cmd_via_shmem() - Post Tx command using shared memory
* @soc: DP soc object
* @ctxt: Tx command to be posted
* @chip_id: Chip id of the mlo soc
*
* Return: None
*/
void dp_umac_reset_post_tx_cmd_via_shmem(struct dp_soc *soc, void *ctxt,
int chip_id);
/**
* dp_check_umac_reset_in_progress() - Check if Umac reset is in progress
* @soc: dp soc handle
*
* Return: true if Umac reset is in progress or false otherwise
*/
bool dp_check_umac_reset_in_progress(struct dp_soc *soc);
#else #else
static inline bool dp_check_umac_reset_in_progress(struct dp_soc *soc)
{
return false;
}
static inline static inline
QDF_STATUS dp_soc_umac_reset_init(struct dp_soc *soc) QDF_STATUS dp_soc_umac_reset_init(struct dp_soc *soc)
{ {

View File

@@ -1759,7 +1759,8 @@ void dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
#ifdef QCA_ENHANCED_STATS_SUPPORT #ifdef QCA_ENHANCED_STATS_SUPPORT
static void static void
dp_enable_enhanced_stats_for_each_pdev(struct dp_soc *soc, void *arg) { dp_enable_enhanced_stats_for_each_pdev(struct dp_soc *soc, void *arg,
int chip_id) {
uint8_t i = 0; uint8_t i = 0;
for (i = 0; i < MAX_PDEV_CNT; i++) for (i = 0; i < MAX_PDEV_CNT; i++)
@@ -1781,7 +1782,8 @@ dp_enable_enhanced_stats_2_0(struct cdp_soc_t *soc, uint8_t pdev_id)
} }
static void static void
dp_disable_enhanced_stats_for_each_pdev(struct dp_soc *soc, void *arg) { dp_disable_enhanced_stats_for_each_pdev(struct dp_soc *soc, void *arg,
int chip_id) {
uint8_t i = 0; uint8_t i = 0;
for (i = 0; i < MAX_PDEV_CNT; i++) for (i = 0; i < MAX_PDEV_CNT; i++)

View File

@@ -2625,14 +2625,16 @@ uint8_t hif_get_max_wmi_ep(struct hif_opaque_softc *scn);
/** /**
* hif_register_umac_reset_handler() - Register UMAC HW reset handler * hif_register_umac_reset_handler() - Register UMAC HW reset handler
* @hif_scn: hif opaque handle * @hif_scn: hif opaque handle
* @handler: callback handler function * @irq_handler: irq callback handler function
* @tl_handler: tasklet callback handler function
* @cb_ctx: context to passed to @handler * @cb_ctx: context to passed to @handler
* @irq: irq number to be used for UMAC HW reset interrupt * @irq: irq number to be used for UMAC HW reset interrupt
* *
* Return: QDF_STATUS of operation * Return: QDF_STATUS of operation
*/ */
QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn, QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn,
int (*handler)(void *cb_ctx), bool (*irq_handler)(void *cb_ctx),
int (*tl_handler)(void *cb_ctx),
void *cb_ctx, int irq); void *cb_ctx, int irq);
/** /**
@@ -2647,7 +2649,8 @@ QDF_STATUS hif_get_umac_reset_irq(struct hif_opaque_softc *hif_scn,
#else #else
static inline static inline
QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn, QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn,
int (*handler)(void *cb_ctx), bool (*irq_handler)(void *cb_ctx),
int (*tl_handler)(void *cb_ctx),
void *cb_ctx, int irq) void *cb_ctx, int irq)
{ {
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;

View File

@@ -1197,8 +1197,9 @@ static irqreturn_t hif_umac_reset_irq_handler(int irq, void *ctx)
{ {
struct hif_umac_reset_ctx *umac_reset_ctx = ctx; struct hif_umac_reset_ctx *umac_reset_ctx = ctx;
/* Schedule the tasklet and exit */ /* Schedule the tasklet if it is umac reset interrupt and exit */
tasklet_hi_schedule(&umac_reset_ctx->intr_tq); if (umac_reset_ctx->irq_handler(umac_reset_ctx->cb_ctx))
tasklet_hi_schedule(&umac_reset_ctx->intr_tq);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -1224,7 +1225,8 @@ QDF_STATUS hif_get_umac_reset_irq(struct hif_opaque_softc *hif_scn,
qdf_export_symbol(hif_get_umac_reset_irq); qdf_export_symbol(hif_get_umac_reset_irq);
QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn, QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn,
int (*handler)(void *cb_ctx), bool (*irq_handler)(void *cb_ctx),
int (*tl_handler)(void *cb_ctx),
void *cb_ctx, int irq) void *cb_ctx, int irq)
{ {
struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_scn); struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_scn);
@@ -1238,7 +1240,8 @@ QDF_STATUS hif_register_umac_reset_handler(struct hif_opaque_softc *hif_scn,
umac_reset_ctx = &hif_sc->umac_reset_ctx; umac_reset_ctx = &hif_sc->umac_reset_ctx;
umac_reset_ctx->cb_handler = handler; umac_reset_ctx->irq_handler = irq_handler;
umac_reset_ctx->cb_handler = tl_handler;
umac_reset_ctx->cb_ctx = cb_ctx; umac_reset_ctx->cb_ctx = cb_ctx;
umac_reset_ctx->os_irq = irq; umac_reset_ctx->os_irq = irq;

View File

@@ -243,6 +243,7 @@ struct hif_cfg {
/** /**
* struct hif_umac_reset_ctx - UMAC HW reset context at HIF layer * struct hif_umac_reset_ctx - UMAC HW reset context at HIF layer
* @intr_tq: Tasklet structure * @intr_tq: Tasklet structure
* @irq_handler: IRQ handler
* @cb_handler: Callback handler * @cb_handler: Callback handler
* @cb_ctx: Argument to be passed to @cb_handler * @cb_ctx: Argument to be passed to @cb_handler
* @os_irq: Interrupt number for this IRQ * @os_irq: Interrupt number for this IRQ
@@ -250,6 +251,7 @@ struct hif_cfg {
*/ */
struct hif_umac_reset_ctx { struct hif_umac_reset_ctx {
struct tasklet_struct intr_tq; struct tasklet_struct intr_tq;
bool (*irq_handler)(void *cb_ctx);
int (*cb_handler)(void *cb_ctx); int (*cb_handler)(void *cb_ctx);
void *cb_ctx; void *cb_ctx;
uint32_t os_irq; uint32_t os_irq;