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;
}
/**
* 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
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,
struct dp_vdev *ptnr_vdev,
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
@@ -527,17 +536,7 @@ void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
dp_ptnr_vdev_iter_func func,
void *arg,
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
* @be_soc: dp_soc_be pointer

View File

@@ -24,7 +24,20 @@
#include <dp_internal.h>
#include <wlan_cfg.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
* @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));
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);
}
@@ -75,6 +89,7 @@ static void dp_mlo_ctxt_detach_wifi3(struct cdp_mlo_ctxt *cdp_ml_ctxt)
if (!cdp_ml_ctxt)
return;
qdf_spinlock_destroy(&mlo_ctxt->grp_umac_reset_ctx.grp_ctx_lock);
qdf_spinlock_destroy(&mlo_ctxt->ml_soc_list_lock);
dp_mlo_peer_find_hash_detach_be(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
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);
}
@@ -164,7 +181,7 @@ static QDF_STATUS dp_partner_soc_rx_hw_cc_init(struct dp_mlo_ctxt *mlo_ctxt,
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 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
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,
struct dp_vdev_be *be_vdev,
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);
#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)
{
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;
}
#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
* @rx_fst: pointer to rx_fst handle
* @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 cdp_ctrl_mlo_mgr *ctrl_ctxt;
@@ -64,6 +65,9 @@ struct dp_mlo_ctxt {
uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ];
struct dp_pdev_be *link_to_pdev_map[WLAN_MAX_MLO_CHIPS *
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,
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
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,
int ring_num);
#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_post_reset(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 /* 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,
int ring_type, int ring_num, int mac_id,
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
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_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 i;
qdf_assert_always(intr_bkp);
if (!intr_bkp)
return;
for (i = 0; i < num_ctxt; 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_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
* @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;
}
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",
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_start,
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)
#endif
typedef void dp_ptnr_soc_iter_func(struct dp_soc *ptnr_soc, void *arg,
int chip_id);
enum rx_pktlog_mode {
DP_RX_PKTLOG_DISABLED = 0,
DP_RX_PKTLOG_FULL,

View File

@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <dp_types.h>
#include <dp_internal.h>
#include <wlan_cfg.h>
#include <hif.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;
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;
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);
}
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
* shared memory
@@ -219,6 +192,16 @@ dp_umac_reset_get_rx_event_from_shmem(
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)) {
rx_event |= UMAC_RESET_RX_EVENT_DO_PRE_RESET;
num_events++;
@@ -247,6 +230,36 @@ err:
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
* @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",
rx_event,
umac_reset_ctx->current_state);
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;
}
@@ -289,6 +306,125 @@ dp_umac_reset_validate_n_update_state_machine_on_rx(
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_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;
enum umac_reset_rx_event rx_event;
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) {
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");
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) {
case UMAC_RESET_RX_EVENT_NONE:
/* This interrupt is not meant for us, so exit */
dp_umac_reset_debug("Not a UMAC reset event");
if (umac_reset_ctx->pending_action)
action = umac_reset_ctx->pending_action;
else
dp_umac_reset_err("Not a UMAC reset event!!");
status = QDF_STATUS_SUCCESS;
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;
case UMAC_RESET_RX_EVENT_DO_PRE_RESET:
umac_reset_ctx->ts.pre_reset_start =
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:
status = dp_umac_reset_validate_n_update_state_machine_on_rx(
umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_PRE_RESET,
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;
break;
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(
umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_START,
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;
break;
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(
umac_reset_ctx, rx_event,
UMAC_RESET_STATE_WAIT_FOR_DO_POST_RESET_COMPLETE,
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;
break;
@@ -365,12 +538,7 @@ static int dp_umac_reset_rx_event_handler(void *dp_ctx)
/* Call the handler for this event */
if (QDF_IS_STATUS_SUCCESS(status)) {
if (!umac_reset_ctx->rx_actions.cb[action]) {
dp_umac_reset_err("rx callback is NULL");
goto exit;
}
status = umac_reset_ctx->rx_actions.cb[action](soc);
dp_umac_reset_handle_action_cb(soc, umac_reset_ctx, action);
}
exit:
@@ -432,6 +600,7 @@ QDF_STATUS dp_umac_reset_interrupt_attach(struct dp_soc *soc)
/* Finally register to this IRQ from HIF layer */
return hif_register_umac_reset_handler(
soc->hif_handle,
dp_umac_reset_peek_rx_event,
dp_umac_reset_rx_event_handler,
&soc->intr_ctx[umac_reset_ctx->intr_offset],
umac_reset_irq);
@@ -465,7 +634,7 @@ QDF_STATUS dp_umac_reset_register_rx_action_callback(
}
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;
}
@@ -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
* @umac_reset_ctx: UMAC reset context
* @tx_cmd: Tx command to be posted
* @soc: DP soc object
* @ctxt: Tx command to be posted
* @chip_id: Chip id of the mlo soc
*
* Return: QDF status of operation
* Return: None
*/
static QDF_STATUS
dp_umac_reset_post_tx_cmd_via_shmem(
struct dp_soc_umac_reset_ctx *umac_reset_ctx,
enum umac_reset_tx_cmd tx_cmd)
void
dp_umac_reset_post_tx_cmd_via_shmem(struct dp_soc *soc, void *ctxt, int chip_id)
{
enum umac_reset_tx_cmd tx_cmd = *((enum umac_reset_tx_cmd *)ctxt);
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;
if (!shmem_vaddr) {
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) {
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:
HTT_UMAC_HANG_RECOVERY_MSG_SHMEM_PRE_RESET_DONE_SET(
shmem_vaddr->h2t_msg, 1);
@@ -528,10 +727,10 @@ dp_umac_reset_post_tx_cmd_via_shmem(
default:
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;
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:
tx_cmd = UMAC_RESET_TX_CMD_PRE_RESET_DONE;
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:
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;
default:
@@ -574,7 +778,7 @@ dp_umac_reset_notify_target(struct dp_soc_umac_reset_ctx *umac_reset_ctx)
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)) {
dp_umac_reset_err("Couldn't post Tx cmd");
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);
}
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(
struct dp_soc *soc,
enum umac_reset_action action)
@@ -632,6 +851,10 @@ QDF_STATUS dp_umac_reset_notify_action_completion(
}
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:
next_state = UMAC_RESET_STATE_HOST_PRE_RESET_DONE;
break;
@@ -644,6 +867,10 @@ QDF_STATUS dp_umac_reset_notify_action_completion(
next_state = UMAC_RESET_STATE_HOST_POST_RESET_COMPLETE_DONE;
break;
case UMAC_RESET_ACTION_ABORT:
next_state = UMAC_RESET_STATE_WAIT_FOR_TRIGGER;
break;
default:
dp_umac_reset_err("Invalid action");
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);
}
/**
* 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
* 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
* @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_POST_RESET_START: DO_POST_RESET_START
* @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
*/
enum umac_reset_action {
UMAC_RESET_ACTION_DO_PRE_RESET = 0,
UMAC_RESET_ACTION_DO_POST_RESET_START = 1,
UMAC_RESET_ACTION_DO_POST_RESET_COMPLETE = 2,
UMAC_RESET_ACTION_NONE,
UMAC_RESET_ACTION_DO_TRIGGER_RECOVERY,
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
};
@@ -54,6 +60,9 @@ enum umac_reset_action {
/**
* 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_DO_PRE_RESET_RECEIVED: Received the DO_PRE_RESET event
* @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
*/
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_HOST_PRE_RESET_DONE,
@@ -88,6 +101,8 @@ enum umac_reset_state {
/**
* enum umac_reset_rx_event - Rx events deduced by the UMAC reset
* @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_POST_RESET_START: DO_POST_RESET_START 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 {
UMAC_RESET_RX_EVENT_NONE = 0x0,
UMAC_RESET_RX_EVENT_DO_PRE_RESET = 0x1,
UMAC_RESET_RX_EVENT_DO_POST_RESET_START = 0x2,
UMAC_RESET_RX_EVENT_DO_POST_RESET_COMPELTE = 0x4,
UMAC_RESET_RX_EVENT_DO_TRIGGER_RECOVERY,
UMAC_RESET_RX_EVENT_DO_TRIGGER_TR_SYNC,
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,
};
/**
* 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_POST_RESET_START_DONE: POST_RESET_START_DONE
* @UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE: POST_RESET_COMPLETE_DONE
*/
enum umac_reset_tx_cmd {
UMAC_RESET_TX_CMD_TRIGGER_DONE,
UMAC_RESET_TX_CMD_PRE_RESET_DONE,
UMAC_RESET_TX_CMD_POST_RESET_START_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
* @trigger_start: Umac reset trigger event timestamp
* @trigger_done: Umac reset trigger done timestamp
* @pre_reset_start: Umac prereset start event timestamp
* @pre_reset_done: Umac prereset done 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
*/
struct reset_ts {
uint64_t trigger_start;
uint64_t trigger_done;
uint64_t pre_reset_start;
uint64_t pre_reset_done;
uint64_t post_reset_start;
@@ -141,6 +164,30 @@ struct reset_ts {
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
* @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
* @shmem_exp_magic_num: Expected magic number in the shared memory
* @rx_actions: callbacks for handling UMAC reset actions
* @pending_action: Action pending to be executed.
* @intr_ctx_bkp: DP Interrupts ring masks backup
* @nbuf_list: skb list for delayed free
* @skel_enable: Enable skeleton code for umac reset
@@ -167,6 +215,7 @@ struct dp_soc_umac_reset_ctx {
enum umac_reset_state current_state;
uint32_t shmem_exp_magic_num;
struct umac_reset_rx_actions rx_actions;
enum umac_reset_rx_event pending_action;
struct dp_intr_bkp *intr_ctx_bkp;
qdf_nbuf_t nbuf_list;
bool skel_enable;
@@ -230,7 +279,31 @@ QDF_STATUS dp_umac_reset_register_rx_action_callback(
QDF_STATUS dp_umac_reset_notify_action_completion(
struct dp_soc *soc,
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
static inline bool dp_check_umac_reset_in_progress(struct dp_soc *soc)
{
return false;
}
static inline
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
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;
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
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;
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_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
* @irq: irq number to be used for UMAC HW reset interrupt
*
* Return: QDF_STATUS of operation
*/
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);
/**
@@ -2647,7 +2649,8 @@ QDF_STATUS hif_get_umac_reset_irq(struct hif_opaque_softc *hif_scn,
#else
static inline
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)
{
return QDF_STATUS_SUCCESS;

View File

@@ -1197,7 +1197,8 @@ static irqreturn_t hif_umac_reset_irq_handler(int irq, void *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 */
if (umac_reset_ctx->irq_handler(umac_reset_ctx->cb_ctx))
tasklet_hi_schedule(&umac_reset_ctx->intr_tq);
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_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)
{
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->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->os_irq = irq;

View File

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