1846a86e2SMadalin Bucur /* Copyright 2008-2016 Freescale Semiconductor Inc.
2846a86e2SMadalin Bucur  *
3846a86e2SMadalin Bucur  * Redistribution and use in source and binary forms, with or without
4846a86e2SMadalin Bucur  * modification, are permitted provided that the following conditions are met:
5846a86e2SMadalin Bucur  *     * Redistributions of source code must retain the above copyright
6846a86e2SMadalin Bucur  *	 notice, this list of conditions and the following disclaimer.
7846a86e2SMadalin Bucur  *     * Redistributions in binary form must reproduce the above copyright
8846a86e2SMadalin Bucur  *	 notice, this list of conditions and the following disclaimer in the
9846a86e2SMadalin Bucur  *	 documentation and/or other materials provided with the distribution.
10846a86e2SMadalin Bucur  *     * Neither the name of Freescale Semiconductor nor the
11846a86e2SMadalin Bucur  *	 names of its contributors may be used to endorse or promote products
12846a86e2SMadalin Bucur  *	 derived from this software without specific prior written permission.
13846a86e2SMadalin Bucur  *
14846a86e2SMadalin Bucur  *
15846a86e2SMadalin Bucur  * ALTERNATIVELY, this software may be distributed under the terms of the
16846a86e2SMadalin Bucur  * GNU General Public License ("GPL") as published by the Free Software
17846a86e2SMadalin Bucur  * Foundation, either version 2 of that License or (at your option) any
18846a86e2SMadalin Bucur  * later version.
19846a86e2SMadalin Bucur  *
20846a86e2SMadalin Bucur  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
21846a86e2SMadalin Bucur  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22846a86e2SMadalin Bucur  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23846a86e2SMadalin Bucur  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
24846a86e2SMadalin Bucur  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25846a86e2SMadalin Bucur  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26846a86e2SMadalin Bucur  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27846a86e2SMadalin Bucur  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28846a86e2SMadalin Bucur  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29846a86e2SMadalin Bucur  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30846a86e2SMadalin Bucur  */
31846a86e2SMadalin Bucur 
32846a86e2SMadalin Bucur #include <linux/init.h>
33846a86e2SMadalin Bucur #include <linux/module.h>
34846a86e2SMadalin Bucur #include <linux/io.h>
35846a86e2SMadalin Bucur #include <linux/of_net.h>
36846a86e2SMadalin Bucur #include "dpaa_eth.h"
37846a86e2SMadalin Bucur #include "mac.h"
38846a86e2SMadalin Bucur 
39846a86e2SMadalin Bucur static ssize_t dpaa_eth_show_addr(struct device *dev,
40846a86e2SMadalin Bucur 				  struct device_attribute *attr, char *buf)
41846a86e2SMadalin Bucur {
42846a86e2SMadalin Bucur 	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
43846a86e2SMadalin Bucur 	struct mac_device *mac_dev = priv->mac_dev;
44846a86e2SMadalin Bucur 
45846a86e2SMadalin Bucur 	if (mac_dev)
46846a86e2SMadalin Bucur 		return sprintf(buf, "%llx",
47846a86e2SMadalin Bucur 				(unsigned long long)mac_dev->res->start);
48846a86e2SMadalin Bucur 	else
49846a86e2SMadalin Bucur 		return sprintf(buf, "none");
50846a86e2SMadalin Bucur }
51846a86e2SMadalin Bucur 
52846a86e2SMadalin Bucur static ssize_t dpaa_eth_show_fqids(struct device *dev,
53846a86e2SMadalin Bucur 				   struct device_attribute *attr, char *buf)
54846a86e2SMadalin Bucur {
55846a86e2SMadalin Bucur 	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
56846a86e2SMadalin Bucur 	struct dpaa_fq *prev = NULL;
57846a86e2SMadalin Bucur 	char *prevstr = NULL;
58846a86e2SMadalin Bucur 	struct dpaa_fq *tmp;
59846a86e2SMadalin Bucur 	struct dpaa_fq *fq;
60846a86e2SMadalin Bucur 	u32 first_fqid = 0;
61846a86e2SMadalin Bucur 	u32 last_fqid = 0;
62846a86e2SMadalin Bucur 	ssize_t bytes = 0;
63846a86e2SMadalin Bucur 	char *str;
64846a86e2SMadalin Bucur 	int i = 0;
65846a86e2SMadalin Bucur 
66846a86e2SMadalin Bucur 	list_for_each_entry_safe(fq, tmp, &priv->dpaa_fq_list, list) {
67846a86e2SMadalin Bucur 		switch (fq->fq_type) {
68846a86e2SMadalin Bucur 		case FQ_TYPE_RX_DEFAULT:
69846a86e2SMadalin Bucur 			str = "Rx default";
70846a86e2SMadalin Bucur 			break;
71846a86e2SMadalin Bucur 		case FQ_TYPE_RX_ERROR:
72846a86e2SMadalin Bucur 			str = "Rx error";
73846a86e2SMadalin Bucur 			break;
74846a86e2SMadalin Bucur 		case FQ_TYPE_TX_CONFIRM:
75846a86e2SMadalin Bucur 			str = "Tx default confirmation";
76846a86e2SMadalin Bucur 			break;
77846a86e2SMadalin Bucur 		case FQ_TYPE_TX_CONF_MQ:
78846a86e2SMadalin Bucur 			str = "Tx confirmation (mq)";
79846a86e2SMadalin Bucur 			break;
80846a86e2SMadalin Bucur 		case FQ_TYPE_TX_ERROR:
81846a86e2SMadalin Bucur 			str = "Tx error";
82846a86e2SMadalin Bucur 			break;
83846a86e2SMadalin Bucur 		case FQ_TYPE_TX:
84846a86e2SMadalin Bucur 			str = "Tx";
85846a86e2SMadalin Bucur 			break;
86846a86e2SMadalin Bucur 		default:
87846a86e2SMadalin Bucur 			str = "Unknown";
88846a86e2SMadalin Bucur 		}
89846a86e2SMadalin Bucur 
90846a86e2SMadalin Bucur 		if (prev && (abs(fq->fqid - prev->fqid) != 1 ||
91846a86e2SMadalin Bucur 			     str != prevstr)) {
92846a86e2SMadalin Bucur 			if (last_fqid == first_fqid)
93846a86e2SMadalin Bucur 				bytes += sprintf(buf + bytes,
94846a86e2SMadalin Bucur 					"%s: %d\n", prevstr, prev->fqid);
95846a86e2SMadalin Bucur 			else
96846a86e2SMadalin Bucur 				bytes += sprintf(buf + bytes,
97846a86e2SMadalin Bucur 					"%s: %d - %d\n", prevstr,
98846a86e2SMadalin Bucur 					first_fqid, last_fqid);
99846a86e2SMadalin Bucur 		}
100846a86e2SMadalin Bucur 
101846a86e2SMadalin Bucur 		if (prev && abs(fq->fqid - prev->fqid) == 1 &&
102846a86e2SMadalin Bucur 		    str == prevstr) {
103846a86e2SMadalin Bucur 			last_fqid = fq->fqid;
104846a86e2SMadalin Bucur 		} else {
105846a86e2SMadalin Bucur 			first_fqid = fq->fqid;
106846a86e2SMadalin Bucur 			last_fqid = fq->fqid;
107846a86e2SMadalin Bucur 		}
108846a86e2SMadalin Bucur 
109846a86e2SMadalin Bucur 		prev = fq;
110846a86e2SMadalin Bucur 		prevstr = str;
111846a86e2SMadalin Bucur 		i++;
112846a86e2SMadalin Bucur 	}
113846a86e2SMadalin Bucur 
114846a86e2SMadalin Bucur 	if (prev) {
115846a86e2SMadalin Bucur 		if (last_fqid == first_fqid)
116846a86e2SMadalin Bucur 			bytes += sprintf(buf + bytes, "%s: %d\n", prevstr,
117846a86e2SMadalin Bucur 					prev->fqid);
118846a86e2SMadalin Bucur 		else
119846a86e2SMadalin Bucur 			bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr,
120846a86e2SMadalin Bucur 					first_fqid, last_fqid);
121846a86e2SMadalin Bucur 	}
122846a86e2SMadalin Bucur 
123846a86e2SMadalin Bucur 	return bytes;
124846a86e2SMadalin Bucur }
125846a86e2SMadalin Bucur 
126846a86e2SMadalin Bucur static ssize_t dpaa_eth_show_bpids(struct device *dev,
127846a86e2SMadalin Bucur 				   struct device_attribute *attr, char *buf)
128846a86e2SMadalin Bucur {
129846a86e2SMadalin Bucur 	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
130846a86e2SMadalin Bucur 	ssize_t bytes = 0;
131846a86e2SMadalin Bucur 	int i = 0;
132846a86e2SMadalin Bucur 
133846a86e2SMadalin Bucur 	for (i = 0; i < DPAA_BPS_NUM; i++)
134846a86e2SMadalin Bucur 		bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, "%u\n",
135846a86e2SMadalin Bucur 				  priv->dpaa_bps[i]->bpid);
136846a86e2SMadalin Bucur 
137846a86e2SMadalin Bucur 	return bytes;
138846a86e2SMadalin Bucur }
139846a86e2SMadalin Bucur 
140846a86e2SMadalin Bucur static struct device_attribute dpaa_eth_attrs[] = {
141846a86e2SMadalin Bucur 	__ATTR(device_addr, 0444, dpaa_eth_show_addr, NULL),
142846a86e2SMadalin Bucur 	__ATTR(fqids, 0444, dpaa_eth_show_fqids, NULL),
143846a86e2SMadalin Bucur 	__ATTR(bpids, 0444, dpaa_eth_show_bpids, NULL),
144846a86e2SMadalin Bucur };
145846a86e2SMadalin Bucur 
146846a86e2SMadalin Bucur void dpaa_eth_sysfs_init(struct device *dev)
147846a86e2SMadalin Bucur {
148846a86e2SMadalin Bucur 	int i;
149846a86e2SMadalin Bucur 
150846a86e2SMadalin Bucur 	for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
151846a86e2SMadalin Bucur 		if (device_create_file(dev, &dpaa_eth_attrs[i])) {
152846a86e2SMadalin Bucur 			dev_err(dev, "Error creating sysfs file\n");
153846a86e2SMadalin Bucur 			while (i > 0)
154846a86e2SMadalin Bucur 				device_remove_file(dev, &dpaa_eth_attrs[--i]);
155846a86e2SMadalin Bucur 			return;
156846a86e2SMadalin Bucur 		}
157846a86e2SMadalin Bucur }
158846a86e2SMadalin Bucur 
159846a86e2SMadalin Bucur void dpaa_eth_sysfs_remove(struct device *dev)
160846a86e2SMadalin Bucur {
161846a86e2SMadalin Bucur 	int i;
162846a86e2SMadalin Bucur 
163846a86e2SMadalin Bucur 	for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
164846a86e2SMadalin Bucur 		device_remove_file(dev, &dpaa_eth_attrs[i]);
165846a86e2SMadalin Bucur }
166