linux_dsm_epyc7002/drivers/net/wireless/ath/wil6210/ethtool.c
Vladimir Kondratiev 78366f69be wil6210: add advanced interrupt moderation
Add advanced interrupt moderation support available since "Sparrow B0".
Legacy interrupt moderation used only one counter to moderate tx, rx,
and misc interrupts.
Advanced interrupt moderation bypasses misc, and handles separately tx
and rx interrupts. In addition it has two timers for each interrupt type.
Max burst duration timer which defines how long to postpone interrupt after
first event (receive event for rx and tx complete event for tx), and
interframe timeout which defines how to determine the end of the burst and
issue interrupt even if the first timer still pending.
Capabilities flags in wil_priv is set on initialization according to
HW. The rest of the code checks for advanced interrupt capability bit
in capabilities flags field.
Debugfs is split accordingly: "legacy" interrupt moderation remains
unchanged, new debugs files added for advanced interrupt moderation
support.
Module params are aligned to support advanced interrupt moderation
(tx & rx). When not available (for legacy interrupt moderation) will
use only rx configuration; Tx configuration will be ignored in this
case.

Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
2015-01-15 14:31:38 +02:00

126 lines
3.6 KiB
C

/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
#include <net/cfg80211.h>
#include "wil6210.h"
static int wil_ethtoolops_begin(struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
mutex_lock(&wil->mutex);
wil_dbg_misc(wil, "%s()\n", __func__);
return 0;
}
static void wil_ethtoolops_complete(struct net_device *ndev)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
wil_dbg_misc(wil, "%s()\n", __func__);
mutex_unlock(&wil->mutex);
}
static int wil_ethtoolops_get_coalesce(struct net_device *ndev,
struct ethtool_coalesce *cp)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
u32 tx_itr_en, tx_itr_val = 0;
u32 rx_itr_en, rx_itr_val = 0;
wil_dbg_misc(wil, "%s()\n", __func__);
if (test_bit(hw_capability_advanced_itr_moderation,
wil->hw_capabilities)) {
tx_itr_en = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL));
if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN)
tx_itr_val =
ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH));
rx_itr_en = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL));
if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN)
rx_itr_val =
ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH));
} else {
rx_itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
if (rx_itr_en & BIT_DMA_ITR_CNT_CRL_EN)
rx_itr_val = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
}
cp->tx_coalesce_usecs = tx_itr_val;
cp->rx_coalesce_usecs = rx_itr_val;
return 0;
}
static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
struct ethtool_coalesce *cp)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
wil_dbg_misc(wil, "%s(rx %d usec, tx %d usec)\n", __func__,
cp->rx_coalesce_usecs, cp->tx_coalesce_usecs);
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n");
return -EINVAL;
}
/* only @rx_coalesce_usecs and @tx_coalesce_usecs supported,
* ignore other parameters
*/
if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX ||
cp->tx_coalesce_usecs > WIL6210_ITR_TRSH_MAX)
goto out_bad;
wil->tx_max_burst_duration = cp->tx_coalesce_usecs;
wil->rx_max_burst_duration = cp->rx_coalesce_usecs;
wil_configure_interrupt_moderation(wil);
return 0;
out_bad:
wil_dbg_misc(wil, "Unsupported coalescing params. Raw command:\n");
print_hex_dump_debug("DBG[MISC] coal ", DUMP_PREFIX_OFFSET, 16, 4,
cp, sizeof(*cp), false);
return -EINVAL;
}
static const struct ethtool_ops wil_ethtool_ops = {
.begin = wil_ethtoolops_begin,
.complete = wil_ethtoolops_complete,
.get_drvinfo = cfg80211_get_drvinfo,
.get_coalesce = wil_ethtoolops_get_coalesce,
.set_coalesce = wil_ethtoolops_set_coalesce,
};
void wil_set_ethtoolops(struct net_device *ndev)
{
ndev->ethtool_ops = &wil_ethtool_ops;
}