|
@@ -6102,303 +6102,6 @@ static int drv_cmd_get_linkspeed(hdd_adapter_t *adapter,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#ifdef FEATURE_NAPI
|
|
|
-/**
|
|
|
- * hdd_parse_napi() - helper functions to drv_cmd_napi
|
|
|
- * @str : source string to parse
|
|
|
- * @cmd : pointer to cmd part after parsing
|
|
|
- * @sub : pointer to subcmd part after parsing
|
|
|
- * @aux : pointer to optional aux part after parsing
|
|
|
- *
|
|
|
- * Example:
|
|
|
- * NAPI SCALE <n> +-- IN str
|
|
|
- * | | +------ OUT aux
|
|
|
- * | +------------ OUT subcmd
|
|
|
- * +----------------- OUT cmd
|
|
|
- *
|
|
|
- * Return: ==0: success; !=0: failure
|
|
|
- */
|
|
|
-static int hdd_parse_napi(char **str, char **cmd, char **sub, char **aux)
|
|
|
-{
|
|
|
- int rc;
|
|
|
- char *token, *lcmd = NULL, *lsub = NULL, *laux = NULL;
|
|
|
-
|
|
|
- NAPI_DEBUG("-->\n");
|
|
|
-
|
|
|
- token = strsep(str, " \t");
|
|
|
- if (NULL == token) {
|
|
|
- hdd_err("cannot parse cmd");
|
|
|
- goto parse_end;
|
|
|
- }
|
|
|
- lcmd = token;
|
|
|
-
|
|
|
- token = strsep(str, " \t");
|
|
|
- if (NULL == token) {
|
|
|
- hdd_err("cannot parse subcmd");
|
|
|
- goto parse_end;
|
|
|
- }
|
|
|
- lsub = token;
|
|
|
-
|
|
|
- token = strsep(str, " \t");
|
|
|
- if (NULL == token)
|
|
|
- hdd_warn("cannot parse aux\n");
|
|
|
- else
|
|
|
- laux = token;
|
|
|
-
|
|
|
-parse_end:
|
|
|
- if ((NULL == lcmd) || (NULL == lsub))
|
|
|
- rc = -EINVAL;
|
|
|
- else {
|
|
|
- rc = 0;
|
|
|
- *cmd = lcmd;
|
|
|
- *sub = lsub;
|
|
|
- if (NULL != aux)
|
|
|
- *aux = laux;
|
|
|
- }
|
|
|
- NAPI_DEBUG("<--[rc=%d]\n", rc);
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * hdd_parse_stats() - print NAPI stats into a buffer
|
|
|
- * @buf : buffer to write stats into
|
|
|
- * @max : "size of buffer"
|
|
|
- * @idp : NULL: all stats, otherwise, ptr to the NAPI instance
|
|
|
- * @napid: binary structure to retrieve the stats from
|
|
|
- *
|
|
|
- * Return: number of bytes written into the buffer
|
|
|
- */
|
|
|
-int hdd_napi_stats(char *buf,
|
|
|
- int max,
|
|
|
- char *indp,
|
|
|
- struct qca_napi_data *napid)
|
|
|
-{
|
|
|
- int n = 0;
|
|
|
- int i, j, k; /* NAPI, CPU, bucket indices */
|
|
|
- int from, to;
|
|
|
- struct qca_napi_info *napii;
|
|
|
- struct qca_napi_stat *napis;
|
|
|
-
|
|
|
- NAPI_DEBUG("-->\n");
|
|
|
-
|
|
|
- if (NULL == napid)
|
|
|
- return n;
|
|
|
- if (NULL == indp) {
|
|
|
- from = 0;
|
|
|
- to = CE_COUNT_MAX;
|
|
|
- } else {
|
|
|
- if (0 > kstrtoint(indp, 10, &to)) {
|
|
|
- from = 0;
|
|
|
- to = CE_COUNT_MAX;
|
|
|
- } else
|
|
|
- from = to;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = from; i < to; i++)
|
|
|
- if (napid->ce_map & (0x01 << i)) {
|
|
|
- napii = &(napid->napis[i]);
|
|
|
- for (j = 0; j < NR_CPUS; j++) {
|
|
|
- napis = &(napii->stats[j]);
|
|
|
- n += scnprintf(buf + n, max - n,
|
|
|
- "STATS: NAPI[%d] CPU: %d scheds: %d polls: %d completes: %d done: %d ",
|
|
|
- i, j,
|
|
|
- napis->napi_schedules,
|
|
|
- napis->napi_polls,
|
|
|
- napis->napi_completes,
|
|
|
- napis->napi_workdone);
|
|
|
-
|
|
|
- for (k = 0; k < QCA_NAPI_NUM_BUCKETS; k++) {
|
|
|
- n += scnprintf(
|
|
|
- buf + n, max - n,
|
|
|
- " %d",
|
|
|
- napis->napi_budget_uses[k]);
|
|
|
- }
|
|
|
- n += scnprintf(buf+n, max - n, "\n");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- NAPI_DEBUG("<--[n=%d]\n", n);
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * napi_set_scale() - sets the scale attribute in all NAPI entries
|
|
|
- * @sc : scale to set
|
|
|
- *
|
|
|
- * Return: void
|
|
|
- */
|
|
|
-static void napi_set_scale(uint8_t sc)
|
|
|
-{
|
|
|
- uint32_t i;
|
|
|
- struct qca_napi_data *napi_data;
|
|
|
-
|
|
|
- napi_data = hdd_napi_get_all();
|
|
|
- if (likely(NULL != napi_data))
|
|
|
- for (i = 0; i < CE_COUNT_MAX; i++)
|
|
|
- if (napi_data->ce_map & (0x01 << i))
|
|
|
- napi_data->napis[i].scale = sc;
|
|
|
-
|
|
|
- return;
|
|
|
-}
|
|
|
-/**
|
|
|
- * drv_cmd_napi() - processes NAPI commands
|
|
|
- * @adapter : net_device
|
|
|
- * @hdd_ctx : HDD context
|
|
|
- * @command : command string from user command (including "NAPI")
|
|
|
- * @command_len: length of command
|
|
|
- * @priv_data : ifr_data
|
|
|
- *
|
|
|
- * Commands supported:
|
|
|
- * NAPI ENABLE : enables NAPI administratively. Note that this may not
|
|
|
- * enable NAPI functionally, as some other conditions
|
|
|
- * may not have been satisfied yet
|
|
|
- * NAPI DISABLE : reverse operation of "enable"
|
|
|
- * NAPI STATUS : get global status of NAPI instances
|
|
|
- * NAPI STATS [<n>] : get the stats for a given NAPI instance
|
|
|
- * NAPI SCALE <n> : set the scale factor
|
|
|
- *
|
|
|
- * Return: 0: success; !0: failure
|
|
|
- */
|
|
|
-static int drv_cmd_napi(hdd_adapter_t *adapter,
|
|
|
- hdd_context_t *hdd_ctx,
|
|
|
- uint8_t *command,
|
|
|
- uint8_t command_len,
|
|
|
- hdd_priv_data_t *priv_data)
|
|
|
-{
|
|
|
- int rc = 0;
|
|
|
- int n, l;
|
|
|
- char *cmd = NULL, *subcmd = NULL, *aux = NULL;
|
|
|
- char *synopsis = "NAPI ENABLE\n"
|
|
|
- "NAPI DISABLE\n"
|
|
|
- "NAPI STATUS\n"
|
|
|
- "NAPI STATS [<n>] -- if no <n> then all\n"
|
|
|
- "NAPI SCALE <n> -- set the scale\n";
|
|
|
- char *reply = NULL;
|
|
|
-
|
|
|
- /* make a local copy, as strsep modifies the str in place */
|
|
|
- char *str = NULL;
|
|
|
-
|
|
|
- NAPI_DEBUG("-->\n");
|
|
|
-
|
|
|
- /**
|
|
|
- * NOTE TO MAINTAINER: from this point to the end of the function,
|
|
|
- * please do not return anywhere in the code except the very end
|
|
|
- * to avoid memory leakage (goto end_drv_napi instead)
|
|
|
- * or make sure that reply+str is freed
|
|
|
- */
|
|
|
- reply = kmalloc(MAX_USER_COMMAND_SIZE, GFP_KERNEL);
|
|
|
- if (NULL == reply) {
|
|
|
- hdd_err("could not allocate reply buffer");
|
|
|
- rc = -ENOMEM;
|
|
|
- goto end_drv_napi;
|
|
|
- }
|
|
|
-
|
|
|
- str = kmalloc(strlen(command) + 1, GFP_KERNEL);
|
|
|
- if (NULL == str) {
|
|
|
- hdd_err("could not allocate copy of input buffer");
|
|
|
- rc = -ENOMEM;
|
|
|
- goto end_drv_napi;
|
|
|
- }
|
|
|
-
|
|
|
- strlcpy(str, command, strlen(command) + 1);
|
|
|
- hdd_debug("parsing command into cmd=0x%p sub=0x%p aux=0x%p\n",
|
|
|
- cmd, subcmd, aux);
|
|
|
-
|
|
|
-
|
|
|
- rc = hdd_parse_napi(&str, &cmd, &subcmd, &aux);
|
|
|
-
|
|
|
- if (0 != rc) {
|
|
|
- const char *msg = "unknown or badly formatted cmd\n%s";
|
|
|
- l = QDF_MIN(MAX_USER_COMMAND_SIZE,
|
|
|
- strlen(msg)+strlen(synopsis));
|
|
|
- n = scnprintf(reply, l, msg, synopsis);
|
|
|
-
|
|
|
- if (copy_to_user(priv_data->buf, reply,
|
|
|
- QDF_MIN(priv_data->total_len, l)))
|
|
|
- hdd_err("failed to copy data to user buffer");
|
|
|
- hdd_debug("reply: %s", reply);
|
|
|
-
|
|
|
- rc = -EINVAL;
|
|
|
- } else {
|
|
|
- hdd_debug("cmd=(%s) subcmd=(%s) aux=(%s)\n",
|
|
|
- cmd, subcmd, aux);
|
|
|
- if (!strcmp(subcmd, "ENABLE"))
|
|
|
- hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)1);
|
|
|
- else if (!strcmp(subcmd, "DISABLE"))
|
|
|
- hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)0);
|
|
|
- else if (!strcmp(subcmd, "STATUS")) {
|
|
|
- int n = 0;
|
|
|
- uint32_t i;
|
|
|
- struct qca_napi_data *napi_data;
|
|
|
-
|
|
|
- napi_data = hdd_napi_get_all();
|
|
|
- if (unlikely(NULL == napi_data))
|
|
|
- goto status_end;
|
|
|
- n += scnprintf(reply+n, MAX_USER_COMMAND_SIZE - n,
|
|
|
- "NAPI state: 0x%08x map: 0x%08x\n",
|
|
|
- napi_data->state,
|
|
|
- napi_data->ce_map);
|
|
|
-
|
|
|
- for (i = 0; i < CE_COUNT_MAX; i++)
|
|
|
- if (napi_data->ce_map & (0x01 << i)) {
|
|
|
- n += scnprintf(
|
|
|
- reply + n,
|
|
|
- MAX_USER_COMMAND_SIZE - n,
|
|
|
- "#%d: id: %d, scale=%d\n",
|
|
|
- i,
|
|
|
- napi_data->napis[i].id,
|
|
|
- napi_data->napis[i].scale);
|
|
|
- }
|
|
|
- status_end:
|
|
|
- hdd_info("wlan: STATUS DATA:\n%s", reply);
|
|
|
- if (copy_to_user(priv_data->buf, reply,
|
|
|
- QDF_MIN(n, priv_data->total_len)))
|
|
|
- rc = -EINVAL;
|
|
|
- } else if (!strcmp(subcmd, "STATS")) {
|
|
|
- int n = 0;
|
|
|
- struct qca_napi_data *napi_data;
|
|
|
-
|
|
|
- napi_data = hdd_napi_get_all();
|
|
|
- if (NULL != napi_data) {
|
|
|
- n = hdd_napi_stats(reply, MAX_USER_COMMAND_SIZE,
|
|
|
- aux, napi_data);
|
|
|
- NAPI_DEBUG("STATS: returns %d\n", n);
|
|
|
- }
|
|
|
- if (n > 0) {
|
|
|
- if (copy_to_user(priv_data->buf, reply,
|
|
|
- QDF_MIN(priv_data->total_len,
|
|
|
- n)))
|
|
|
- rc = -EINVAL;
|
|
|
- hdd_info("wlan: STATS_DATA\n%s\n", reply);
|
|
|
- } else
|
|
|
- rc = -EINVAL;
|
|
|
- } else if (!strcmp(subcmd, "SCALE")) {
|
|
|
- if (NULL == aux) {
|
|
|
- rc = -EINVAL;
|
|
|
- hdd_err("wlan: SCALE cmd requires <n>");
|
|
|
- } else {
|
|
|
- uint8_t sc;
|
|
|
- rc = kstrtou8(aux, 10, &sc);
|
|
|
- if (rc) {
|
|
|
- hdd_err("wlan: bad scale (%s)", aux);
|
|
|
- rc = -EINVAL;
|
|
|
- } else
|
|
|
- napi_set_scale(sc);
|
|
|
- }
|
|
|
- } /* SCALE */
|
|
|
- }
|
|
|
-end_drv_napi:
|
|
|
- if (NULL != str)
|
|
|
- kfree(str);
|
|
|
- if (NULL != reply)
|
|
|
- kfree(reply);
|
|
|
-
|
|
|
- NAPI_DEBUG("<--[rc=%d]\n", rc);
|
|
|
- return rc;
|
|
|
-}
|
|
|
-#endif /* FEATURE_NAPI */
|
|
|
-
|
|
|
/**
|
|
|
* hdd_set_rx_filter() - set RX filter
|
|
|
* @adapter: Pointer to adapter
|
|
@@ -7172,9 +6875,6 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = {
|
|
|
#endif
|
|
|
{"RSSI", drv_cmd_get_rssi},
|
|
|
{"LINKSPEED", drv_cmd_get_linkspeed},
|
|
|
-#ifdef FEATURE_NAPI
|
|
|
- {"NAPI", drv_cmd_napi},
|
|
|
-#endif /* FEATURE_NAPI */
|
|
|
{"RXFILTER-REMOVE", drv_cmd_rx_filter_remove},
|
|
|
{"RXFILTER-ADD", drv_cmd_rx_filter_add},
|
|
|
{"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel},
|