Add ability to read some mib values.
The code from marvel only writes mib stat values to the console which
is less than useful. Provide a way to read the stats we care about.
Change-Id: I28766441e1004de2e34623e44a5f1c9f2bcd4a04
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile
index 866029a..627471c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile
@@ -16,12 +16,14 @@
ifeq ($(CONFIG_MV_ETH_NFP_LIB),y)
obj-$(CONFIG_MV_ETHERNET) += mv_netdev.o mv_ethernet.o mv_eth_sysfs.o
+ obj-$(CONFIG_MV_ETHERNET) += goog_eth_sysfs.o
obj-$(CONFIG_MV_PON) += mv_pon_sysfs.o
obj-$(CONFIG_MV_ETH_SWITCH) += mv_eth_switch.o
obj-$(CONFIG_MV_ETH_TOOL) += mv_eth_tool.o
obj-y += ../nfplib.a
else
obj-$(CONFIG_MV_ETHERNET) += mv_netdev.o mv_ethernet.o mv_eth_sysfs.o
+ obj-$(CONFIG_MV_ETHERNET) += goog_eth_sysfs.o
obj-$(CONFIG_MV_PON) += mv_pon_sysfs.o
obj-$(CONFIG_MV_ETH_SWITCH) += mv_eth_switch.o
obj-$(CONFIG_MV_ETH_TOOL) += mv_eth_tool.o
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/goog_eth_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/goog_eth_sysfs.c
new file mode 100755
index 0000000..a359ad5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/goog_eth_sysfs.c
@@ -0,0 +1,145 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Google, 2013
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "gbe/mvNeta.h"
+#include "mv_netdev.h"
+
+struct goog_net_attribute {
+ struct device_attribute dev_attr;
+ uint64_t val;
+ uint32_t mib;
+ uint32_t port;
+};
+
+#define GOOG_ATTR(_name, _portname, _show, _mib, _port) \
+ struct goog_net_attribute goog_attr_##_name##_##_portname = { \
+ .dev_attr = __ATTR(_name, S_IRUSR, _show, NULL), \
+ .mib= _mib, \
+ .port = _port, \
+ }
+
+static ssize_t goog_get_stat(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ MV_U32 reg_low, reg_high = 0;
+ uint64_t reg_val;
+ struct goog_net_attribute *goog_attr = container_of(attr, struct goog_net_attribute, dev_attr);
+ // These mib registers are clear on read.
+ reg_low = mvNetaMibCounterRead(goog_attr->port, 0, goog_attr->mib, ®_high);
+ reg_val = ((uint64_t)reg_high) << 32 | (uint64_t)reg_low;
+ goog_attr->val += reg_val;
+ return sprintf(buf, "%llu\n", goog_attr->val);
+}
+
+// Stats for the UNI port.
+static GOOG_ATTR(rx_good_packets, uni, goog_get_stat, ETH_MIB_GOOD_FRAMES_RECEIVED, 0);
+static GOOG_ATTR(rx_bad_packets, uni, goog_get_stat, ETH_MIB_BAD_FRAMES_RECEIVED, 0);
+static GOOG_ATTR(rx_broadcast_packets, uni, goog_get_stat, ETH_MIB_BROADCAST_FRAMES_RECEIVED, 0);
+static GOOG_ATTR(rx_multicast_packets, uni, goog_get_stat, ETH_MIB_MULTICAST_FRAMES_RECEIVED, 0);
+static GOOG_ATTR(tx_good_packets, uni, goog_get_stat, ETH_MIB_GOOD_FRAMES_SENT, 0);
+static GOOG_ATTR(tx_broadcast_packets, uni, goog_get_stat, ETH_MIB_BROADCAST_FRAMES_SENT, 0);
+static GOOG_ATTR(tx_multicast_packets, uni, goog_get_stat, ETH_MIB_MULTICAST_FRAMES_SENT, 0);
+
+static struct attribute *goog_uni_attrs[] = {
+ &goog_attr_rx_good_packets_uni.dev_attr.attr,
+ &goog_attr_rx_bad_packets_uni.dev_attr.attr,
+ &goog_attr_rx_multicast_packets_uni.dev_attr.attr,
+ &goog_attr_rx_broadcast_packets_uni.dev_attr.attr,
+ &goog_attr_tx_good_packets_uni.dev_attr.attr,
+ &goog_attr_tx_broadcast_packets_uni.dev_attr.attr,
+ &goog_attr_tx_multicast_packets_uni.dev_attr.attr,
+ NULL
+};
+
+
+static struct attribute_group goog_uni_stats = {
+ .name = "unistats",
+ .attrs = goog_uni_attrs,
+};
+
+
+// Stats for the ANI port.
+static GOOG_ATTR(rx_good_packets, ani, goog_get_stat, ETH_MIB_GOOD_FRAMES_RECEIVED, MV_PON_PORT_ID);
+static GOOG_ATTR(rx_bad_packets, ani, goog_get_stat, ETH_MIB_BAD_FRAMES_RECEIVED, MV_PON_PORT_ID);
+static GOOG_ATTR(rx_broadcast_packets, ani, goog_get_stat, ETH_MIB_BROADCAST_FRAMES_RECEIVED, MV_PON_PORT_ID);
+static GOOG_ATTR(rx_multicast_packets, ani, goog_get_stat, ETH_MIB_MULTICAST_FRAMES_RECEIVED, MV_PON_PORT_ID);
+static GOOG_ATTR(tx_good_packets, ani, goog_get_stat, ETH_MIB_GOOD_FRAMES_SENT, MV_PON_PORT_ID);
+static GOOG_ATTR(tx_broadcast_packets, ani, goog_get_stat, ETH_MIB_BROADCAST_FRAMES_SENT, MV_PON_PORT_ID);
+static GOOG_ATTR(tx_multicast_packets, ani, goog_get_stat, ETH_MIB_MULTICAST_FRAMES_SENT, MV_PON_PORT_ID);
+
+static struct attribute *goog_ani_attrs[] = {
+ &goog_attr_rx_good_packets_ani.dev_attr.attr,
+ &goog_attr_rx_bad_packets_ani.dev_attr.attr,
+ &goog_attr_rx_multicast_packets_ani.dev_attr.attr,
+ &goog_attr_rx_broadcast_packets_ani.dev_attr.attr,
+ &goog_attr_tx_good_packets_ani.dev_attr.attr,
+ &goog_attr_tx_broadcast_packets_ani.dev_attr.attr,
+ &goog_attr_tx_multicast_packets_ani.dev_attr.attr,
+ NULL
+};
+
+static struct attribute_group goog_ani_stats = {
+ .name = "anistats",
+ .attrs = goog_ani_attrs,
+};
+
+int __devinit goog_eth_sysfs_init(void)
+{
+ int err = 0;
+ struct device *pd = NULL;
+
+ pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+ if (!pd) {
+ platform_device_register_simple("neta", -1, NULL, 0);
+ pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+ }
+
+ if (!pd) {
+ printk(KERN_ERR"%s: cannot find neta device\n", __func__);
+ pd = &platform_bus;
+ }
+
+ err = sysfs_create_group(&pd->kobj, &goog_uni_stats);
+ if (err) {
+ printk(KERN_INFO "sysfs group failed %d\n", err);
+ goto out;
+ }
+
+ err = sysfs_create_group(&pd->kobj, &goog_ani_stats);
+ if (err) {
+ printk(KERN_INFO "sysfs group failed %d\n", err);
+ goto out;
+ }
+out:
+ return err;
+}
+
+
+
+module_init(goog_eth_sysfs_init);
+
+MODULE_AUTHOR("jnewlin@google.com");
+MODULE_DESCRIPTION("Readable netstats for Marvell 6601.");
+MODULE_LICENSE("GPL");