1d45d8979SChristina Jacob // SPDX-License-Identifier: GPL-2.0
2cb0e3ec4SSunil Goutham /* Marvell RVU Ethernet driver
3d45d8979SChristina Jacob *
4cb0e3ec4SSunil Goutham * Copyright (C) 2020 Marvell.
5d45d8979SChristina Jacob *
6d45d8979SChristina Jacob */
7d45d8979SChristina Jacob
8d45d8979SChristina Jacob #include <linux/pci.h>
9d45d8979SChristina Jacob #include <linux/ethtool.h>
10d45d8979SChristina Jacob #include <linux/stddef.h>
11d45d8979SChristina Jacob #include <linux/etherdevice.h>
12d45d8979SChristina Jacob #include <linux/log2.h>
13c9c12d33SAleksey Makarov #include <linux/net_tstamp.h>
141a50280cSChristina Jacob #include <linux/linkmode.h>
15d45d8979SChristina Jacob
16d45d8979SChristina Jacob #include "otx2_common.h"
17c9c12d33SAleksey Makarov #include "otx2_ptp.h"
18d45d8979SChristina Jacob
19ef6c8da7SGeetha sowjanya #define DRV_NAME "rvu-nicpf"
20ef6c8da7SGeetha sowjanya #define DRV_VF_NAME "rvu-nicvf"
21d45d8979SChristina Jacob
22d45d8979SChristina Jacob struct otx2_stat {
23d45d8979SChristina Jacob char name[ETH_GSTRING_LEN];
24d45d8979SChristina Jacob unsigned int index;
25d45d8979SChristina Jacob };
26d45d8979SChristina Jacob
27d45d8979SChristina Jacob /* HW device stats */
28d45d8979SChristina Jacob #define OTX2_DEV_STAT(stat) { \
29d45d8979SChristina Jacob .name = #stat, \
30d45d8979SChristina Jacob .index = offsetof(struct otx2_dev_stats, stat) / sizeof(u64), \
31d45d8979SChristina Jacob }
32d45d8979SChristina Jacob
331a50280cSChristina Jacob enum link_mode {
341a50280cSChristina Jacob OTX2_MODE_SUPPORTED,
351a50280cSChristina Jacob OTX2_MODE_ADVERTISED
361a50280cSChristina Jacob };
371a50280cSChristina Jacob
38d45d8979SChristina Jacob static const struct otx2_stat otx2_dev_stats[] = {
39d45d8979SChristina Jacob OTX2_DEV_STAT(rx_ucast_frames),
40d45d8979SChristina Jacob OTX2_DEV_STAT(rx_bcast_frames),
41d45d8979SChristina Jacob OTX2_DEV_STAT(rx_mcast_frames),
42d45d8979SChristina Jacob
43d45d8979SChristina Jacob OTX2_DEV_STAT(tx_ucast_frames),
44d45d8979SChristina Jacob OTX2_DEV_STAT(tx_bcast_frames),
45d45d8979SChristina Jacob OTX2_DEV_STAT(tx_mcast_frames),
46d45d8979SChristina Jacob };
47d45d8979SChristina Jacob
48d45d8979SChristina Jacob /* Driver level stats */
49d45d8979SChristina Jacob #define OTX2_DRV_STAT(stat) { \
50d45d8979SChristina Jacob .name = #stat, \
51d45d8979SChristina Jacob .index = offsetof(struct otx2_drv_stats, stat) / sizeof(atomic_t), \
52d45d8979SChristina Jacob }
53d45d8979SChristina Jacob
54d45d8979SChristina Jacob static const struct otx2_stat otx2_drv_stats[] = {
55d45d8979SChristina Jacob OTX2_DRV_STAT(rx_fcs_errs),
56d45d8979SChristina Jacob OTX2_DRV_STAT(rx_oversize_errs),
57d45d8979SChristina Jacob OTX2_DRV_STAT(rx_undersize_errs),
58d45d8979SChristina Jacob OTX2_DRV_STAT(rx_csum_errs),
59d45d8979SChristina Jacob OTX2_DRV_STAT(rx_len_errs),
60d45d8979SChristina Jacob OTX2_DRV_STAT(rx_other_errs),
61d45d8979SChristina Jacob };
62d45d8979SChristina Jacob
63d45d8979SChristina Jacob static const struct otx2_stat otx2_queue_stats[] = {
64d45d8979SChristina Jacob { "bytes", 0 },
65d45d8979SChristina Jacob { "frames", 1 },
66d45d8979SChristina Jacob };
67d45d8979SChristina Jacob
68d45d8979SChristina Jacob static const unsigned int otx2_n_dev_stats = ARRAY_SIZE(otx2_dev_stats);
69d45d8979SChristina Jacob static const unsigned int otx2_n_drv_stats = ARRAY_SIZE(otx2_drv_stats);
70d45d8979SChristina Jacob static const unsigned int otx2_n_queue_stats = ARRAY_SIZE(otx2_queue_stats);
71d45d8979SChristina Jacob
72d0cf9503SChristina Jacob static struct cgx_fw_data *otx2_get_fwdata(struct otx2_nic *pfvf);
73d0cf9503SChristina Jacob
otx2_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)74d45d8979SChristina Jacob static void otx2_get_drvinfo(struct net_device *netdev,
75d45d8979SChristina Jacob struct ethtool_drvinfo *info)
76d45d8979SChristina Jacob {
77d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
78d45d8979SChristina Jacob
79f029c781SWolfram Sang strscpy(info->driver, DRV_NAME, sizeof(info->driver));
80f029c781SWolfram Sang strscpy(info->bus_info, pci_name(pfvf->pdev), sizeof(info->bus_info));
81d45d8979SChristina Jacob }
82d45d8979SChristina Jacob
otx2_get_qset_strings(struct otx2_nic * pfvf,u8 ** data,int qset)83d45d8979SChristina Jacob static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset)
84d45d8979SChristina Jacob {
85d45d8979SChristina Jacob int start_qidx = qset * pfvf->hw.rx_queues;
86d45d8979SChristina Jacob int qidx, stats;
87d45d8979SChristina Jacob
88d45d8979SChristina Jacob for (qidx = 0; qidx < pfvf->hw.rx_queues; qidx++) {
89d45d8979SChristina Jacob for (stats = 0; stats < otx2_n_queue_stats; stats++) {
90d45d8979SChristina Jacob sprintf(*data, "rxq%d: %s", qidx + start_qidx,
91d45d8979SChristina Jacob otx2_queue_stats[stats].name);
92d45d8979SChristina Jacob *data += ETH_GSTRING_LEN;
93d45d8979SChristina Jacob }
94d45d8979SChristina Jacob }
956cebb6a4SHariprasad Kelam
966cebb6a4SHariprasad Kelam for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
97d45d8979SChristina Jacob for (stats = 0; stats < otx2_n_queue_stats; stats++) {
986cebb6a4SHariprasad Kelam if (qidx >= pfvf->hw.non_qos_queues)
996cebb6a4SHariprasad Kelam sprintf(*data, "txq_qos%d: %s",
1006cebb6a4SHariprasad Kelam qidx + start_qidx - pfvf->hw.non_qos_queues,
1016cebb6a4SHariprasad Kelam otx2_queue_stats[stats].name);
1026cebb6a4SHariprasad Kelam else
103d45d8979SChristina Jacob sprintf(*data, "txq%d: %s", qidx + start_qidx,
104d45d8979SChristina Jacob otx2_queue_stats[stats].name);
105d45d8979SChristina Jacob *data += ETH_GSTRING_LEN;
106d45d8979SChristina Jacob }
107d45d8979SChristina Jacob }
108d45d8979SChristina Jacob }
109d45d8979SChristina Jacob
otx2_get_strings(struct net_device * netdev,u32 sset,u8 * data)110d45d8979SChristina Jacob static void otx2_get_strings(struct net_device *netdev, u32 sset, u8 *data)
111d45d8979SChristina Jacob {
112d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
113d45d8979SChristina Jacob int stats;
114d45d8979SChristina Jacob
115d45d8979SChristina Jacob if (sset != ETH_SS_STATS)
116d45d8979SChristina Jacob return;
117d45d8979SChristina Jacob
118d45d8979SChristina Jacob for (stats = 0; stats < otx2_n_dev_stats; stats++) {
119d45d8979SChristina Jacob memcpy(data, otx2_dev_stats[stats].name, ETH_GSTRING_LEN);
120d45d8979SChristina Jacob data += ETH_GSTRING_LEN;
121d45d8979SChristina Jacob }
122d45d8979SChristina Jacob
123d45d8979SChristina Jacob for (stats = 0; stats < otx2_n_drv_stats; stats++) {
124d45d8979SChristina Jacob memcpy(data, otx2_drv_stats[stats].name, ETH_GSTRING_LEN);
125d45d8979SChristina Jacob data += ETH_GSTRING_LEN;
126d45d8979SChristina Jacob }
127d45d8979SChristina Jacob
128d45d8979SChristina Jacob otx2_get_qset_strings(pfvf, &data, 0);
129d45d8979SChristina Jacob
13063f85c40SHariprasad Kelam if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) {
131d45d8979SChristina Jacob for (stats = 0; stats < CGX_RX_STATS_COUNT; stats++) {
132d45d8979SChristina Jacob sprintf(data, "cgx_rxstat%d: ", stats);
133d45d8979SChristina Jacob data += ETH_GSTRING_LEN;
134d45d8979SChristina Jacob }
135d45d8979SChristina Jacob
136d45d8979SChristina Jacob for (stats = 0; stats < CGX_TX_STATS_COUNT; stats++) {
137d45d8979SChristina Jacob sprintf(data, "cgx_txstat%d: ", stats);
138d45d8979SChristina Jacob data += ETH_GSTRING_LEN;
139d45d8979SChristina Jacob }
14063f85c40SHariprasad Kelam }
141d45d8979SChristina Jacob
142d45d8979SChristina Jacob strcpy(data, "reset_count");
143d45d8979SChristina Jacob data += ETH_GSTRING_LEN;
144d0cf9503SChristina Jacob sprintf(data, "Fec Corrected Errors: ");
145d0cf9503SChristina Jacob data += ETH_GSTRING_LEN;
146d0cf9503SChristina Jacob sprintf(data, "Fec Uncorrected Errors: ");
147d0cf9503SChristina Jacob data += ETH_GSTRING_LEN;
148d45d8979SChristina Jacob }
149d45d8979SChristina Jacob
otx2_get_qset_stats(struct otx2_nic * pfvf,struct ethtool_stats * stats,u64 ** data)150d45d8979SChristina Jacob static void otx2_get_qset_stats(struct otx2_nic *pfvf,
151d45d8979SChristina Jacob struct ethtool_stats *stats, u64 **data)
152d45d8979SChristina Jacob {
153d45d8979SChristina Jacob int stat, qidx;
154d45d8979SChristina Jacob
155d45d8979SChristina Jacob if (!pfvf)
156d45d8979SChristina Jacob return;
157d45d8979SChristina Jacob for (qidx = 0; qidx < pfvf->hw.rx_queues; qidx++) {
158d45d8979SChristina Jacob if (!otx2_update_rq_stats(pfvf, qidx)) {
159d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_queue_stats; stat++)
160d45d8979SChristina Jacob *((*data)++) = 0;
161d45d8979SChristina Jacob continue;
162d45d8979SChristina Jacob }
163d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_queue_stats; stat++)
164d45d8979SChristina Jacob *((*data)++) = ((u64 *)&pfvf->qset.rq[qidx].stats)
165d45d8979SChristina Jacob [otx2_queue_stats[stat].index];
166d45d8979SChristina Jacob }
167d45d8979SChristina Jacob
1686cebb6a4SHariprasad Kelam for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
169d45d8979SChristina Jacob if (!otx2_update_sq_stats(pfvf, qidx)) {
170d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_queue_stats; stat++)
171d45d8979SChristina Jacob *((*data)++) = 0;
172d45d8979SChristina Jacob continue;
173d45d8979SChristina Jacob }
174d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_queue_stats; stat++)
175d45d8979SChristina Jacob *((*data)++) = ((u64 *)&pfvf->qset.sq[qidx].stats)
176d45d8979SChristina Jacob [otx2_queue_stats[stat].index];
177d45d8979SChristina Jacob }
178d45d8979SChristina Jacob }
179d45d8979SChristina Jacob
otx2_get_phy_fec_stats(struct otx2_nic * pfvf)180d0cf9503SChristina Jacob static int otx2_get_phy_fec_stats(struct otx2_nic *pfvf)
181d0cf9503SChristina Jacob {
182d0cf9503SChristina Jacob struct msg_req *req;
183d0cf9503SChristina Jacob int rc = -ENOMEM;
184d0cf9503SChristina Jacob
185d0cf9503SChristina Jacob mutex_lock(&pfvf->mbox.lock);
186d0cf9503SChristina Jacob req = otx2_mbox_alloc_msg_cgx_get_phy_fec_stats(&pfvf->mbox);
187d0cf9503SChristina Jacob if (!req)
188d0cf9503SChristina Jacob goto end;
189d0cf9503SChristina Jacob
190d0cf9503SChristina Jacob if (!otx2_sync_mbox_msg(&pfvf->mbox))
191d0cf9503SChristina Jacob rc = 0;
192d0cf9503SChristina Jacob end:
193d0cf9503SChristina Jacob mutex_unlock(&pfvf->mbox.lock);
194d0cf9503SChristina Jacob return rc;
195d0cf9503SChristina Jacob }
196d0cf9503SChristina Jacob
197d45d8979SChristina Jacob /* Get device and per queue statistics */
otx2_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)198d45d8979SChristina Jacob static void otx2_get_ethtool_stats(struct net_device *netdev,
199d45d8979SChristina Jacob struct ethtool_stats *stats, u64 *data)
200d45d8979SChristina Jacob {
201d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
202d0cf9503SChristina Jacob u64 fec_corr_blks, fec_uncorr_blks;
203d0cf9503SChristina Jacob struct cgx_fw_data *rsp;
204d45d8979SChristina Jacob int stat;
205d45d8979SChristina Jacob
206d45d8979SChristina Jacob otx2_get_dev_stats(pfvf);
207d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_dev_stats; stat++)
208d45d8979SChristina Jacob *(data++) = ((u64 *)&pfvf->hw.dev_stats)
209d45d8979SChristina Jacob [otx2_dev_stats[stat].index];
210d45d8979SChristina Jacob
211d45d8979SChristina Jacob for (stat = 0; stat < otx2_n_drv_stats; stat++)
212d45d8979SChristina Jacob *(data++) = atomic_read(&((atomic_t *)&pfvf->hw.drv_stats)
213d45d8979SChristina Jacob [otx2_drv_stats[stat].index]);
214d45d8979SChristina Jacob
215d45d8979SChristina Jacob otx2_get_qset_stats(pfvf, stats, &data);
21663f85c40SHariprasad Kelam
21763f85c40SHariprasad Kelam if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) {
218d45d8979SChristina Jacob otx2_update_lmac_stats(pfvf);
219d45d8979SChristina Jacob for (stat = 0; stat < CGX_RX_STATS_COUNT; stat++)
220d45d8979SChristina Jacob *(data++) = pfvf->hw.cgx_rx_stats[stat];
221d45d8979SChristina Jacob for (stat = 0; stat < CGX_TX_STATS_COUNT; stat++)
222d45d8979SChristina Jacob *(data++) = pfvf->hw.cgx_tx_stats[stat];
22363f85c40SHariprasad Kelam }
22463f85c40SHariprasad Kelam
225d45d8979SChristina Jacob *(data++) = pfvf->reset_count;
226d0cf9503SChristina Jacob
227d0cf9503SChristina Jacob fec_corr_blks = pfvf->hw.cgx_fec_corr_blks;
228d0cf9503SChristina Jacob fec_uncorr_blks = pfvf->hw.cgx_fec_uncorr_blks;
229d0cf9503SChristina Jacob
230d0cf9503SChristina Jacob rsp = otx2_get_fwdata(pfvf);
231d0cf9503SChristina Jacob if (!IS_ERR(rsp) && rsp->fwdata.phy.misc.has_fec_stats &&
232d0cf9503SChristina Jacob !otx2_get_phy_fec_stats(pfvf)) {
233d0cf9503SChristina Jacob /* Fetch fwdata again because it's been recently populated with
234d0cf9503SChristina Jacob * latest PHY FEC stats.
235d0cf9503SChristina Jacob */
236d0cf9503SChristina Jacob rsp = otx2_get_fwdata(pfvf);
237d0cf9503SChristina Jacob if (!IS_ERR(rsp)) {
238d0cf9503SChristina Jacob struct fec_stats_s *p = &rsp->fwdata.phy.fec_stats;
239d0cf9503SChristina Jacob
240d0cf9503SChristina Jacob if (pfvf->linfo.fec == OTX2_FEC_BASER) {
241d0cf9503SChristina Jacob fec_corr_blks = p->brfec_corr_blks;
242d0cf9503SChristina Jacob fec_uncorr_blks = p->brfec_uncorr_blks;
243d0cf9503SChristina Jacob } else {
244d0cf9503SChristina Jacob fec_corr_blks = p->rsfec_corr_cws;
245d0cf9503SChristina Jacob fec_uncorr_blks = p->rsfec_uncorr_cws;
246d0cf9503SChristina Jacob }
247d0cf9503SChristina Jacob }
248d0cf9503SChristina Jacob }
249d0cf9503SChristina Jacob
250d0cf9503SChristina Jacob *(data++) = fec_corr_blks;
251d0cf9503SChristina Jacob *(data++) = fec_uncorr_blks;
252d45d8979SChristina Jacob }
253d45d8979SChristina Jacob
otx2_get_sset_count(struct net_device * netdev,int sset)254d45d8979SChristina Jacob static int otx2_get_sset_count(struct net_device *netdev, int sset)
255d45d8979SChristina Jacob {
256d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
25763f85c40SHariprasad Kelam int qstats_count, mac_stats = 0;
258d45d8979SChristina Jacob
259d45d8979SChristina Jacob if (sset != ETH_SS_STATS)
260d45d8979SChristina Jacob return -EINVAL;
261d45d8979SChristina Jacob
262d45d8979SChristina Jacob qstats_count = otx2_n_queue_stats *
2636cebb6a4SHariprasad Kelam (pfvf->hw.rx_queues + otx2_get_total_tx_queues(pfvf));
26463f85c40SHariprasad Kelam if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag))
26563f85c40SHariprasad Kelam mac_stats = CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT;
266d0cf9503SChristina Jacob otx2_update_lmac_fec_stats(pfvf);
267d45d8979SChristina Jacob
268d45d8979SChristina Jacob return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count +
26963f85c40SHariprasad Kelam mac_stats + OTX2_FEC_STATS_CNT + 1;
270d45d8979SChristina Jacob }
271d45d8979SChristina Jacob
272d45d8979SChristina Jacob /* Get no of queues device supports and current queue count */
otx2_get_channels(struct net_device * dev,struct ethtool_channels * channel)273d45d8979SChristina Jacob static void otx2_get_channels(struct net_device *dev,
274d45d8979SChristina Jacob struct ethtool_channels *channel)
275d45d8979SChristina Jacob {
276d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(dev);
277d45d8979SChristina Jacob
278d45d8979SChristina Jacob channel->max_rx = pfvf->hw.max_queues;
279d45d8979SChristina Jacob channel->max_tx = pfvf->hw.max_queues;
280d45d8979SChristina Jacob
281d45d8979SChristina Jacob channel->rx_count = pfvf->hw.rx_queues;
282d45d8979SChristina Jacob channel->tx_count = pfvf->hw.tx_queues;
283d45d8979SChristina Jacob }
284d45d8979SChristina Jacob
285d45d8979SChristina Jacob /* Set no of Tx, Rx queues to be used */
otx2_set_channels(struct net_device * dev,struct ethtool_channels * channel)286d45d8979SChristina Jacob static int otx2_set_channels(struct net_device *dev,
287d45d8979SChristina Jacob struct ethtool_channels *channel)
288d45d8979SChristina Jacob {
289d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(dev);
290d45d8979SChristina Jacob bool if_up = netif_running(dev);
2916cebb6a4SHariprasad Kelam int err, qos_txqs;
292d45d8979SChristina Jacob
293d45d8979SChristina Jacob if (!channel->rx_count || !channel->tx_count)
294d45d8979SChristina Jacob return -EINVAL;
295d45d8979SChristina Jacob
29668fbff68SSubbaraya Sundeep if (bitmap_weight(&pfvf->rq_bmap, pfvf->hw.rx_queues) > 1) {
29768fbff68SSubbaraya Sundeep netdev_err(dev,
29868fbff68SSubbaraya Sundeep "Receive queues are in use by TC police action\n");
29968fbff68SSubbaraya Sundeep return -EINVAL;
30068fbff68SSubbaraya Sundeep }
30168fbff68SSubbaraya Sundeep
302d45d8979SChristina Jacob if (if_up)
30305c22b54STomasz Duszynski dev->netdev_ops->ndo_stop(dev);
304d45d8979SChristina Jacob
3056cebb6a4SHariprasad Kelam qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
3066cebb6a4SHariprasad Kelam OTX2_QOS_MAX_LEAF_NODES);
3076cebb6a4SHariprasad Kelam
3086cebb6a4SHariprasad Kelam err = otx2_set_real_num_queues(dev, channel->tx_count + qos_txqs,
309d45d8979SChristina Jacob channel->rx_count);
310d45d8979SChristina Jacob if (err)
31169f0aeb1SGeetha sowjanya return err;
312d45d8979SChristina Jacob
313d45d8979SChristina Jacob pfvf->hw.rx_queues = channel->rx_count;
314d45d8979SChristina Jacob pfvf->hw.tx_queues = channel->tx_count;
3156cebb6a4SHariprasad Kelam if (pfvf->xdp_prog)
3166cebb6a4SHariprasad Kelam pfvf->hw.xdp_queues = channel->rx_count;
317d45d8979SChristina Jacob
318d45d8979SChristina Jacob if (if_up)
31969f0aeb1SGeetha sowjanya err = dev->netdev_ops->ndo_open(dev);
320d45d8979SChristina Jacob
321d45d8979SChristina Jacob netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
322d45d8979SChristina Jacob pfvf->hw.tx_queues, pfvf->hw.rx_queues);
323d45d8979SChristina Jacob
324d45d8979SChristina Jacob return err;
325d45d8979SChristina Jacob }
326d45d8979SChristina Jacob
otx2_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)32775f36270SGeetha sowjanya static void otx2_get_pauseparam(struct net_device *netdev,
32875f36270SGeetha sowjanya struct ethtool_pauseparam *pause)
32975f36270SGeetha sowjanya {
33075f36270SGeetha sowjanya struct otx2_nic *pfvf = netdev_priv(netdev);
33175f36270SGeetha sowjanya struct cgx_pause_frm_cfg *req, *rsp;
33275f36270SGeetha sowjanya
33305c22b54STomasz Duszynski if (is_otx2_lbkvf(pfvf->pdev))
33405c22b54STomasz Duszynski return;
33505c22b54STomasz Duszynski
3366ddf005fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock);
33775f36270SGeetha sowjanya req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox);
3386ddf005fSSubbaraya Sundeep if (!req) {
3396ddf005fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock);
34075f36270SGeetha sowjanya return;
3416ddf005fSSubbaraya Sundeep }
34275f36270SGeetha sowjanya
34375f36270SGeetha sowjanya if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
34475f36270SGeetha sowjanya rsp = (struct cgx_pause_frm_cfg *)
34575f36270SGeetha sowjanya otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
346*c0f64fd7SDipendra Khadka if (IS_ERR(rsp)) {
347*c0f64fd7SDipendra Khadka mutex_unlock(&pfvf->mbox.lock);
348*c0f64fd7SDipendra Khadka return;
349*c0f64fd7SDipendra Khadka }
350*c0f64fd7SDipendra Khadka
35175f36270SGeetha sowjanya pause->rx_pause = rsp->rx_pause;
35275f36270SGeetha sowjanya pause->tx_pause = rsp->tx_pause;
35375f36270SGeetha sowjanya }
3546ddf005fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock);
35575f36270SGeetha sowjanya }
35675f36270SGeetha sowjanya
otx2_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)35775f36270SGeetha sowjanya static int otx2_set_pauseparam(struct net_device *netdev,
35875f36270SGeetha sowjanya struct ethtool_pauseparam *pause)
35975f36270SGeetha sowjanya {
36075f36270SGeetha sowjanya struct otx2_nic *pfvf = netdev_priv(netdev);
36175f36270SGeetha sowjanya
36275f36270SGeetha sowjanya if (pause->autoneg)
36375f36270SGeetha sowjanya return -EOPNOTSUPP;
36475f36270SGeetha sowjanya
36505c22b54STomasz Duszynski if (is_otx2_lbkvf(pfvf->pdev))
36605c22b54STomasz Duszynski return -EOPNOTSUPP;
36705c22b54STomasz Duszynski
36875f36270SGeetha sowjanya if (pause->rx_pause)
36975f36270SGeetha sowjanya pfvf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED;
37075f36270SGeetha sowjanya else
37175f36270SGeetha sowjanya pfvf->flags &= ~OTX2_FLAG_RX_PAUSE_ENABLED;
37275f36270SGeetha sowjanya
37375f36270SGeetha sowjanya if (pause->tx_pause)
37475f36270SGeetha sowjanya pfvf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED;
37575f36270SGeetha sowjanya else
37675f36270SGeetha sowjanya pfvf->flags &= ~OTX2_FLAG_TX_PAUSE_ENABLED;
37775f36270SGeetha sowjanya
37875f36270SGeetha sowjanya return otx2_config_pause_frm(pfvf);
37975f36270SGeetha sowjanya }
38075f36270SGeetha sowjanya
otx2_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)381d45d8979SChristina Jacob static void otx2_get_ringparam(struct net_device *netdev,
38274624944SHao Chen struct ethtool_ringparam *ring,
38374624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
38474624944SHao Chen struct netlink_ext_ack *extack)
385d45d8979SChristina Jacob {
386d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
387d45d8979SChristina Jacob struct otx2_qset *qs = &pfvf->qset;
388d45d8979SChristina Jacob
389d45d8979SChristina Jacob ring->rx_max_pending = Q_COUNT(Q_SIZE_MAX);
390d45d8979SChristina Jacob ring->rx_pending = qs->rqe_cnt ? qs->rqe_cnt : Q_COUNT(Q_SIZE_256);
391d45d8979SChristina Jacob ring->tx_max_pending = Q_COUNT(Q_SIZE_MAX);
392d45d8979SChristina Jacob ring->tx_pending = qs->sqe_cnt ? qs->sqe_cnt : Q_COUNT(Q_SIZE_4K);
393a989eb66SSubbaraya Sundeep kernel_ring->rx_buf_len = pfvf->hw.rbuf_len;
39468258596SSubbaraya Sundeep kernel_ring->cqe_size = pfvf->hw.xqe_size;
395d45d8979SChristina Jacob }
396d45d8979SChristina Jacob
otx2_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)397d45d8979SChristina Jacob static int otx2_set_ringparam(struct net_device *netdev,
39874624944SHao Chen struct ethtool_ringparam *ring,
39974624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
40074624944SHao Chen struct netlink_ext_ack *extack)
401d45d8979SChristina Jacob {
402d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
403a989eb66SSubbaraya Sundeep u32 rx_buf_len = kernel_ring->rx_buf_len;
404a989eb66SSubbaraya Sundeep u32 old_rx_buf_len = pfvf->hw.rbuf_len;
40568258596SSubbaraya Sundeep u32 xqe_size = kernel_ring->cqe_size;
406d45d8979SChristina Jacob bool if_up = netif_running(netdev);
407d45d8979SChristina Jacob struct otx2_qset *qs = &pfvf->qset;
408d45d8979SChristina Jacob u32 rx_count, tx_count;
409d45d8979SChristina Jacob
410d45d8979SChristina Jacob if (ring->rx_mini_pending || ring->rx_jumbo_pending)
411d45d8979SChristina Jacob return -EINVAL;
412d45d8979SChristina Jacob
413a989eb66SSubbaraya Sundeep /* Hardware supports max size of 32k for a receive buffer
414a989eb66SSubbaraya Sundeep * and 1536 is typical ethernet frame size.
415a989eb66SSubbaraya Sundeep */
416a989eb66SSubbaraya Sundeep if (rx_buf_len && (rx_buf_len < 1536 || rx_buf_len > 32768)) {
417a989eb66SSubbaraya Sundeep netdev_err(netdev,
418a989eb66SSubbaraya Sundeep "Receive buffer range is 1536 - 32768");
419a989eb66SSubbaraya Sundeep return -EINVAL;
420a989eb66SSubbaraya Sundeep }
421a989eb66SSubbaraya Sundeep
42268258596SSubbaraya Sundeep if (xqe_size != 128 && xqe_size != 512) {
42368258596SSubbaraya Sundeep netdev_err(netdev,
42468258596SSubbaraya Sundeep "Completion event size must be 128 or 512");
42568258596SSubbaraya Sundeep return -EINVAL;
42668258596SSubbaraya Sundeep }
42768258596SSubbaraya Sundeep
428d45d8979SChristina Jacob /* Permitted lengths are 16 64 256 1K 4K 16K 64K 256K 1M */
429d45d8979SChristina Jacob rx_count = ring->rx_pending;
430d45d8979SChristina Jacob /* On some silicon variants a skid or reserved CQEs are
431d45d8979SChristina Jacob * needed to avoid CQ overflow.
432d45d8979SChristina Jacob */
433d45d8979SChristina Jacob if (rx_count < pfvf->hw.rq_skid)
434d45d8979SChristina Jacob rx_count = pfvf->hw.rq_skid;
435d45d8979SChristina Jacob rx_count = Q_COUNT(Q_SIZE(rx_count, 3));
436d45d8979SChristina Jacob
437d45d8979SChristina Jacob /* Due pipelining impact minimum 2000 unused SQ CQE's
438d45d8979SChristina Jacob * need to be maintained to avoid CQ overflow, hence the
439d45d8979SChristina Jacob * minimum 4K size.
440d45d8979SChristina Jacob */
441d45d8979SChristina Jacob tx_count = clamp_t(u32, ring->tx_pending,
442d45d8979SChristina Jacob Q_COUNT(Q_SIZE_4K), Q_COUNT(Q_SIZE_MAX));
443d45d8979SChristina Jacob tx_count = Q_COUNT(Q_SIZE(tx_count, 3));
444d45d8979SChristina Jacob
445a989eb66SSubbaraya Sundeep if (tx_count == qs->sqe_cnt && rx_count == qs->rqe_cnt &&
44668258596SSubbaraya Sundeep rx_buf_len == old_rx_buf_len && xqe_size == pfvf->hw.xqe_size)
447d45d8979SChristina Jacob return 0;
448d45d8979SChristina Jacob
449d45d8979SChristina Jacob if (if_up)
45005c22b54STomasz Duszynski netdev->netdev_ops->ndo_stop(netdev);
451d45d8979SChristina Jacob
452d45d8979SChristina Jacob /* Assigned to the nearest possible exponent. */
453d45d8979SChristina Jacob qs->sqe_cnt = tx_count;
454d45d8979SChristina Jacob qs->rqe_cnt = rx_count;
455d45d8979SChristina Jacob
456a989eb66SSubbaraya Sundeep pfvf->hw.rbuf_len = rx_buf_len;
45768258596SSubbaraya Sundeep pfvf->hw.xqe_size = xqe_size;
458a989eb66SSubbaraya Sundeep
459d45d8979SChristina Jacob if (if_up)
46069f0aeb1SGeetha sowjanya return netdev->netdev_ops->ndo_open(netdev);
46105c22b54STomasz Duszynski
462d45d8979SChristina Jacob return 0;
463d45d8979SChristina Jacob }
464d45d8979SChristina Jacob
otx2_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * cmd,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)465d45d8979SChristina Jacob static int otx2_get_coalesce(struct net_device *netdev,
466f3ccfda1SYufeng Mo struct ethtool_coalesce *cmd,
467f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
468f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
469d45d8979SChristina Jacob {
470d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
471d45d8979SChristina Jacob struct otx2_hw *hw = &pfvf->hw;
472d45d8979SChristina Jacob
473d45d8979SChristina Jacob cmd->rx_coalesce_usecs = hw->cq_time_wait;
474d45d8979SChristina Jacob cmd->rx_max_coalesced_frames = hw->cq_ecount_wait;
475d45d8979SChristina Jacob cmd->tx_coalesce_usecs = hw->cq_time_wait;
476d45d8979SChristina Jacob cmd->tx_max_coalesced_frames = hw->cq_ecount_wait;
4776e144b47SSuman Ghosh if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) ==
4786e144b47SSuman Ghosh OTX2_FLAG_ADPTV_INT_COAL_ENABLED) {
4796e144b47SSuman Ghosh cmd->use_adaptive_rx_coalesce = 1;
4806e144b47SSuman Ghosh cmd->use_adaptive_tx_coalesce = 1;
4816e144b47SSuman Ghosh } else {
4826e144b47SSuman Ghosh cmd->use_adaptive_rx_coalesce = 0;
4836e144b47SSuman Ghosh cmd->use_adaptive_tx_coalesce = 0;
4846e144b47SSuman Ghosh }
485d45d8979SChristina Jacob
486d45d8979SChristina Jacob return 0;
487d45d8979SChristina Jacob }
488d45d8979SChristina Jacob
otx2_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)489d45d8979SChristina Jacob static int otx2_set_coalesce(struct net_device *netdev,
490f3ccfda1SYufeng Mo struct ethtool_coalesce *ec,
491f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
492f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
493d45d8979SChristina Jacob {
494d45d8979SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
495d45d8979SChristina Jacob struct otx2_hw *hw = &pfvf->hw;
4966e144b47SSuman Ghosh u8 priv_coalesce_status;
497d45d8979SChristina Jacob int qidx;
498d45d8979SChristina Jacob
499d45d8979SChristina Jacob if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames)
500d45d8979SChristina Jacob return 0;
501d45d8979SChristina Jacob
5026e144b47SSuman Ghosh if (ec->use_adaptive_rx_coalesce != ec->use_adaptive_tx_coalesce) {
5036e144b47SSuman Ghosh netdev_err(netdev,
5046e144b47SSuman Ghosh "adaptive-rx should be same as adaptive-tx");
5056e144b47SSuman Ghosh return -EINVAL;
5066e144b47SSuman Ghosh }
5076e144b47SSuman Ghosh
5086e144b47SSuman Ghosh /* Check and update coalesce status */
5096e144b47SSuman Ghosh if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) ==
5106e144b47SSuman Ghosh OTX2_FLAG_ADPTV_INT_COAL_ENABLED) {
5116e144b47SSuman Ghosh priv_coalesce_status = 1;
5126e144b47SSuman Ghosh if (!ec->use_adaptive_rx_coalesce)
5136e144b47SSuman Ghosh pfvf->flags &= ~OTX2_FLAG_ADPTV_INT_COAL_ENABLED;
5146e144b47SSuman Ghosh } else {
5156e144b47SSuman Ghosh priv_coalesce_status = 0;
5166e144b47SSuman Ghosh if (ec->use_adaptive_rx_coalesce)
5176e144b47SSuman Ghosh pfvf->flags |= OTX2_FLAG_ADPTV_INT_COAL_ENABLED;
5186e144b47SSuman Ghosh }
5196e144b47SSuman Ghosh
520d45d8979SChristina Jacob /* 'cq_time_wait' is 8bit and is in multiple of 100ns,
521d45d8979SChristina Jacob * so clamp the user given value to the range of 1 to 25usec.
522d45d8979SChristina Jacob */
523d45d8979SChristina Jacob ec->rx_coalesce_usecs = clamp_t(u32, ec->rx_coalesce_usecs,
524d45d8979SChristina Jacob 1, CQ_TIMER_THRESH_MAX);
525d45d8979SChristina Jacob ec->tx_coalesce_usecs = clamp_t(u32, ec->tx_coalesce_usecs,
526d45d8979SChristina Jacob 1, CQ_TIMER_THRESH_MAX);
527d45d8979SChristina Jacob
528d45d8979SChristina Jacob /* Rx and Tx are mapped to same CQ, check which one
529d45d8979SChristina Jacob * is changed, if both then choose the min.
530d45d8979SChristina Jacob */
531d45d8979SChristina Jacob if (hw->cq_time_wait == ec->rx_coalesce_usecs)
532d45d8979SChristina Jacob hw->cq_time_wait = ec->tx_coalesce_usecs;
533d45d8979SChristina Jacob else if (hw->cq_time_wait == ec->tx_coalesce_usecs)
534d45d8979SChristina Jacob hw->cq_time_wait = ec->rx_coalesce_usecs;
535d45d8979SChristina Jacob else
536d45d8979SChristina Jacob hw->cq_time_wait = min_t(u8, ec->rx_coalesce_usecs,
537d45d8979SChristina Jacob ec->tx_coalesce_usecs);
538d45d8979SChristina Jacob
539d45d8979SChristina Jacob /* Max ecount_wait supported is 16bit,
540d45d8979SChristina Jacob * so clamp the user given value to the range of 1 to 64k.
541d45d8979SChristina Jacob */
542d45d8979SChristina Jacob ec->rx_max_coalesced_frames = clamp_t(u32, ec->rx_max_coalesced_frames,
5436e144b47SSuman Ghosh 1, NAPI_POLL_WEIGHT);
544d45d8979SChristina Jacob ec->tx_max_coalesced_frames = clamp_t(u32, ec->tx_max_coalesced_frames,
5456e144b47SSuman Ghosh 1, NAPI_POLL_WEIGHT);
546d45d8979SChristina Jacob
547d45d8979SChristina Jacob /* Rx and Tx are mapped to same CQ, check which one
548d45d8979SChristina Jacob * is changed, if both then choose the min.
549d45d8979SChristina Jacob */
550d45d8979SChristina Jacob if (hw->cq_ecount_wait == ec->rx_max_coalesced_frames)
551d45d8979SChristina Jacob hw->cq_ecount_wait = ec->tx_max_coalesced_frames;
552d45d8979SChristina Jacob else if (hw->cq_ecount_wait == ec->tx_max_coalesced_frames)
553d45d8979SChristina Jacob hw->cq_ecount_wait = ec->rx_max_coalesced_frames;
554d45d8979SChristina Jacob else
555d45d8979SChristina Jacob hw->cq_ecount_wait = min_t(u16, ec->rx_max_coalesced_frames,
556d45d8979SChristina Jacob ec->tx_max_coalesced_frames);
557d45d8979SChristina Jacob
5586e144b47SSuman Ghosh /* Reset 'cq_time_wait' and 'cq_ecount_wait' to
5596e144b47SSuman Ghosh * default values if coalesce status changed from
5606e144b47SSuman Ghosh * 'on' to 'off'.
5616e144b47SSuman Ghosh */
5626e144b47SSuman Ghosh if (priv_coalesce_status &&
5636e144b47SSuman Ghosh ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) !=
5646e144b47SSuman Ghosh OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) {
5656e144b47SSuman Ghosh hw->cq_time_wait = CQ_TIMER_THRESH_DEFAULT;
5666e144b47SSuman Ghosh hw->cq_ecount_wait = CQ_CQE_THRESH_DEFAULT;
5676e144b47SSuman Ghosh }
5686e144b47SSuman Ghosh
569d45d8979SChristina Jacob if (netif_running(netdev)) {
570d45d8979SChristina Jacob for (qidx = 0; qidx < pfvf->hw.cint_cnt; qidx++)
571d45d8979SChristina Jacob otx2_config_irq_coalescing(pfvf, qidx);
572d45d8979SChristina Jacob }
573d45d8979SChristina Jacob
574d45d8979SChristina Jacob return 0;
575d45d8979SChristina Jacob }
576d45d8979SChristina Jacob
otx2_get_rss_hash_opts(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc)5776e92d71bSSunil Goutham static int otx2_get_rss_hash_opts(struct otx2_nic *pfvf,
5786e92d71bSSunil Goutham struct ethtool_rxnfc *nfc)
5796e92d71bSSunil Goutham {
5806e92d71bSSunil Goutham struct otx2_rss_info *rss = &pfvf->hw.rss_info;
5816e92d71bSSunil Goutham
5826e92d71bSSunil Goutham if (!(rss->flowkey_cfg &
5836e92d71bSSunil Goutham (NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6)))
5846e92d71bSSunil Goutham return 0;
5856e92d71bSSunil Goutham
5866e92d71bSSunil Goutham /* Mimimum is IPv4 and IPv6, SIP/DIP */
5876e92d71bSSunil Goutham nfc->data = RXH_IP_SRC | RXH_IP_DST;
588a55ff8efSGeorge Cherian if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_VLAN)
589a55ff8efSGeorge Cherian nfc->data |= RXH_VLAN;
5906e92d71bSSunil Goutham
5916e92d71bSSunil Goutham switch (nfc->flow_type) {
5926e92d71bSSunil Goutham case TCP_V4_FLOW:
5936e92d71bSSunil Goutham case TCP_V6_FLOW:
5946e92d71bSSunil Goutham if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_TCP)
5956e92d71bSSunil Goutham nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
5966e92d71bSSunil Goutham break;
5976e92d71bSSunil Goutham case UDP_V4_FLOW:
5986e92d71bSSunil Goutham case UDP_V6_FLOW:
5996e92d71bSSunil Goutham if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_UDP)
6006e92d71bSSunil Goutham nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
6016e92d71bSSunil Goutham break;
6026e92d71bSSunil Goutham case SCTP_V4_FLOW:
6036e92d71bSSunil Goutham case SCTP_V6_FLOW:
6046e92d71bSSunil Goutham if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_SCTP)
6056e92d71bSSunil Goutham nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
6066e92d71bSSunil Goutham break;
6076e92d71bSSunil Goutham case AH_ESP_V4_FLOW:
608b9b7421aSSubbaraya Sundeep case AH_ESP_V6_FLOW:
609b9b7421aSSubbaraya Sundeep if (rss->flowkey_cfg & NIX_FLOW_KEY_TYPE_ESP)
610b9b7421aSSubbaraya Sundeep nfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
611b9b7421aSSubbaraya Sundeep break;
6126e92d71bSSunil Goutham case AH_V4_FLOW:
6136e92d71bSSunil Goutham case ESP_V4_FLOW:
6146e92d71bSSunil Goutham case IPV4_FLOW:
615b9b7421aSSubbaraya Sundeep break;
6166e92d71bSSunil Goutham case AH_V6_FLOW:
6176e92d71bSSunil Goutham case ESP_V6_FLOW:
6186e92d71bSSunil Goutham case IPV6_FLOW:
6196e92d71bSSunil Goutham break;
6206e92d71bSSunil Goutham default:
6216e92d71bSSunil Goutham return -EINVAL;
6226e92d71bSSunil Goutham }
623b9b7421aSSubbaraya Sundeep
6246e92d71bSSunil Goutham return 0;
6256e92d71bSSunil Goutham }
6266e92d71bSSunil Goutham
otx2_set_rss_hash_opts(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc)6276e92d71bSSunil Goutham static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf,
6286e92d71bSSunil Goutham struct ethtool_rxnfc *nfc)
6296e92d71bSSunil Goutham {
6306e92d71bSSunil Goutham struct otx2_rss_info *rss = &pfvf->hw.rss_info;
6316e92d71bSSunil Goutham u32 rxh_l4 = RXH_L4_B_0_1 | RXH_L4_B_2_3;
6326e92d71bSSunil Goutham u32 rss_cfg = rss->flowkey_cfg;
6336e92d71bSSunil Goutham
6346e92d71bSSunil Goutham if (!rss->enable) {
6356e92d71bSSunil Goutham netdev_err(pfvf->netdev,
6366e92d71bSSunil Goutham "RSS is disabled, cannot change settings\n");
6376e92d71bSSunil Goutham return -EIO;
6386e92d71bSSunil Goutham }
6396e92d71bSSunil Goutham
6406e92d71bSSunil Goutham /* Mimimum is IPv4 and IPv6, SIP/DIP */
6416e92d71bSSunil Goutham if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST))
6426e92d71bSSunil Goutham return -EINVAL;
6436e92d71bSSunil Goutham
644a55ff8efSGeorge Cherian if (nfc->data & RXH_VLAN)
645a55ff8efSGeorge Cherian rss_cfg |= NIX_FLOW_KEY_TYPE_VLAN;
646a55ff8efSGeorge Cherian else
647a55ff8efSGeorge Cherian rss_cfg &= ~NIX_FLOW_KEY_TYPE_VLAN;
648a55ff8efSGeorge Cherian
6496e92d71bSSunil Goutham switch (nfc->flow_type) {
6506e92d71bSSunil Goutham case TCP_V4_FLOW:
6516e92d71bSSunil Goutham case TCP_V6_FLOW:
6526e92d71bSSunil Goutham /* Different config for v4 and v6 is not supported.
6536e92d71bSSunil Goutham * Both of them have to be either 4-tuple or 2-tuple.
6546e92d71bSSunil Goutham */
6556e92d71bSSunil Goutham switch (nfc->data & rxh_l4) {
6566e92d71bSSunil Goutham case 0:
6576e92d71bSSunil Goutham rss_cfg &= ~NIX_FLOW_KEY_TYPE_TCP;
6586e92d71bSSunil Goutham break;
6596e92d71bSSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
6606e92d71bSSunil Goutham rss_cfg |= NIX_FLOW_KEY_TYPE_TCP;
6616e92d71bSSunil Goutham break;
6626e92d71bSSunil Goutham default:
6636e92d71bSSunil Goutham return -EINVAL;
6646e92d71bSSunil Goutham }
6656e92d71bSSunil Goutham break;
6666e92d71bSSunil Goutham case UDP_V4_FLOW:
6676e92d71bSSunil Goutham case UDP_V6_FLOW:
6686e92d71bSSunil Goutham switch (nfc->data & rxh_l4) {
6696e92d71bSSunil Goutham case 0:
6706e92d71bSSunil Goutham rss_cfg &= ~NIX_FLOW_KEY_TYPE_UDP;
6716e92d71bSSunil Goutham break;
6726e92d71bSSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
6736e92d71bSSunil Goutham rss_cfg |= NIX_FLOW_KEY_TYPE_UDP;
6746e92d71bSSunil Goutham break;
6756e92d71bSSunil Goutham default:
6766e92d71bSSunil Goutham return -EINVAL;
6776e92d71bSSunil Goutham }
6786e92d71bSSunil Goutham break;
6796e92d71bSSunil Goutham case SCTP_V4_FLOW:
6806e92d71bSSunil Goutham case SCTP_V6_FLOW:
6816e92d71bSSunil Goutham switch (nfc->data & rxh_l4) {
6826e92d71bSSunil Goutham case 0:
6836e92d71bSSunil Goutham rss_cfg &= ~NIX_FLOW_KEY_TYPE_SCTP;
6846e92d71bSSunil Goutham break;
6856e92d71bSSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
6866e92d71bSSunil Goutham rss_cfg |= NIX_FLOW_KEY_TYPE_SCTP;
6876e92d71bSSunil Goutham break;
6886e92d71bSSunil Goutham default:
6896e92d71bSSunil Goutham return -EINVAL;
6906e92d71bSSunil Goutham }
6916e92d71bSSunil Goutham break;
692b9b7421aSSubbaraya Sundeep case AH_ESP_V4_FLOW:
693b9b7421aSSubbaraya Sundeep case AH_ESP_V6_FLOW:
694b9b7421aSSubbaraya Sundeep switch (nfc->data & rxh_l4) {
695b9b7421aSSubbaraya Sundeep case 0:
696b9b7421aSSubbaraya Sundeep rss_cfg &= ~(NIX_FLOW_KEY_TYPE_ESP |
697b9b7421aSSubbaraya Sundeep NIX_FLOW_KEY_TYPE_AH);
698b9b7421aSSubbaraya Sundeep rss_cfg |= NIX_FLOW_KEY_TYPE_VLAN |
699b9b7421aSSubbaraya Sundeep NIX_FLOW_KEY_TYPE_IPV4_PROTO;
700b9b7421aSSubbaraya Sundeep break;
701b9b7421aSSubbaraya Sundeep case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
702b9b7421aSSubbaraya Sundeep /* If VLAN hashing is also requested for ESP then do not
703b9b7421aSSubbaraya Sundeep * allow because of hardware 40 bytes flow key limit.
704b9b7421aSSubbaraya Sundeep */
705b9b7421aSSubbaraya Sundeep if (rss_cfg & NIX_FLOW_KEY_TYPE_VLAN) {
706b9b7421aSSubbaraya Sundeep netdev_err(pfvf->netdev,
707b9b7421aSSubbaraya Sundeep "RSS hash of ESP or AH with VLAN is not supported\n");
708b9b7421aSSubbaraya Sundeep return -EOPNOTSUPP;
709b9b7421aSSubbaraya Sundeep }
710b9b7421aSSubbaraya Sundeep
711b9b7421aSSubbaraya Sundeep rss_cfg |= NIX_FLOW_KEY_TYPE_ESP | NIX_FLOW_KEY_TYPE_AH;
712b9b7421aSSubbaraya Sundeep /* Disable IPv4 proto hashing since IPv6 SA+DA(32 bytes)
713b9b7421aSSubbaraya Sundeep * and ESP SPI+sequence(8 bytes) uses hardware maximum
714b9b7421aSSubbaraya Sundeep * limit of 40 byte flow key.
715b9b7421aSSubbaraya Sundeep */
716b9b7421aSSubbaraya Sundeep rss_cfg &= ~NIX_FLOW_KEY_TYPE_IPV4_PROTO;
717b9b7421aSSubbaraya Sundeep break;
718b9b7421aSSubbaraya Sundeep default:
719b9b7421aSSubbaraya Sundeep return -EINVAL;
720b9b7421aSSubbaraya Sundeep }
721b9b7421aSSubbaraya Sundeep break;
7226e92d71bSSunil Goutham case IPV4_FLOW:
7236e92d71bSSunil Goutham case IPV6_FLOW:
7246e92d71bSSunil Goutham rss_cfg = NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6;
7256e92d71bSSunil Goutham break;
7266e92d71bSSunil Goutham default:
7276e92d71bSSunil Goutham return -EINVAL;
7286e92d71bSSunil Goutham }
7296e92d71bSSunil Goutham
7306e92d71bSSunil Goutham rss->flowkey_cfg = rss_cfg;
7316e92d71bSSunil Goutham otx2_set_flowkey_cfg(pfvf);
7326e92d71bSSunil Goutham return 0;
7336e92d71bSSunil Goutham }
7346e92d71bSSunil Goutham
otx2_get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * nfc,u32 * rules)7356e92d71bSSunil Goutham static int otx2_get_rxnfc(struct net_device *dev,
7366e92d71bSSunil Goutham struct ethtool_rxnfc *nfc, u32 *rules)
7376e92d71bSSunil Goutham {
7383cffaed2SRakesh Babu bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
7396e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(dev);
7406e92d71bSSunil Goutham int ret = -EOPNOTSUPP;
7416e92d71bSSunil Goutham
7426e92d71bSSunil Goutham switch (nfc->cmd) {
7436e92d71bSSunil Goutham case ETHTOOL_GRXRINGS:
7446e92d71bSSunil Goutham nfc->data = pfvf->hw.rx_queues;
7456e92d71bSSunil Goutham ret = 0;
7466e92d71bSSunil Goutham break;
747f0a1913fSSubbaraya Sundeep case ETHTOOL_GRXCLSRLCNT:
7483cffaed2SRakesh Babu if (netif_running(dev) && ntuple) {
749f0a1913fSSubbaraya Sundeep nfc->rule_cnt = pfvf->flow_cfg->nr_flows;
750f0a1913fSSubbaraya Sundeep ret = 0;
7513cffaed2SRakesh Babu }
752f0a1913fSSubbaraya Sundeep break;
753f0a1913fSSubbaraya Sundeep case ETHTOOL_GRXCLSRULE:
7543cffaed2SRakesh Babu if (netif_running(dev) && ntuple)
755f0a1913fSSubbaraya Sundeep ret = otx2_get_flow(pfvf, nfc, nfc->fs.location);
756f0a1913fSSubbaraya Sundeep break;
757f0a1913fSSubbaraya Sundeep case ETHTOOL_GRXCLSRLALL:
7583cffaed2SRakesh Babu if (netif_running(dev) && ntuple)
759f0a1913fSSubbaraya Sundeep ret = otx2_get_all_flows(pfvf, nfc, rules);
760f0a1913fSSubbaraya Sundeep break;
7616e92d71bSSunil Goutham case ETHTOOL_GRXFH:
7626e92d71bSSunil Goutham return otx2_get_rss_hash_opts(pfvf, nfc);
7636e92d71bSSunil Goutham default:
7646e92d71bSSunil Goutham break;
7656e92d71bSSunil Goutham }
7666e92d71bSSunil Goutham return ret;
7676e92d71bSSunil Goutham }
7686e92d71bSSunil Goutham
otx2_set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * nfc)7696e92d71bSSunil Goutham static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
7706e92d71bSSunil Goutham {
771f0a1913fSSubbaraya Sundeep bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
772f0a1913fSSubbaraya Sundeep struct otx2_nic *pfvf = netdev_priv(dev);
773f0a1913fSSubbaraya Sundeep int ret = -EOPNOTSUPP;
774f0a1913fSSubbaraya Sundeep
775ec87f054SSuman Ghosh pfvf->flow_cfg->ntuple = ntuple;
776f0a1913fSSubbaraya Sundeep switch (nfc->cmd) {
777f0a1913fSSubbaraya Sundeep case ETHTOOL_SRXFH:
778f0a1913fSSubbaraya Sundeep ret = otx2_set_rss_hash_opts(pfvf, nfc);
779f0a1913fSSubbaraya Sundeep break;
780f0a1913fSSubbaraya Sundeep case ETHTOOL_SRXCLSRLINS:
781f0a1913fSSubbaraya Sundeep if (netif_running(dev) && ntuple)
78281a43620SGeetha sowjanya ret = otx2_add_flow(pfvf, nfc);
783f0a1913fSSubbaraya Sundeep break;
784f0a1913fSSubbaraya Sundeep case ETHTOOL_SRXCLSRLDEL:
785f0a1913fSSubbaraya Sundeep if (netif_running(dev) && ntuple)
786f0a1913fSSubbaraya Sundeep ret = otx2_remove_flow(pfvf, nfc->fs.location);
787f0a1913fSSubbaraya Sundeep break;
788f0a1913fSSubbaraya Sundeep default:
789f0a1913fSSubbaraya Sundeep break;
790f0a1913fSSubbaraya Sundeep }
791f0a1913fSSubbaraya Sundeep
792f0a1913fSSubbaraya Sundeep return ret;
793f0a1913fSSubbaraya Sundeep }
794f0a1913fSSubbaraya Sundeep
otx2_get_rxfh_key_size(struct net_device * netdev)7956e92d71bSSunil Goutham static u32 otx2_get_rxfh_key_size(struct net_device *netdev)
7966e92d71bSSunil Goutham {
7976e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(netdev);
7986e92d71bSSunil Goutham struct otx2_rss_info *rss;
7996e92d71bSSunil Goutham
8006e92d71bSSunil Goutham rss = &pfvf->hw.rss_info;
8016e92d71bSSunil Goutham
8026e92d71bSSunil Goutham return sizeof(rss->key);
8036e92d71bSSunil Goutham }
8046e92d71bSSunil Goutham
otx2_get_rxfh_indir_size(struct net_device * dev)8056e92d71bSSunil Goutham static u32 otx2_get_rxfh_indir_size(struct net_device *dev)
8066e92d71bSSunil Goutham {
80781a43620SGeetha sowjanya return MAX_RSS_INDIR_TBL_SIZE;
8086e92d71bSSunil Goutham }
8096e92d71bSSunil Goutham
otx2_rss_ctx_delete(struct otx2_nic * pfvf,int ctx_id)81081a43620SGeetha sowjanya static int otx2_rss_ctx_delete(struct otx2_nic *pfvf, int ctx_id)
8116e92d71bSSunil Goutham {
81281a43620SGeetha sowjanya struct otx2_rss_info *rss = &pfvf->hw.rss_info;
8136e92d71bSSunil Goutham
81481a43620SGeetha sowjanya otx2_rss_ctx_flow_del(pfvf, ctx_id);
81581a43620SGeetha sowjanya kfree(rss->rss_ctx[ctx_id]);
81681a43620SGeetha sowjanya rss->rss_ctx[ctx_id] = NULL;
8176e92d71bSSunil Goutham
8186e92d71bSSunil Goutham return 0;
8196e92d71bSSunil Goutham }
8206e92d71bSSunil Goutham
otx2_rss_ctx_create(struct otx2_nic * pfvf,u32 * rss_context)82181a43620SGeetha sowjanya static int otx2_rss_ctx_create(struct otx2_nic *pfvf,
82281a43620SGeetha sowjanya u32 *rss_context)
82381a43620SGeetha sowjanya {
82481a43620SGeetha sowjanya struct otx2_rss_info *rss = &pfvf->hw.rss_info;
82581a43620SGeetha sowjanya u8 ctx;
82681a43620SGeetha sowjanya
82781a43620SGeetha sowjanya for (ctx = 0; ctx < MAX_RSS_GROUPS; ctx++) {
82881a43620SGeetha sowjanya if (!rss->rss_ctx[ctx])
82981a43620SGeetha sowjanya break;
83081a43620SGeetha sowjanya }
83181a43620SGeetha sowjanya if (ctx == MAX_RSS_GROUPS)
83281a43620SGeetha sowjanya return -EINVAL;
83381a43620SGeetha sowjanya
83481a43620SGeetha sowjanya rss->rss_ctx[ctx] = kzalloc(sizeof(*rss->rss_ctx[ctx]), GFP_KERNEL);
83581a43620SGeetha sowjanya if (!rss->rss_ctx[ctx])
83681a43620SGeetha sowjanya return -ENOMEM;
83781a43620SGeetha sowjanya *rss_context = ctx;
83881a43620SGeetha sowjanya
83981a43620SGeetha sowjanya return 0;
84081a43620SGeetha sowjanya }
84181a43620SGeetha sowjanya
84281a43620SGeetha sowjanya /* RSS context configuration */
otx2_set_rxfh_context(struct net_device * dev,const u32 * indir,const u8 * hkey,const u8 hfunc,u32 * rss_context,bool delete)84381a43620SGeetha sowjanya static int otx2_set_rxfh_context(struct net_device *dev, const u32 *indir,
84481a43620SGeetha sowjanya const u8 *hkey, const u8 hfunc,
84581a43620SGeetha sowjanya u32 *rss_context, bool delete)
8466e92d71bSSunil Goutham {
8476e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(dev);
84881a43620SGeetha sowjanya struct otx2_rss_ctx *rss_ctx;
8496e92d71bSSunil Goutham struct otx2_rss_info *rss;
85081a43620SGeetha sowjanya int ret, idx;
8516e92d71bSSunil Goutham
8526e92d71bSSunil Goutham if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
8536e92d71bSSunil Goutham return -EOPNOTSUPP;
8546e92d71bSSunil Goutham
855e5cc361eSDan Carpenter if (*rss_context != ETH_RXFH_CONTEXT_ALLOC &&
856e5cc361eSDan Carpenter *rss_context >= MAX_RSS_GROUPS)
857e5cc361eSDan Carpenter return -EINVAL;
858e5cc361eSDan Carpenter
8596e92d71bSSunil Goutham rss = &pfvf->hw.rss_info;
8606e92d71bSSunil Goutham
8616e92d71bSSunil Goutham if (!rss->enable) {
8626e92d71bSSunil Goutham netdev_err(dev, "RSS is disabled, cannot change settings\n");
8636e92d71bSSunil Goutham return -EIO;
8646e92d71bSSunil Goutham }
8656e92d71bSSunil Goutham
8666e92d71bSSunil Goutham if (hkey) {
8676e92d71bSSunil Goutham memcpy(rss->key, hkey, sizeof(rss->key));
8686e92d71bSSunil Goutham otx2_set_rss_key(pfvf);
8696e92d71bSSunil Goutham }
87081a43620SGeetha sowjanya if (delete)
87181a43620SGeetha sowjanya return otx2_rss_ctx_delete(pfvf, *rss_context);
8726e92d71bSSunil Goutham
87381a43620SGeetha sowjanya if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
87481a43620SGeetha sowjanya ret = otx2_rss_ctx_create(pfvf, rss_context);
87581a43620SGeetha sowjanya if (ret)
87681a43620SGeetha sowjanya return ret;
87781a43620SGeetha sowjanya }
87881a43620SGeetha sowjanya if (indir) {
87981a43620SGeetha sowjanya rss_ctx = rss->rss_ctx[*rss_context];
88081a43620SGeetha sowjanya for (idx = 0; idx < rss->rss_size; idx++)
88181a43620SGeetha sowjanya rss_ctx->ind_tbl[idx] = indir[idx];
88281a43620SGeetha sowjanya }
88381a43620SGeetha sowjanya otx2_set_rss_table(pfvf, *rss_context);
88481a43620SGeetha sowjanya
8856e92d71bSSunil Goutham return 0;
8866e92d71bSSunil Goutham }
8876e92d71bSSunil Goutham
otx2_get_rxfh_context(struct net_device * dev,u32 * indir,u8 * hkey,u8 * hfunc,u32 rss_context)88881a43620SGeetha sowjanya static int otx2_get_rxfh_context(struct net_device *dev, u32 *indir,
88981a43620SGeetha sowjanya u8 *hkey, u8 *hfunc, u32 rss_context)
89081a43620SGeetha sowjanya {
89181a43620SGeetha sowjanya struct otx2_nic *pfvf = netdev_priv(dev);
89281a43620SGeetha sowjanya struct otx2_rss_ctx *rss_ctx;
89381a43620SGeetha sowjanya struct otx2_rss_info *rss;
89481a43620SGeetha sowjanya int idx, rx_queues;
89581a43620SGeetha sowjanya
89681a43620SGeetha sowjanya rss = &pfvf->hw.rss_info;
89781a43620SGeetha sowjanya
89881a43620SGeetha sowjanya if (hfunc)
89981a43620SGeetha sowjanya *hfunc = ETH_RSS_HASH_TOP;
90081a43620SGeetha sowjanya
90181a43620SGeetha sowjanya if (!indir)
90281a43620SGeetha sowjanya return 0;
90381a43620SGeetha sowjanya
90481a43620SGeetha sowjanya if (!rss->enable && rss_context == DEFAULT_RSS_CONTEXT_GROUP) {
90581a43620SGeetha sowjanya rx_queues = pfvf->hw.rx_queues;
90681a43620SGeetha sowjanya for (idx = 0; idx < MAX_RSS_INDIR_TBL_SIZE; idx++)
90781a43620SGeetha sowjanya indir[idx] = ethtool_rxfh_indir_default(idx, rx_queues);
90881a43620SGeetha sowjanya return 0;
90981a43620SGeetha sowjanya }
91081a43620SGeetha sowjanya if (rss_context >= MAX_RSS_GROUPS)
91181a43620SGeetha sowjanya return -ENOENT;
91281a43620SGeetha sowjanya
91381a43620SGeetha sowjanya rss_ctx = rss->rss_ctx[rss_context];
91481a43620SGeetha sowjanya if (!rss_ctx)
91581a43620SGeetha sowjanya return -ENOENT;
91681a43620SGeetha sowjanya
91781a43620SGeetha sowjanya if (indir) {
91881a43620SGeetha sowjanya for (idx = 0; idx < rss->rss_size; idx++)
91981a43620SGeetha sowjanya indir[idx] = rss_ctx->ind_tbl[idx];
92081a43620SGeetha sowjanya }
92181a43620SGeetha sowjanya if (hkey)
92281a43620SGeetha sowjanya memcpy(hkey, rss->key, sizeof(rss->key));
92381a43620SGeetha sowjanya
92481a43620SGeetha sowjanya return 0;
92581a43620SGeetha sowjanya }
92681a43620SGeetha sowjanya
92781a43620SGeetha sowjanya /* Get RSS configuration */
otx2_get_rxfh(struct net_device * dev,u32 * indir,u8 * hkey,u8 * hfunc)92881a43620SGeetha sowjanya static int otx2_get_rxfh(struct net_device *dev, u32 *indir,
92981a43620SGeetha sowjanya u8 *hkey, u8 *hfunc)
93081a43620SGeetha sowjanya {
93181a43620SGeetha sowjanya return otx2_get_rxfh_context(dev, indir, hkey, hfunc,
93281a43620SGeetha sowjanya DEFAULT_RSS_CONTEXT_GROUP);
93381a43620SGeetha sowjanya }
93481a43620SGeetha sowjanya
93581a43620SGeetha sowjanya /* Configure RSS table and hash key */
otx2_set_rxfh(struct net_device * dev,const u32 * indir,const u8 * hkey,const u8 hfunc)93681a43620SGeetha sowjanya static int otx2_set_rxfh(struct net_device *dev, const u32 *indir,
93781a43620SGeetha sowjanya const u8 *hkey, const u8 hfunc)
93881a43620SGeetha sowjanya {
93981a43620SGeetha sowjanya
94081a43620SGeetha sowjanya u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
94181a43620SGeetha sowjanya
94281a43620SGeetha sowjanya return otx2_set_rxfh_context(dev, indir, hkey, hfunc, &rss_context, 0);
94381a43620SGeetha sowjanya }
94481a43620SGeetha sowjanya
otx2_get_msglevel(struct net_device * netdev)9456e92d71bSSunil Goutham static u32 otx2_get_msglevel(struct net_device *netdev)
9466e92d71bSSunil Goutham {
9476e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(netdev);
9486e92d71bSSunil Goutham
9496e92d71bSSunil Goutham return pfvf->msg_enable;
9506e92d71bSSunil Goutham }
9516e92d71bSSunil Goutham
otx2_set_msglevel(struct net_device * netdev,u32 val)9526e92d71bSSunil Goutham static void otx2_set_msglevel(struct net_device *netdev, u32 val)
9536e92d71bSSunil Goutham {
9546e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(netdev);
9556e92d71bSSunil Goutham
9566e92d71bSSunil Goutham pfvf->msg_enable = val;
9576e92d71bSSunil Goutham }
9586e92d71bSSunil Goutham
otx2_get_link(struct net_device * netdev)9596e92d71bSSunil Goutham static u32 otx2_get_link(struct net_device *netdev)
9606e92d71bSSunil Goutham {
9616e92d71bSSunil Goutham struct otx2_nic *pfvf = netdev_priv(netdev);
9626e92d71bSSunil Goutham
96305c22b54STomasz Duszynski /* LBK link is internal and always UP */
96405c22b54STomasz Duszynski if (is_otx2_lbkvf(pfvf->pdev))
96505c22b54STomasz Duszynski return 1;
9666e92d71bSSunil Goutham return pfvf->linfo.link_up;
9676e92d71bSSunil Goutham }
9686e92d71bSSunil Goutham
otx2_get_ts_info(struct net_device * netdev,struct ethtool_ts_info * info)969c9c12d33SAleksey Makarov static int otx2_get_ts_info(struct net_device *netdev,
970c9c12d33SAleksey Makarov struct ethtool_ts_info *info)
971c9c12d33SAleksey Makarov {
972c9c12d33SAleksey Makarov struct otx2_nic *pfvf = netdev_priv(netdev);
973c9c12d33SAleksey Makarov
974c9c12d33SAleksey Makarov if (!pfvf->ptp)
975c9c12d33SAleksey Makarov return ethtool_op_get_ts_info(netdev, info);
976c9c12d33SAleksey Makarov
977c9c12d33SAleksey Makarov info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
978c9c12d33SAleksey Makarov SOF_TIMESTAMPING_RX_SOFTWARE |
979c9c12d33SAleksey Makarov SOF_TIMESTAMPING_SOFTWARE |
980c9c12d33SAleksey Makarov SOF_TIMESTAMPING_TX_HARDWARE |
981c9c12d33SAleksey Makarov SOF_TIMESTAMPING_RX_HARDWARE |
982c9c12d33SAleksey Makarov SOF_TIMESTAMPING_RAW_HARDWARE;
983c9c12d33SAleksey Makarov
984c9c12d33SAleksey Makarov info->phc_index = otx2_ptp_clock_index(pfvf);
985c9c12d33SAleksey Makarov
9862958d17aSHariprasad Kelam info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
9872958d17aSHariprasad Kelam if (test_bit(CN10K_PTP_ONESTEP, &pfvf->hw.cap_flag))
9882958d17aSHariprasad Kelam info->tx_types |= BIT(HWTSTAMP_TX_ONESTEP_SYNC);
989c9c12d33SAleksey Makarov
9902958d17aSHariprasad Kelam info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
9912958d17aSHariprasad Kelam BIT(HWTSTAMP_FILTER_ALL);
992c9c12d33SAleksey Makarov
993c9c12d33SAleksey Makarov return 0;
994c9c12d33SAleksey Makarov }
995c9c12d33SAleksey Makarov
otx2_get_fwdata(struct otx2_nic * pfvf)996d0cf9503SChristina Jacob static struct cgx_fw_data *otx2_get_fwdata(struct otx2_nic *pfvf)
997d0cf9503SChristina Jacob {
998d0cf9503SChristina Jacob struct cgx_fw_data *rsp = NULL;
999d0cf9503SChristina Jacob struct msg_req *req;
1000d0cf9503SChristina Jacob int err = 0;
1001d0cf9503SChristina Jacob
1002d0cf9503SChristina Jacob mutex_lock(&pfvf->mbox.lock);
1003d0cf9503SChristina Jacob req = otx2_mbox_alloc_msg_cgx_get_aux_link_info(&pfvf->mbox);
1004d0cf9503SChristina Jacob if (!req) {
1005d0cf9503SChristina Jacob mutex_unlock(&pfvf->mbox.lock);
1006d0cf9503SChristina Jacob return ERR_PTR(-ENOMEM);
1007d0cf9503SChristina Jacob }
1008d0cf9503SChristina Jacob
1009d0cf9503SChristina Jacob err = otx2_sync_mbox_msg(&pfvf->mbox);
1010d0cf9503SChristina Jacob if (!err) {
1011d0cf9503SChristina Jacob rsp = (struct cgx_fw_data *)
1012d0cf9503SChristina Jacob otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
1013d0cf9503SChristina Jacob } else {
1014d0cf9503SChristina Jacob rsp = ERR_PTR(err);
1015d0cf9503SChristina Jacob }
1016d0cf9503SChristina Jacob
1017d0cf9503SChristina Jacob mutex_unlock(&pfvf->mbox.lock);
1018d0cf9503SChristina Jacob return rsp;
1019d0cf9503SChristina Jacob }
1020d0cf9503SChristina Jacob
otx2_get_fecparam(struct net_device * netdev,struct ethtool_fecparam * fecparam)1021d0cf9503SChristina Jacob static int otx2_get_fecparam(struct net_device *netdev,
1022d0cf9503SChristina Jacob struct ethtool_fecparam *fecparam)
1023d0cf9503SChristina Jacob {
1024d0cf9503SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
1025d0cf9503SChristina Jacob struct cgx_fw_data *rsp;
1026d0cf9503SChristina Jacob const int fec[] = {
1027d0cf9503SChristina Jacob ETHTOOL_FEC_OFF,
1028d0cf9503SChristina Jacob ETHTOOL_FEC_BASER,
1029d0cf9503SChristina Jacob ETHTOOL_FEC_RS,
1030d0cf9503SChristina Jacob ETHTOOL_FEC_BASER | ETHTOOL_FEC_RS};
1031d0cf9503SChristina Jacob #define FEC_MAX_INDEX 4
1032d0cf9503SChristina Jacob if (pfvf->linfo.fec < FEC_MAX_INDEX)
1033d0cf9503SChristina Jacob fecparam->active_fec = fec[pfvf->linfo.fec];
1034d0cf9503SChristina Jacob
1035d0cf9503SChristina Jacob rsp = otx2_get_fwdata(pfvf);
1036d0cf9503SChristina Jacob if (IS_ERR(rsp))
1037d0cf9503SChristina Jacob return PTR_ERR(rsp);
1038d0cf9503SChristina Jacob
1039b0aae0bdSDavid S. Miller if (rsp->fwdata.supported_fec < FEC_MAX_INDEX) {
1040d0cf9503SChristina Jacob if (!rsp->fwdata.supported_fec)
1041d0cf9503SChristina Jacob fecparam->fec = ETHTOOL_FEC_NONE;
1042d0cf9503SChristina Jacob else
104338b5133aSDan Carpenter fecparam->fec = fec[rsp->fwdata.supported_fec];
1044d0cf9503SChristina Jacob }
1045d0cf9503SChristina Jacob return 0;
1046d0cf9503SChristina Jacob }
1047d0cf9503SChristina Jacob
otx2_set_fecparam(struct net_device * netdev,struct ethtool_fecparam * fecparam)1048d0cf9503SChristina Jacob static int otx2_set_fecparam(struct net_device *netdev,
1049d0cf9503SChristina Jacob struct ethtool_fecparam *fecparam)
1050d0cf9503SChristina Jacob {
1051d0cf9503SChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
1052d0cf9503SChristina Jacob struct mbox *mbox = &pfvf->mbox;
1053d0cf9503SChristina Jacob struct fec_mode *req, *rsp;
1054d0cf9503SChristina Jacob int err = 0, fec = 0;
1055d0cf9503SChristina Jacob
1056d0cf9503SChristina Jacob switch (fecparam->fec) {
1057d0cf9503SChristina Jacob /* Firmware does not support AUTO mode consider it as FEC_OFF */
1058d0cf9503SChristina Jacob case ETHTOOL_FEC_OFF:
1059d0cf9503SChristina Jacob case ETHTOOL_FEC_AUTO:
1060d0cf9503SChristina Jacob fec = OTX2_FEC_OFF;
1061d0cf9503SChristina Jacob break;
1062d0cf9503SChristina Jacob case ETHTOOL_FEC_RS:
1063d0cf9503SChristina Jacob fec = OTX2_FEC_RS;
1064d0cf9503SChristina Jacob break;
1065d0cf9503SChristina Jacob case ETHTOOL_FEC_BASER:
1066d0cf9503SChristina Jacob fec = OTX2_FEC_BASER;
1067d0cf9503SChristina Jacob break;
1068d0cf9503SChristina Jacob default:
1069d0cf9503SChristina Jacob netdev_warn(pfvf->netdev, "Unsupported FEC mode: %d",
1070d0cf9503SChristina Jacob fecparam->fec);
1071d0cf9503SChristina Jacob return -EINVAL;
1072d0cf9503SChristina Jacob }
1073d0cf9503SChristina Jacob
1074d0cf9503SChristina Jacob if (fec == pfvf->linfo.fec)
1075d0cf9503SChristina Jacob return 0;
1076d0cf9503SChristina Jacob
1077d0cf9503SChristina Jacob mutex_lock(&mbox->lock);
1078d0cf9503SChristina Jacob req = otx2_mbox_alloc_msg_cgx_set_fec_param(&pfvf->mbox);
1079d0cf9503SChristina Jacob if (!req) {
1080d0cf9503SChristina Jacob err = -ENOMEM;
1081d0cf9503SChristina Jacob goto end;
1082d0cf9503SChristina Jacob }
1083d0cf9503SChristina Jacob req->fec = fec;
1084d0cf9503SChristina Jacob err = otx2_sync_mbox_msg(&pfvf->mbox);
1085d0cf9503SChristina Jacob if (err)
1086d0cf9503SChristina Jacob goto end;
1087d0cf9503SChristina Jacob
1088d0cf9503SChristina Jacob rsp = (struct fec_mode *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
1089d0cf9503SChristina Jacob 0, &req->hdr);
1090*c0f64fd7SDipendra Khadka if (IS_ERR(rsp)) {
1091*c0f64fd7SDipendra Khadka err = PTR_ERR(rsp);
1092*c0f64fd7SDipendra Khadka goto end;
1093*c0f64fd7SDipendra Khadka }
1094*c0f64fd7SDipendra Khadka
1095d0cf9503SChristina Jacob if (rsp->fec >= 0)
1096d0cf9503SChristina Jacob pfvf->linfo.fec = rsp->fec;
1097d0cf9503SChristina Jacob else
1098d0cf9503SChristina Jacob err = rsp->fec;
1099d0cf9503SChristina Jacob end:
1100d0cf9503SChristina Jacob mutex_unlock(&mbox->lock);
1101d0cf9503SChristina Jacob return err;
1102d0cf9503SChristina Jacob }
1103d0cf9503SChristina Jacob
otx2_get_fec_info(u64 index,int req_mode,struct ethtool_link_ksettings * link_ksettings)11041a50280cSChristina Jacob static void otx2_get_fec_info(u64 index, int req_mode,
11051a50280cSChristina Jacob struct ethtool_link_ksettings *link_ksettings)
11061a50280cSChristina Jacob {
11071a50280cSChristina Jacob __ETHTOOL_DECLARE_LINK_MODE_MASK(otx2_fec_modes) = { 0, };
11081a50280cSChristina Jacob
11091a50280cSChristina Jacob switch (index) {
11101a50280cSChristina Jacob case OTX2_FEC_NONE:
11111a50280cSChristina Jacob linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT,
11121a50280cSChristina Jacob otx2_fec_modes);
11131a50280cSChristina Jacob break;
11141a50280cSChristina Jacob case OTX2_FEC_BASER:
11151a50280cSChristina Jacob linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
11161a50280cSChristina Jacob otx2_fec_modes);
11171a50280cSChristina Jacob break;
11181a50280cSChristina Jacob case OTX2_FEC_RS:
11191a50280cSChristina Jacob linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
11201a50280cSChristina Jacob otx2_fec_modes);
11211a50280cSChristina Jacob break;
11221a50280cSChristina Jacob case OTX2_FEC_BASER | OTX2_FEC_RS:
11231a50280cSChristina Jacob linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
11241a50280cSChristina Jacob otx2_fec_modes);
11251a50280cSChristina Jacob linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
11261a50280cSChristina Jacob otx2_fec_modes);
11271a50280cSChristina Jacob break;
11281a50280cSChristina Jacob }
11291a50280cSChristina Jacob
11301a50280cSChristina Jacob /* Add fec modes to existing modes */
11311a50280cSChristina Jacob if (req_mode == OTX2_MODE_ADVERTISED)
11321a50280cSChristina Jacob linkmode_or(link_ksettings->link_modes.advertising,
11331a50280cSChristina Jacob link_ksettings->link_modes.advertising,
11341a50280cSChristina Jacob otx2_fec_modes);
11351a50280cSChristina Jacob else
11361a50280cSChristina Jacob linkmode_or(link_ksettings->link_modes.supported,
11371a50280cSChristina Jacob link_ksettings->link_modes.supported,
11381a50280cSChristina Jacob otx2_fec_modes);
11391a50280cSChristina Jacob }
11401a50280cSChristina Jacob
otx2_get_link_mode_info(u64 link_mode_bmap,bool req_mode,struct ethtool_link_ksettings * link_ksettings)11411a50280cSChristina Jacob static void otx2_get_link_mode_info(u64 link_mode_bmap,
11421a50280cSChristina Jacob bool req_mode,
11431a50280cSChristina Jacob struct ethtool_link_ksettings
11441a50280cSChristina Jacob *link_ksettings)
11451a50280cSChristina Jacob {
11461a50280cSChristina Jacob __ETHTOOL_DECLARE_LINK_MODE_MASK(otx2_link_modes) = { 0, };
11471a50280cSChristina Jacob const int otx2_sgmii_features[6] = {
11481a50280cSChristina Jacob ETHTOOL_LINK_MODE_10baseT_Half_BIT,
11491a50280cSChristina Jacob ETHTOOL_LINK_MODE_10baseT_Full_BIT,
11501a50280cSChristina Jacob ETHTOOL_LINK_MODE_100baseT_Half_BIT,
11511a50280cSChristina Jacob ETHTOOL_LINK_MODE_100baseT_Full_BIT,
11521a50280cSChristina Jacob ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
11531a50280cSChristina Jacob ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
11541a50280cSChristina Jacob };
11551a50280cSChristina Jacob /* CGX link modes to Ethtool link mode mapping */
11561a50280cSChristina Jacob const int cgx_link_mode[27] = {
11571a50280cSChristina Jacob 0, /* SGMII Mode */
11581a50280cSChristina Jacob ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
11591a50280cSChristina Jacob ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
11601a50280cSChristina Jacob ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
11611a50280cSChristina Jacob ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
11621a50280cSChristina Jacob ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
11631a50280cSChristina Jacob 0,
11641a50280cSChristina Jacob ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
11651a50280cSChristina Jacob 0,
11661a50280cSChristina Jacob 0,
11671a50280cSChristina Jacob ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
11681a50280cSChristina Jacob ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
11691a50280cSChristina Jacob ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
11701a50280cSChristina Jacob ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
11711a50280cSChristina Jacob ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
11721a50280cSChristina Jacob ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
11731a50280cSChristina Jacob 0,
11741a50280cSChristina Jacob ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
11751a50280cSChristina Jacob 0,
11761a50280cSChristina Jacob ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
11771a50280cSChristina Jacob ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
11781a50280cSChristina Jacob ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
11791a50280cSChristina Jacob 0,
11801a50280cSChristina Jacob ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
11811a50280cSChristina Jacob ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
11821a50280cSChristina Jacob ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
11831a50280cSChristina Jacob ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT
11841a50280cSChristina Jacob };
11851a50280cSChristina Jacob u8 bit;
11861a50280cSChristina Jacob
11871a50280cSChristina Jacob for_each_set_bit(bit, (unsigned long *)&link_mode_bmap, 27) {
11881a50280cSChristina Jacob /* SGMII mode is set */
11891a50280cSChristina Jacob if (bit == 0)
11901a50280cSChristina Jacob linkmode_set_bit_array(otx2_sgmii_features,
11911a50280cSChristina Jacob ARRAY_SIZE(otx2_sgmii_features),
11921a50280cSChristina Jacob otx2_link_modes);
11931a50280cSChristina Jacob else
11941a50280cSChristina Jacob linkmode_set_bit(cgx_link_mode[bit], otx2_link_modes);
11951a50280cSChristina Jacob }
11961a50280cSChristina Jacob
11971a50280cSChristina Jacob if (req_mode == OTX2_MODE_ADVERTISED)
11981a50280cSChristina Jacob linkmode_copy(link_ksettings->link_modes.advertising,
11991a50280cSChristina Jacob otx2_link_modes);
12001a50280cSChristina Jacob else
12011a50280cSChristina Jacob linkmode_copy(link_ksettings->link_modes.supported,
12021a50280cSChristina Jacob otx2_link_modes);
12031a50280cSChristina Jacob }
12041a50280cSChristina Jacob
otx2_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)12051a50280cSChristina Jacob static int otx2_get_link_ksettings(struct net_device *netdev,
12061a50280cSChristina Jacob struct ethtool_link_ksettings *cmd)
12071a50280cSChristina Jacob {
12081a50280cSChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
12091a50280cSChristina Jacob struct cgx_fw_data *rsp = NULL;
12101a50280cSChristina Jacob
12111a50280cSChristina Jacob cmd->base.duplex = pfvf->linfo.full_duplex;
12121a50280cSChristina Jacob cmd->base.speed = pfvf->linfo.speed;
12131a50280cSChristina Jacob cmd->base.autoneg = pfvf->linfo.an;
12141a50280cSChristina Jacob
12151a50280cSChristina Jacob rsp = otx2_get_fwdata(pfvf);
12161a50280cSChristina Jacob if (IS_ERR(rsp))
12171a50280cSChristina Jacob return PTR_ERR(rsp);
12181a50280cSChristina Jacob
12191a50280cSChristina Jacob if (rsp->fwdata.supported_an)
12201a50280cSChristina Jacob ethtool_link_ksettings_add_link_mode(cmd,
12211a50280cSChristina Jacob supported,
12221a50280cSChristina Jacob Autoneg);
12231a50280cSChristina Jacob
12241a50280cSChristina Jacob otx2_get_link_mode_info(rsp->fwdata.advertised_link_modes,
12251a50280cSChristina Jacob OTX2_MODE_ADVERTISED, cmd);
12261a50280cSChristina Jacob otx2_get_fec_info(rsp->fwdata.advertised_fec,
12271a50280cSChristina Jacob OTX2_MODE_ADVERTISED, cmd);
12281a50280cSChristina Jacob otx2_get_link_mode_info(rsp->fwdata.supported_link_modes,
12291a50280cSChristina Jacob OTX2_MODE_SUPPORTED, cmd);
12301a50280cSChristina Jacob otx2_get_fec_info(rsp->fwdata.supported_fec,
12311a50280cSChristina Jacob OTX2_MODE_SUPPORTED, cmd);
12321a50280cSChristina Jacob return 0;
12331a50280cSChristina Jacob }
12341a50280cSChristina Jacob
otx2_get_advertised_mode(const struct ethtool_link_ksettings * cmd,u64 * mode)1235cff713ceSChristina Jacob static void otx2_get_advertised_mode(const struct ethtool_link_ksettings *cmd,
1236cff713ceSChristina Jacob u64 *mode)
1237cff713ceSChristina Jacob {
1238cff713ceSChristina Jacob u32 bit_pos;
1239cff713ceSChristina Jacob
1240cff713ceSChristina Jacob /* Firmware does not support requesting multiple advertised modes
1241cff713ceSChristina Jacob * return first set bit
1242cff713ceSChristina Jacob */
1243cff713ceSChristina Jacob bit_pos = find_first_bit(cmd->link_modes.advertising,
1244cff713ceSChristina Jacob __ETHTOOL_LINK_MODE_MASK_NBITS);
1245cff713ceSChristina Jacob if (bit_pos != __ETHTOOL_LINK_MODE_MASK_NBITS)
1246cff713ceSChristina Jacob *mode = bit_pos;
1247cff713ceSChristina Jacob }
1248cff713ceSChristina Jacob
otx2_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)1249cff713ceSChristina Jacob static int otx2_set_link_ksettings(struct net_device *netdev,
1250cff713ceSChristina Jacob const struct ethtool_link_ksettings *cmd)
1251cff713ceSChristina Jacob {
1252cff713ceSChristina Jacob struct otx2_nic *pf = netdev_priv(netdev);
1253cff713ceSChristina Jacob struct ethtool_link_ksettings cur_ks;
1254cff713ceSChristina Jacob struct cgx_set_link_mode_req *req;
1255cff713ceSChristina Jacob struct mbox *mbox = &pf->mbox;
1256cff713ceSChristina Jacob int err = 0;
1257cff713ceSChristina Jacob
1258cff713ceSChristina Jacob memset(&cur_ks, 0, sizeof(struct ethtool_link_ksettings));
1259cff713ceSChristina Jacob
1260cff713ceSChristina Jacob if (!ethtool_validate_speed(cmd->base.speed) ||
1261cff713ceSChristina Jacob !ethtool_validate_duplex(cmd->base.duplex))
1262cff713ceSChristina Jacob return -EINVAL;
1263cff713ceSChristina Jacob
1264cff713ceSChristina Jacob if (cmd->base.autoneg != AUTONEG_ENABLE &&
1265cff713ceSChristina Jacob cmd->base.autoneg != AUTONEG_DISABLE)
1266cff713ceSChristina Jacob return -EINVAL;
1267cff713ceSChristina Jacob
1268cff713ceSChristina Jacob otx2_get_link_ksettings(netdev, &cur_ks);
1269cff713ceSChristina Jacob
1270cff713ceSChristina Jacob /* Check requested modes against supported modes by hardware */
12714973056cSSean Anderson if (!linkmode_subset(cmd->link_modes.advertising,
12724973056cSSean Anderson cur_ks.link_modes.supported))
1273cff713ceSChristina Jacob return -EINVAL;
1274cff713ceSChristina Jacob
1275cff713ceSChristina Jacob mutex_lock(&mbox->lock);
1276cff713ceSChristina Jacob req = otx2_mbox_alloc_msg_cgx_set_link_mode(&pf->mbox);
1277cff713ceSChristina Jacob if (!req) {
1278cff713ceSChristina Jacob err = -ENOMEM;
1279cff713ceSChristina Jacob goto end;
1280cff713ceSChristina Jacob }
1281cff713ceSChristina Jacob
1282cff713ceSChristina Jacob req->args.speed = cmd->base.speed;
1283cff713ceSChristina Jacob /* firmware expects 1 for half duplex and 0 for full duplex
1284cff713ceSChristina Jacob * hence inverting
1285cff713ceSChristina Jacob */
1286cff713ceSChristina Jacob req->args.duplex = cmd->base.duplex ^ 0x1;
1287cff713ceSChristina Jacob req->args.an = cmd->base.autoneg;
1288cff713ceSChristina Jacob otx2_get_advertised_mode(cmd, &req->args.mode);
1289cff713ceSChristina Jacob
1290cff713ceSChristina Jacob err = otx2_sync_mbox_msg(&pf->mbox);
1291cff713ceSChristina Jacob end:
1292cff713ceSChristina Jacob mutex_unlock(&mbox->lock);
1293cff713ceSChristina Jacob return err;
1294cff713ceSChristina Jacob }
1295cff713ceSChristina Jacob
otx2_get_fec_stats(struct net_device * netdev,struct ethtool_fec_stats * fec_stats)1296b441c4acSHariprasad Kelam static void otx2_get_fec_stats(struct net_device *netdev,
1297b441c4acSHariprasad Kelam struct ethtool_fec_stats *fec_stats)
1298b441c4acSHariprasad Kelam {
1299b441c4acSHariprasad Kelam struct otx2_nic *pfvf = netdev_priv(netdev);
1300b441c4acSHariprasad Kelam struct cgx_fw_data *rsp;
1301b441c4acSHariprasad Kelam
1302b441c4acSHariprasad Kelam otx2_update_lmac_fec_stats(pfvf);
1303b441c4acSHariprasad Kelam
1304b441c4acSHariprasad Kelam /* Report MAC FEC stats */
1305b441c4acSHariprasad Kelam fec_stats->corrected_blocks.total = pfvf->hw.cgx_fec_corr_blks;
1306b441c4acSHariprasad Kelam fec_stats->uncorrectable_blocks.total = pfvf->hw.cgx_fec_uncorr_blks;
1307b441c4acSHariprasad Kelam
1308b441c4acSHariprasad Kelam rsp = otx2_get_fwdata(pfvf);
1309b441c4acSHariprasad Kelam if (!IS_ERR(rsp) && rsp->fwdata.phy.misc.has_fec_stats &&
1310b441c4acSHariprasad Kelam !otx2_get_phy_fec_stats(pfvf)) {
1311b441c4acSHariprasad Kelam /* Fetch fwdata again because it's been recently populated with
1312b441c4acSHariprasad Kelam * latest PHY FEC stats.
1313b441c4acSHariprasad Kelam */
1314b441c4acSHariprasad Kelam rsp = otx2_get_fwdata(pfvf);
1315b441c4acSHariprasad Kelam if (!IS_ERR(rsp)) {
1316b441c4acSHariprasad Kelam struct fec_stats_s *p = &rsp->fwdata.phy.fec_stats;
1317b441c4acSHariprasad Kelam
1318b441c4acSHariprasad Kelam if (pfvf->linfo.fec == OTX2_FEC_BASER) {
1319b441c4acSHariprasad Kelam fec_stats->corrected_blocks.total = p->brfec_corr_blks;
1320b441c4acSHariprasad Kelam fec_stats->uncorrectable_blocks.total = p->brfec_uncorr_blks;
1321b441c4acSHariprasad Kelam } else {
1322b441c4acSHariprasad Kelam fec_stats->corrected_blocks.total = p->rsfec_corr_cws;
1323b441c4acSHariprasad Kelam fec_stats->uncorrectable_blocks.total = p->rsfec_uncorr_cws;
1324b441c4acSHariprasad Kelam }
1325b441c4acSHariprasad Kelam }
1326b441c4acSHariprasad Kelam }
1327b441c4acSHariprasad Kelam }
1328b441c4acSHariprasad Kelam
1329d45d8979SChristina Jacob static const struct ethtool_ops otx2_ethtool_ops = {
1330af7fcbbdSJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
13316e144b47SSuman Ghosh ETHTOOL_COALESCE_MAX_FRAMES |
13326e144b47SSuman Ghosh ETHTOOL_COALESCE_USE_ADAPTIVE,
133368258596SSubbaraya Sundeep .supported_ring_params = ETHTOOL_RING_USE_RX_BUF_LEN |
133468258596SSubbaraya Sundeep ETHTOOL_RING_USE_CQE_SIZE,
13356e92d71bSSunil Goutham .get_link = otx2_get_link,
1336d45d8979SChristina Jacob .get_drvinfo = otx2_get_drvinfo,
1337d45d8979SChristina Jacob .get_strings = otx2_get_strings,
1338d45d8979SChristina Jacob .get_ethtool_stats = otx2_get_ethtool_stats,
1339d45d8979SChristina Jacob .get_sset_count = otx2_get_sset_count,
1340d45d8979SChristina Jacob .set_channels = otx2_set_channels,
1341d45d8979SChristina Jacob .get_channels = otx2_get_channels,
1342d45d8979SChristina Jacob .get_ringparam = otx2_get_ringparam,
1343d45d8979SChristina Jacob .set_ringparam = otx2_set_ringparam,
1344d45d8979SChristina Jacob .get_coalesce = otx2_get_coalesce,
1345d45d8979SChristina Jacob .set_coalesce = otx2_set_coalesce,
13466e92d71bSSunil Goutham .get_rxnfc = otx2_get_rxnfc,
13476e92d71bSSunil Goutham .set_rxnfc = otx2_set_rxnfc,
13486e92d71bSSunil Goutham .get_rxfh_key_size = otx2_get_rxfh_key_size,
13496e92d71bSSunil Goutham .get_rxfh_indir_size = otx2_get_rxfh_indir_size,
13506e92d71bSSunil Goutham .get_rxfh = otx2_get_rxfh,
13516e92d71bSSunil Goutham .set_rxfh = otx2_set_rxfh,
135281a43620SGeetha sowjanya .get_rxfh_context = otx2_get_rxfh_context,
135381a43620SGeetha sowjanya .set_rxfh_context = otx2_set_rxfh_context,
13546e92d71bSSunil Goutham .get_msglevel = otx2_get_msglevel,
13556e92d71bSSunil Goutham .set_msglevel = otx2_set_msglevel,
135675f36270SGeetha sowjanya .get_pauseparam = otx2_get_pauseparam,
135775f36270SGeetha sowjanya .set_pauseparam = otx2_set_pauseparam,
1358c9c12d33SAleksey Makarov .get_ts_info = otx2_get_ts_info,
1359b441c4acSHariprasad Kelam .get_fec_stats = otx2_get_fec_stats,
1360d0cf9503SChristina Jacob .get_fecparam = otx2_get_fecparam,
1361d0cf9503SChristina Jacob .set_fecparam = otx2_set_fecparam,
13621a50280cSChristina Jacob .get_link_ksettings = otx2_get_link_ksettings,
1363cff713ceSChristina Jacob .set_link_ksettings = otx2_set_link_ksettings,
1364d45d8979SChristina Jacob };
1365d45d8979SChristina Jacob
otx2_set_ethtool_ops(struct net_device * netdev)1366d45d8979SChristina Jacob void otx2_set_ethtool_ops(struct net_device *netdev)
1367d45d8979SChristina Jacob {
1368d45d8979SChristina Jacob netdev->ethtool_ops = &otx2_ethtool_ops;
1369d45d8979SChristina Jacob }
137005c22b54STomasz Duszynski
137105c22b54STomasz Duszynski /* VF's ethtool APIs */
otx2vf_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)137205c22b54STomasz Duszynski static void otx2vf_get_drvinfo(struct net_device *netdev,
137305c22b54STomasz Duszynski struct ethtool_drvinfo *info)
137405c22b54STomasz Duszynski {
137505c22b54STomasz Duszynski struct otx2_nic *vf = netdev_priv(netdev);
137605c22b54STomasz Duszynski
1377f029c781SWolfram Sang strscpy(info->driver, DRV_VF_NAME, sizeof(info->driver));
1378f029c781SWolfram Sang strscpy(info->bus_info, pci_name(vf->pdev), sizeof(info->bus_info));
137905c22b54STomasz Duszynski }
138005c22b54STomasz Duszynski
otx2vf_get_strings(struct net_device * netdev,u32 sset,u8 * data)138105c22b54STomasz Duszynski static void otx2vf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
138205c22b54STomasz Duszynski {
138305c22b54STomasz Duszynski struct otx2_nic *vf = netdev_priv(netdev);
138405c22b54STomasz Duszynski int stats;
138505c22b54STomasz Duszynski
138605c22b54STomasz Duszynski if (sset != ETH_SS_STATS)
138705c22b54STomasz Duszynski return;
138805c22b54STomasz Duszynski
138905c22b54STomasz Duszynski for (stats = 0; stats < otx2_n_dev_stats; stats++) {
139005c22b54STomasz Duszynski memcpy(data, otx2_dev_stats[stats].name, ETH_GSTRING_LEN);
139105c22b54STomasz Duszynski data += ETH_GSTRING_LEN;
139205c22b54STomasz Duszynski }
139305c22b54STomasz Duszynski
139405c22b54STomasz Duszynski for (stats = 0; stats < otx2_n_drv_stats; stats++) {
139505c22b54STomasz Duszynski memcpy(data, otx2_drv_stats[stats].name, ETH_GSTRING_LEN);
139605c22b54STomasz Duszynski data += ETH_GSTRING_LEN;
139705c22b54STomasz Duszynski }
139805c22b54STomasz Duszynski
139905c22b54STomasz Duszynski otx2_get_qset_strings(vf, &data, 0);
140005c22b54STomasz Duszynski
140105c22b54STomasz Duszynski strcpy(data, "reset_count");
140205c22b54STomasz Duszynski data += ETH_GSTRING_LEN;
140305c22b54STomasz Duszynski }
140405c22b54STomasz Duszynski
otx2vf_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)140505c22b54STomasz Duszynski static void otx2vf_get_ethtool_stats(struct net_device *netdev,
140605c22b54STomasz Duszynski struct ethtool_stats *stats, u64 *data)
140705c22b54STomasz Duszynski {
140805c22b54STomasz Duszynski struct otx2_nic *vf = netdev_priv(netdev);
140905c22b54STomasz Duszynski int stat;
141005c22b54STomasz Duszynski
141105c22b54STomasz Duszynski otx2_get_dev_stats(vf);
141205c22b54STomasz Duszynski for (stat = 0; stat < otx2_n_dev_stats; stat++)
141305c22b54STomasz Duszynski *(data++) = ((u64 *)&vf->hw.dev_stats)
141405c22b54STomasz Duszynski [otx2_dev_stats[stat].index];
141505c22b54STomasz Duszynski
141605c22b54STomasz Duszynski for (stat = 0; stat < otx2_n_drv_stats; stat++)
141705c22b54STomasz Duszynski *(data++) = atomic_read(&((atomic_t *)&vf->hw.drv_stats)
141805c22b54STomasz Duszynski [otx2_drv_stats[stat].index]);
141905c22b54STomasz Duszynski
142005c22b54STomasz Duszynski otx2_get_qset_stats(vf, stats, &data);
142105c22b54STomasz Duszynski *(data++) = vf->reset_count;
142205c22b54STomasz Duszynski }
142305c22b54STomasz Duszynski
otx2vf_get_sset_count(struct net_device * netdev,int sset)142405c22b54STomasz Duszynski static int otx2vf_get_sset_count(struct net_device *netdev, int sset)
142505c22b54STomasz Duszynski {
142605c22b54STomasz Duszynski struct otx2_nic *vf = netdev_priv(netdev);
142705c22b54STomasz Duszynski int qstats_count;
142805c22b54STomasz Duszynski
142905c22b54STomasz Duszynski if (sset != ETH_SS_STATS)
143005c22b54STomasz Duszynski return -EINVAL;
143105c22b54STomasz Duszynski
143205c22b54STomasz Duszynski qstats_count = otx2_n_queue_stats *
14336cebb6a4SHariprasad Kelam (vf->hw.rx_queues + otx2_get_total_tx_queues(vf));
143405c22b54STomasz Duszynski
143505c22b54STomasz Duszynski return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + 1;
143605c22b54STomasz Duszynski }
143705c22b54STomasz Duszynski
otx2vf_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)14381a50280cSChristina Jacob static int otx2vf_get_link_ksettings(struct net_device *netdev,
14391a50280cSChristina Jacob struct ethtool_link_ksettings *cmd)
14401a50280cSChristina Jacob {
14411a50280cSChristina Jacob struct otx2_nic *pfvf = netdev_priv(netdev);
14421a50280cSChristina Jacob
14431a50280cSChristina Jacob if (is_otx2_lbkvf(pfvf->pdev)) {
14441a50280cSChristina Jacob cmd->base.duplex = DUPLEX_FULL;
14451a50280cSChristina Jacob cmd->base.speed = SPEED_100000;
14461a50280cSChristina Jacob } else {
14471a50280cSChristina Jacob return otx2_get_link_ksettings(netdev, cmd);
14481a50280cSChristina Jacob }
14491a50280cSChristina Jacob return 0;
14501a50280cSChristina Jacob }
14511a50280cSChristina Jacob
145205c22b54STomasz Duszynski static const struct ethtool_ops otx2vf_ethtool_ops = {
145305c22b54STomasz Duszynski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
1454619c010aSSuman Ghosh ETHTOOL_COALESCE_MAX_FRAMES |
1455619c010aSSuman Ghosh ETHTOOL_COALESCE_USE_ADAPTIVE,
145668258596SSubbaraya Sundeep .supported_ring_params = ETHTOOL_RING_USE_RX_BUF_LEN |
145768258596SSubbaraya Sundeep ETHTOOL_RING_USE_CQE_SIZE,
145805c22b54STomasz Duszynski .get_link = otx2_get_link,
145905c22b54STomasz Duszynski .get_drvinfo = otx2vf_get_drvinfo,
146005c22b54STomasz Duszynski .get_strings = otx2vf_get_strings,
146105c22b54STomasz Duszynski .get_ethtool_stats = otx2vf_get_ethtool_stats,
146205c22b54STomasz Duszynski .get_sset_count = otx2vf_get_sset_count,
146305c22b54STomasz Duszynski .set_channels = otx2_set_channels,
146405c22b54STomasz Duszynski .get_channels = otx2_get_channels,
14653cffaed2SRakesh Babu .get_rxnfc = otx2_get_rxnfc,
14663cffaed2SRakesh Babu .set_rxnfc = otx2_set_rxnfc,
146705c22b54STomasz Duszynski .get_rxfh_key_size = otx2_get_rxfh_key_size,
146805c22b54STomasz Duszynski .get_rxfh_indir_size = otx2_get_rxfh_indir_size,
146905c22b54STomasz Duszynski .get_rxfh = otx2_get_rxfh,
147005c22b54STomasz Duszynski .set_rxfh = otx2_set_rxfh,
147181a43620SGeetha sowjanya .get_rxfh_context = otx2_get_rxfh_context,
147281a43620SGeetha sowjanya .set_rxfh_context = otx2_set_rxfh_context,
147305c22b54STomasz Duszynski .get_ringparam = otx2_get_ringparam,
147405c22b54STomasz Duszynski .set_ringparam = otx2_set_ringparam,
147505c22b54STomasz Duszynski .get_coalesce = otx2_get_coalesce,
147605c22b54STomasz Duszynski .set_coalesce = otx2_set_coalesce,
147705c22b54STomasz Duszynski .get_msglevel = otx2_get_msglevel,
147805c22b54STomasz Duszynski .set_msglevel = otx2_set_msglevel,
147905c22b54STomasz Duszynski .get_pauseparam = otx2_get_pauseparam,
148005c22b54STomasz Duszynski .set_pauseparam = otx2_set_pauseparam,
14811a50280cSChristina Jacob .get_link_ksettings = otx2vf_get_link_ksettings,
148243510ef4SNaveen Mamindlapalli .get_ts_info = otx2_get_ts_info,
148305c22b54STomasz Duszynski };
148405c22b54STomasz Duszynski
otx2vf_set_ethtool_ops(struct net_device * netdev)148505c22b54STomasz Duszynski void otx2vf_set_ethtool_ops(struct net_device *netdev)
148605c22b54STomasz Duszynski {
148705c22b54STomasz Duszynski netdev->ethtool_ops = &otx2vf_ethtool_ops;
148805c22b54STomasz Duszynski }
148905c22b54STomasz Duszynski EXPORT_SYMBOL(otx2vf_set_ethtool_ops);
1490