1 | // SPDX-License-Identifier: ISC |
2 | /* |
3 | * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. |
4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
5 | */ |
6 | |
7 | #include <linux/etherdevice.h> |
8 | #include <linux/pci.h> |
9 | #include <linux/rtnetlink.h> |
10 | #include <net/cfg80211.h> |
11 | |
12 | #include "wil6210.h" |
13 | |
14 | static int |
15 | wil_ethtoolops_get_coalesce(struct net_device *ndev, |
16 | struct ethtool_coalesce *cp, |
17 | struct kernel_ethtool_coalesce *kernel_coal, |
18 | struct netlink_ext_ack *extack) |
19 | { |
20 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
21 | u32 tx_itr_en, tx_itr_val = 0; |
22 | u32 rx_itr_en, rx_itr_val = 0; |
23 | int ret; |
24 | |
25 | mutex_lock(&wil->mutex); |
26 | wil_dbg_misc(wil, "ethtoolops_get_coalesce\n" ); |
27 | |
28 | ret = wil_pm_runtime_get(wil); |
29 | if (ret < 0) |
30 | goto out; |
31 | |
32 | tx_itr_en = wil_r(wil, RGF_DMA_ITR_TX_CNT_CTL); |
33 | if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN) |
34 | tx_itr_val = wil_r(wil, RGF_DMA_ITR_TX_CNT_TRSH); |
35 | |
36 | rx_itr_en = wil_r(wil, RGF_DMA_ITR_RX_CNT_CTL); |
37 | if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN) |
38 | rx_itr_val = wil_r(wil, RGF_DMA_ITR_RX_CNT_TRSH); |
39 | |
40 | wil_pm_runtime_put(wil); |
41 | |
42 | cp->tx_coalesce_usecs = tx_itr_val; |
43 | cp->rx_coalesce_usecs = rx_itr_val; |
44 | ret = 0; |
45 | |
46 | out: |
47 | mutex_unlock(lock: &wil->mutex); |
48 | return ret; |
49 | } |
50 | |
51 | static int |
52 | wil_ethtoolops_set_coalesce(struct net_device *ndev, |
53 | struct ethtool_coalesce *cp, |
54 | struct kernel_ethtool_coalesce *kernel_coal, |
55 | struct netlink_ext_ack *extack) |
56 | { |
57 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
58 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
59 | int ret; |
60 | |
61 | mutex_lock(&wil->mutex); |
62 | wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n" , |
63 | cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); |
64 | |
65 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { |
66 | wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n" ); |
67 | ret = -EINVAL; |
68 | goto out; |
69 | } |
70 | |
71 | /* only @rx_coalesce_usecs and @tx_coalesce_usecs supported, |
72 | * ignore other parameters |
73 | */ |
74 | |
75 | if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX || |
76 | cp->tx_coalesce_usecs > WIL6210_ITR_TRSH_MAX) |
77 | goto out_bad; |
78 | |
79 | wil->tx_max_burst_duration = cp->tx_coalesce_usecs; |
80 | wil->rx_max_burst_duration = cp->rx_coalesce_usecs; |
81 | |
82 | ret = wil_pm_runtime_get(wil); |
83 | if (ret < 0) |
84 | goto out; |
85 | |
86 | wil->txrx_ops.configure_interrupt_moderation(wil); |
87 | |
88 | wil_pm_runtime_put(wil); |
89 | ret = 0; |
90 | |
91 | out: |
92 | mutex_unlock(lock: &wil->mutex); |
93 | return ret; |
94 | |
95 | out_bad: |
96 | wil_dbg_misc(wil, "Unsupported coalescing params. Raw command:\n" ); |
97 | print_hex_dump_debug("DBG[MISC] coal " , DUMP_PREFIX_OFFSET, 16, 4, |
98 | cp, sizeof(*cp), false); |
99 | mutex_unlock(lock: &wil->mutex); |
100 | return -EINVAL; |
101 | } |
102 | |
103 | static const struct ethtool_ops wil_ethtool_ops = { |
104 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS, |
105 | .get_drvinfo = cfg80211_get_drvinfo, |
106 | .get_coalesce = wil_ethtoolops_get_coalesce, |
107 | .set_coalesce = wil_ethtoolops_set_coalesce, |
108 | }; |
109 | |
110 | void wil_set_ethtoolops(struct net_device *ndev) |
111 | { |
112 | ndev->ethtool_ops = &wil_ethtool_ops; |
113 | } |
114 | |