1 /*
2  *   Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
3  *   Copyright (c) 2014, I2SE GmbH
4  *
5  *   Permission to use, copy, modify, and/or distribute this software
6  *   for any purpose with or without fee is hereby granted, provided
7  *   that the above copyright notice and this permission notice appear
8  *   in all copies.
9  *
10  *   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  *   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  *   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
13  *   THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
14  *   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  *   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16  *   NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17  *   CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*   This file contains debugging routines for use in the QCA7K driver.
21  */
22 
23 #include <linux/debugfs.h>
24 #include <linux/ethtool.h>
25 #include <linux/seq_file.h>
26 #include <linux/types.h>
27 
28 #include "qca_7k.h"
29 #include "qca_debug.h"
30 
31 #define QCASPI_MAX_REGS 0x20
32 
33 static const u16 qcaspi_spi_regs[] = {
34 	SPI_REG_BFR_SIZE,
35 	SPI_REG_WRBUF_SPC_AVA,
36 	SPI_REG_RDBUF_BYTE_AVA,
37 	SPI_REG_SPI_CONFIG,
38 	SPI_REG_SPI_STATUS,
39 	SPI_REG_INTR_CAUSE,
40 	SPI_REG_INTR_ENABLE,
41 	SPI_REG_RDBUF_WATERMARK,
42 	SPI_REG_WRBUF_WATERMARK,
43 	SPI_REG_SIGNATURE,
44 	SPI_REG_ACTION_CTRL
45 };
46 
47 /* The order of these strings must match the order of the fields in
48  * struct qcaspi_stats
49  * See qca_spi.h
50  */
51 static const char qcaspi_gstrings_stats[][ETH_GSTRING_LEN] = {
52 	"Triggered resets",
53 	"Device resets",
54 	"Reset timeouts",
55 	"Read errors",
56 	"Write errors",
57 	"Read buffer errors",
58 	"Write buffer errors",
59 	"Out of memory",
60 	"Write buffer misses",
61 	"Transmit ring full",
62 	"SPI errors",
63 	"Write verify errors",
64 	"Buffer available errors",
65 	"Bad signature",
66 };
67 
68 #ifdef CONFIG_DEBUG_FS
69 
70 static int
qcaspi_info_show(struct seq_file * s,void * what)71 qcaspi_info_show(struct seq_file *s, void *what)
72 {
73 	struct qcaspi *qca = s->private;
74 
75 	seq_printf(s, "RX buffer size   : %lu\n",
76 		   (unsigned long)qca->buffer_size);
77 
78 	seq_puts(s, "TX ring state    : ");
79 
80 	if (qca->txr.skb[qca->txr.head] == NULL)
81 		seq_puts(s, "empty");
82 	else if (qca->txr.skb[qca->txr.tail])
83 		seq_puts(s, "full");
84 	else
85 		seq_puts(s, "in use");
86 
87 	seq_puts(s, "\n");
88 
89 	seq_printf(s, "TX ring size     : %u\n",
90 		   qca->txr.size);
91 
92 	seq_printf(s, "Sync state       : %u (",
93 		   (unsigned int)qca->sync);
94 	switch (qca->sync) {
95 	case QCASPI_SYNC_UNKNOWN:
96 		seq_puts(s, "QCASPI_SYNC_UNKNOWN");
97 		break;
98 	case QCASPI_SYNC_RESET:
99 		seq_puts(s, "QCASPI_SYNC_RESET");
100 		break;
101 	case QCASPI_SYNC_READY:
102 		seq_puts(s, "QCASPI_SYNC_READY");
103 		break;
104 	default:
105 		seq_puts(s, "INVALID");
106 		break;
107 	}
108 	seq_puts(s, ")\n");
109 
110 	seq_printf(s, "IRQ              : %d\n",
111 		   qca->spi_dev->irq);
112 	seq_printf(s, "INTR REQ         : %u\n",
113 		   qca->intr_req);
114 	seq_printf(s, "INTR SVC         : %u\n",
115 		   qca->intr_svc);
116 
117 	seq_printf(s, "SPI max speed    : %lu\n",
118 		   (unsigned long)qca->spi_dev->max_speed_hz);
119 	seq_printf(s, "SPI mode         : %x\n",
120 		   qca->spi_dev->mode);
121 	seq_printf(s, "SPI chip select  : %u\n",
122 		   (unsigned int)qca->spi_dev->chip_select);
123 	seq_printf(s, "SPI legacy mode  : %u\n",
124 		   (unsigned int)qca->legacy_mode);
125 	seq_printf(s, "SPI burst length : %u\n",
126 		   (unsigned int)qca->burst_len);
127 
128 	return 0;
129 }
130 DEFINE_SHOW_ATTRIBUTE(qcaspi_info);
131 
132 void
qcaspi_init_device_debugfs(struct qcaspi * qca)133 qcaspi_init_device_debugfs(struct qcaspi *qca)
134 {
135 	qca->device_root = debugfs_create_dir(dev_name(&qca->net_dev->dev),
136 					      NULL);
137 
138 	debugfs_create_file("info", S_IFREG | 0444, qca->device_root, qca,
139 			    &qcaspi_info_fops);
140 }
141 
142 void
qcaspi_remove_device_debugfs(struct qcaspi * qca)143 qcaspi_remove_device_debugfs(struct qcaspi *qca)
144 {
145 	debugfs_remove_recursive(qca->device_root);
146 }
147 
148 #else /* CONFIG_DEBUG_FS */
149 
150 void
qcaspi_init_device_debugfs(struct qcaspi * qca)151 qcaspi_init_device_debugfs(struct qcaspi *qca)
152 {
153 }
154 
155 void
qcaspi_remove_device_debugfs(struct qcaspi * qca)156 qcaspi_remove_device_debugfs(struct qcaspi *qca)
157 {
158 }
159 
160 #endif
161 
162 static void
qcaspi_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * p)163 qcaspi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *p)
164 {
165 	struct qcaspi *qca = netdev_priv(dev);
166 
167 	strlcpy(p->driver, QCASPI_DRV_NAME, sizeof(p->driver));
168 	strlcpy(p->version, QCASPI_DRV_VERSION, sizeof(p->version));
169 	strlcpy(p->fw_version, "QCA7000", sizeof(p->fw_version));
170 	strlcpy(p->bus_info, dev_name(&qca->spi_dev->dev),
171 		sizeof(p->bus_info));
172 }
173 
174 static int
qcaspi_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)175 qcaspi_get_link_ksettings(struct net_device *dev,
176 			  struct ethtool_link_ksettings *cmd)
177 {
178 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
179 	ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half);
180 
181 	cmd->base.speed = SPEED_10;
182 	cmd->base.duplex = DUPLEX_HALF;
183 	cmd->base.port = PORT_OTHER;
184 	cmd->base.autoneg = AUTONEG_DISABLE;
185 
186 	return 0;
187 }
188 
189 static void
qcaspi_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * estats,u64 * data)190 qcaspi_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *data)
191 {
192 	struct qcaspi *qca = netdev_priv(dev);
193 	struct qcaspi_stats *st = &qca->stats;
194 
195 	memcpy(data, st, ARRAY_SIZE(qcaspi_gstrings_stats) * sizeof(u64));
196 }
197 
198 static void
qcaspi_get_strings(struct net_device * dev,u32 stringset,u8 * buf)199 qcaspi_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
200 {
201 	switch (stringset) {
202 	case ETH_SS_STATS:
203 		memcpy(buf, &qcaspi_gstrings_stats,
204 		       sizeof(qcaspi_gstrings_stats));
205 		break;
206 	default:
207 		WARN_ON(1);
208 		break;
209 	}
210 }
211 
212 static int
qcaspi_get_sset_count(struct net_device * dev,int sset)213 qcaspi_get_sset_count(struct net_device *dev, int sset)
214 {
215 	switch (sset) {
216 	case ETH_SS_STATS:
217 		return ARRAY_SIZE(qcaspi_gstrings_stats);
218 	default:
219 		return -EINVAL;
220 	}
221 }
222 
223 static int
qcaspi_get_regs_len(struct net_device * dev)224 qcaspi_get_regs_len(struct net_device *dev)
225 {
226 	return sizeof(u32) * QCASPI_MAX_REGS;
227 }
228 
229 static void
qcaspi_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * p)230 qcaspi_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
231 {
232 	struct qcaspi *qca = netdev_priv(dev);
233 	u32 *regs_buff = p;
234 	unsigned int i;
235 
236 	regs->version = 1;
237 	memset(regs_buff, 0, sizeof(u32) * QCASPI_MAX_REGS);
238 
239 	for (i = 0; i < ARRAY_SIZE(qcaspi_spi_regs); i++) {
240 		u16 offset, value;
241 
242 		qcaspi_read_register(qca, qcaspi_spi_regs[i], &value);
243 		offset = qcaspi_spi_regs[i] >> 8;
244 		regs_buff[offset] = value;
245 	}
246 }
247 
248 static void
qcaspi_get_ringparam(struct net_device * dev,struct ethtool_ringparam * ring)249 qcaspi_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
250 {
251 	struct qcaspi *qca = netdev_priv(dev);
252 
253 	ring->rx_max_pending = 4;
254 	ring->tx_max_pending = TX_RING_MAX_LEN;
255 	ring->rx_pending = 4;
256 	ring->tx_pending = qca->txr.count;
257 }
258 
259 static int
qcaspi_set_ringparam(struct net_device * dev,struct ethtool_ringparam * ring)260 qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
261 {
262 	const struct net_device_ops *ops = dev->netdev_ops;
263 	struct qcaspi *qca = netdev_priv(dev);
264 
265 	if ((ring->rx_pending) ||
266 	    (ring->rx_mini_pending) ||
267 	    (ring->rx_jumbo_pending))
268 		return -EINVAL;
269 
270 	if (netif_running(dev))
271 		ops->ndo_stop(dev);
272 
273 	qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
274 	qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);
275 
276 	if (netif_running(dev))
277 		ops->ndo_open(dev);
278 
279 	return 0;
280 }
281 
282 static const struct ethtool_ops qcaspi_ethtool_ops = {
283 	.get_drvinfo = qcaspi_get_drvinfo,
284 	.get_link = ethtool_op_get_link,
285 	.get_ethtool_stats = qcaspi_get_ethtool_stats,
286 	.get_strings = qcaspi_get_strings,
287 	.get_sset_count = qcaspi_get_sset_count,
288 	.get_regs_len = qcaspi_get_regs_len,
289 	.get_regs = qcaspi_get_regs,
290 	.get_ringparam = qcaspi_get_ringparam,
291 	.set_ringparam = qcaspi_set_ringparam,
292 	.get_link_ksettings = qcaspi_get_link_ksettings,
293 };
294 
qcaspi_set_ethtool_ops(struct net_device * dev)295 void qcaspi_set_ethtool_ops(struct net_device *dev)
296 {
297 	dev->ethtool_ops = &qcaspi_ethtool_ops;
298 }
299