| /* |
| * wl ampdu command module |
| * |
| * Broadcom Proprietary and Confidential. Copyright (C) 2017, |
| * All Rights Reserved. |
| * |
| * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom; |
| * the contents of this file may not be disclosed to third parties, copied |
| * or duplicated in any form, in whole or in part, without the prior |
| * written permission of Broadcom. |
| * |
| * |
| * <<Broadcom-WL-IPTag/Proprietary:>> |
| * |
| * $Id: wluc_ampdu.c 458728 2014-02-27 18:15:25Z $ |
| */ |
| |
| #ifdef WIN32 |
| #include <windows.h> |
| #endif |
| |
| #include <wlioctl.h> |
| |
| #if defined(DONGLEBUILD) |
| #include <typedefs.h> |
| #include <osl.h> |
| #endif |
| |
| /* Because IL_BIGENDIAN was removed there are few warnings that need |
| * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN. |
| * Hence these warnings were not seen earlier. |
| * For now ignore the following warnings |
| */ |
| #ifdef WIN32 |
| #pragma warning(push) |
| #pragma warning(disable : 4244) |
| #pragma warning(disable : 4761) |
| #endif |
| |
| #include <bcmutils.h> |
| #include <bcmendian.h> |
| #include "wlu_common.h" |
| #include "wlu.h" |
| |
| static cmd_func_t wl_ampdu_tid; |
| static cmd_func_t wl_ampdu_aggr; |
| static cmd_func_t wl_ampdu_retry_limit_tid; |
| static cmd_func_t wl_ampdu_rr_retry_limit_tid; |
| static cmd_func_t wl_ampdu_send_addba; |
| static cmd_func_t wl_ampdu_send_delba; |
| |
| static cmd_t wl_ampdu_cmds[] = { |
| { "ampdu_tid", wl_ampdu_tid, WLC_GET_VAR, WLC_SET_VAR, |
| "enable/disable per-tid ampdu; usage: wl ampdu_tid <tid> [0/1]" }, |
| { "ampdu_txaggr", wl_ampdu_aggr, WLC_GET_VAR, WLC_SET_VAR, |
| "enable/disable tx aggregation per tid or all tid for specific interface;\n" |
| "\tget current status: wl ampdu_txaggr\n" |
| "\tenable/disable all category(tid): wl ampdu_txaggr <0/1>\n" |
| "\tenable/disable per category(tid): wl ampdu_txaggr [<tid> <0/1>]"}, |
| { "ampdu_rxaggr", wl_ampdu_aggr, WLC_GET_VAR, WLC_SET_VAR, |
| "enable/disable rx aggregation per tid or all tid for specific interface;\n" |
| "\tget current status: wl ampdu_rxaggr\n" |
| "\tenable/disable all category(tid): wl ampdu_rxaggr <0/1>\n" |
| "\tenable/disable per category(tid): wl ampdu_rxaggr [<tid> <0/1>]"}, |
| { "ampdu_retry_limit_tid", wl_ampdu_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR, |
| "Set per-tid ampdu retry limit; usage: wl ampdu_retry_limit_tid <tid> [0~31]" }, |
| { "ampdu_rr_retry_limit_tid", wl_ampdu_rr_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR, |
| "Set per-tid ampdu regular rate retry limit; usage: " |
| "wl ampdu_rr_retry_limit_tid <tid> [0~31]" }, |
| { "ampdu_send_addba", wl_ampdu_send_addba, WLC_GET_VAR, WLC_SET_VAR, |
| "send addba to specified ea-tid; usage: wl ampdu_send_addba <tid> <ea>" }, |
| { "ampdu_send_delba", wl_ampdu_send_delba, WLC_GET_VAR, WLC_SET_VAR, |
| "send delba to specified ea-tid; usage: wl ampdu_send_delba <tid> <ea> [initiator]" }, |
| { "ampdu_txq_prof_start", wl_var_void, -1, WLC_SET_VAR, |
| "start sample txq profiling data"}, |
| { "ampdu_txq_prof_dump", wl_var_void, -1, WLC_SET_VAR, |
| "show txq histogram"}, |
| { "ampdu_txq_ss", wl_var_void, -1, WLC_SET_VAR, |
| "take txq snapshot"}, |
| { NULL, NULL, 0, 0, NULL } |
| }; |
| |
| static char *buf; |
| |
| /* module initialization */ |
| void |
| wluc_ampdu_module_init(void) |
| { |
| (void)g_swap; |
| |
| /* get the global buf */ |
| buf = wl_get_buf(); |
| |
| /* register ampdu commands */ |
| wl_module_cmds_register(wl_ampdu_cmds); |
| } |
| |
| static int |
| wl_ampdu_tid(void *wl, cmd_t *cmd, char **argv) |
| { |
| char *param; |
| const char *cmdname = "ampdu_tid"; |
| struct ampdu_tid_control atc, *reply; |
| uint8 tid; |
| int err; |
| void *ptr = NULL; |
| |
| UNUSED_PARAMETER(cmd); |
| |
| if ((param = *++argv) == NULL) |
| return BCME_USAGE_ERROR; |
| |
| tid = atoi(param); |
| if (tid > MAXPRIO) |
| return BCME_USAGE_ERROR; |
| atc.tid = tid; |
| |
| if ((param = *++argv)) { |
| atc.enable = atoi(param); |
| err = wlu_var_setbuf(wl, cmdname, &atc, sizeof(atc)); |
| } else { |
| if ((err = wlu_var_getbuf_sm(wl, cmdname, &atc, sizeof(atc), &ptr) < 0)) |
| return err; |
| reply = (struct ampdu_tid_control *)ptr; |
| printf("AMPDU for tid %d: %d\n", tid, reply->enable); |
| } |
| return err; |
| } |
| |
| static int |
| wl_ampdu_aggr(void *wl, cmd_t *cmd, char **argv) |
| { |
| struct ampdu_aggr aggr, *reply; |
| int err; |
| int idx; |
| void *ptr = NULL; |
| |
| if (argv[1] == NULL) { |
| /* get current status of aggregation */ |
| if ((err = wlu_var_getbuf_sm(wl, cmd->name, &aggr, sizeof(aggr), &ptr) < 0)) { |
| return err; |
| } |
| reply = ptr; |
| printf("%s_override: %s\n", cmd->name, (reply->aggr_override == AUTO) ? "AUTO" : |
| ((reply->aggr_override == ON) ? "ON" : "OFF")); |
| for (idx = 0; idx < NUMPRIO; idx++) { |
| printf("tid:%d status:%d\n", idx, isbitset(reply->enab_TID_bmap, idx)); |
| } |
| return err; |
| } |
| memset(&aggr, 0, sizeof(aggr)); |
| if (argv[2] == NULL) { |
| /* Set for all TID */ |
| bool enab = atoi(*++argv); |
| aggr.enab_TID_bmap = enab ? NBITMASK(NUMPRIO) : 0; |
| aggr.conf_TID_bmap = NBITMASK(NUMPRIO); |
| } else { |
| char *param; |
| /* Set for specific TIDs */ |
| while ((param = *++argv) != NULL) { |
| uint8 tid; |
| bool enab; |
| tid = atoi(param); |
| if (tid > MAXPRIO) { |
| return BCME_USAGE_ERROR; |
| } |
| if ((param = *++argv) == NULL) { |
| return BCME_USAGE_ERROR; |
| } |
| enab = atoi(param); |
| setbit(&aggr.conf_TID_bmap, tid); |
| if (enab) { |
| setbit(&aggr.enab_TID_bmap, tid); |
| } |
| } |
| } |
| err = wlu_var_setbuf(wl, cmd->name, &aggr, sizeof(aggr)); |
| return err; |
| } |
| |
| static int |
| wl_ampdu_retry_limit_tid(void *wl, cmd_t *cmd, char **argv) |
| { |
| char *param; |
| const char *cmdname = "ampdu_retry_limit_tid"; |
| struct ampdu_retry_tid retry_limit, *reply; |
| uint8 tid; |
| int err; |
| void *ptr = NULL; |
| |
| UNUSED_PARAMETER(cmd); |
| |
| if ((param = *++argv) == NULL) |
| return BCME_USAGE_ERROR; |
| |
| tid = atoi(param); |
| if (tid > MAXPRIO) |
| return BCME_USAGE_ERROR; |
| retry_limit.tid = tid; |
| |
| if ((param = *++argv)) { |
| retry_limit.retry = atoi(param); |
| err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit)); |
| } else { |
| if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit, |
| sizeof(retry_limit), &ptr)) < 0) |
| return err; |
| reply = (struct ampdu_retry_tid *)ptr; |
| printf("AMPDU retry limit for tid %d: %d\n", tid, reply->retry); |
| } |
| return err; |
| } |
| |
| static int |
| wl_ampdu_rr_retry_limit_tid(void *wl, cmd_t *cmd, char **argv) |
| { |
| char *param; |
| const char *cmdname = "ampdu_rr_retry_limit_tid"; |
| struct ampdu_retry_tid retry_limit, *reply; |
| uint8 tid; |
| int err; |
| void *ptr = NULL; |
| |
| UNUSED_PARAMETER(cmd); |
| |
| if ((param = *++argv) == NULL) |
| return BCME_USAGE_ERROR; |
| |
| tid = atoi(param); |
| if (tid > MAXPRIO) |
| return BCME_USAGE_ERROR; |
| retry_limit.tid = tid; |
| |
| if ((param = *++argv)) { |
| retry_limit.retry = atoi(param); |
| err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit)); |
| } else { |
| if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit, |
| sizeof(retry_limit), &ptr)) < 0) |
| return err; |
| reply = (struct ampdu_retry_tid *)ptr; |
| printf("AMPDU regular rate retry limit for tid %d: %d\n", tid, reply->retry); |
| } |
| return err; |
| } |
| |
| |
| static int |
| wl_ampdu_send_addba(void *wl, cmd_t *cmd, char **argv) |
| { |
| char *param; |
| const char *cmdname = "ampdu_send_addba"; |
| struct ampdu_ea_tid aet; |
| uint8 tid; |
| |
| UNUSED_PARAMETER(cmd); |
| |
| if ((param = *++argv) == NULL) |
| return BCME_USAGE_ERROR; |
| |
| tid = atoi(param); |
| if (tid > MAXPRIO) |
| return BCME_USAGE_ERROR; |
| aet.tid = tid; |
| |
| argv++; |
| if (!*argv) { |
| printf("error: missing address\n"); |
| return BCME_USAGE_ERROR; |
| } |
| |
| if (!wl_ether_atoe(*argv, &aet.ea)) { |
| printf("error: could not parse MAC address %s\n", *argv); |
| return BCME_USAGE_ERROR; |
| } |
| |
| return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet)); |
| } |
| |
| static int |
| wl_ampdu_send_delba(void *wl, cmd_t *cmd, char **argv) |
| { |
| char *param; |
| const char *cmdname = "ampdu_send_delba"; |
| struct ampdu_ea_tid aet; |
| uint8 tid; |
| |
| UNUSED_PARAMETER(cmd); |
| |
| if ((param = *++argv) == NULL) |
| return BCME_USAGE_ERROR; |
| |
| tid = atoi(param); |
| if (tid > MAXPRIO) |
| return BCME_USAGE_ERROR; |
| aet.tid = tid; |
| |
| argv++; |
| if (!*argv) { |
| printf("error: missing address\n"); |
| return BCME_USAGE_ERROR; |
| } |
| |
| if (!wl_ether_atoe(*argv, &aet.ea)) { |
| printf("error: could not parse MAC address %s\n", *argv); |
| return BCME_USAGE_ERROR; |
| } |
| |
| /* initiator (optional argument), 0 is recipient, 1 is originator */ |
| argv++; |
| if (*argv) { |
| aet.initiator = atoi(*argv); |
| } |
| else { |
| /* default is originator */ |
| aet.initiator = TRUE; |
| } |
| |
| return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet)); |
| } |