blob: 4e8c2b7b144952dd0755ea72df3e20bf0ee62039 [file] [log] [blame]
/* l2fw_sysfs.c */
#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 "mvTypes.h"
#include "mv_eth_l2fw.h"
#include "linux/inet.h"
#ifdef CONFIG_MV_ETH_L2SEC
extern int l2fw_set_cesa_chan(int port, int cesaChan);
#endif
static ssize_t l2fw_help(char *buf)
{
int off = 0;
off += sprintf(buf+off, "help\n");
off += sprintf(buf+off, "echo mode rxp txp > l2fw - set l2f <rxp>->");
off += sprintf(buf+off, "<txp><mode> 0-dis,1-as_is,2-swap,3-copy\n");
off += sprintf(buf+off, "echo threshold > l2fw_xor: set threshold\n");
#ifdef CONFIG_MV_ETH_L2SEC
off += sprintf(buf+off, "echo 1 > esp - enable ESP\n");
#endif
off += sprintf(buf+off, "cat dump - display L2fw rules DB\n");
off += sprintf(buf+off, "echo 1 > flush - flush L2fw rules DB\n");
return off;
}
static ssize_t l2fw_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const char *name = attr->attr.name;
int off = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (!strcmp(name, "help")) {
off = l2fw_help(buf);
return off;
}
if (!strcmp(name, "dump")) {
l2fw_dump();
return off;
}
if (!strcmp(name, "numHashEntries")) {
l2fw_show_numHashEntries();
return off;
}
#ifdef CONFIG_MV_ETH_L2SEC
if (!strcmp(name, "esp")) {
l2fw_esp_show();
return off;
}
#endif
if (!strcmp(name, "help")) {
off = l2fw_help(buf);
return off;
}
#ifdef CONFIG_MV_ETH_L2SEC
if (!strcmp(name, "stats")) {
l2fw_stats();
return off;
}
#endif
return off;
}
static ssize_t l2fw_hex_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
{
const char *name = attr->attr.name;
int err;
unsigned int addr1, addr2;
int port;
unsigned long flags;
#ifdef CONFIG_MV_ETH_L2SEC
int enableEsp;
#endif
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = addr1 = addr2 = port = 0;
local_irq_save(flags);
if (!strcmp(name, "l2fw_add")) {
sscanf(buf, "%x %x %d", &addr1, &addr2, &port);
l2fw_add(addr1, addr2, port);
} else if (!strcmp(name, "l2fw_add_ip")) {
l2fw_add_ip(buf);
#ifdef CONFIG_MV_ETH_L2SEC
} else if (!strcmp(name, "esp")) {
sscanf(buf, "%d", &enableEsp);
l2fw_esp_set(enableEsp);
#endif
} else if (!strcmp(name, "flush")) {
l2fw_flush();
}
local_irq_restore(flags);
return err ? -EINVAL : len;
}
static ssize_t l2fw_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
const char *name = attr->attr.name;
int err;
unsigned int p, txp, txq, v;
unsigned long flags;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = p = txp = txq = v = 0;
sscanf(buf, "%d %d %d %d", &p, &txp, &txq, &v);
local_irq_save(flags);
if (!strcmp(name, "l2fw_xor"))
l2fw_xor(p);
else if (!strcmp(name, "l2fw"))
l2fw(p, txp, txq);
#ifdef CONFIG_MV_ETH_L2SEC
else if (!strcmp(name, "cesa_chan"))
err = l2fw_set_cesa_chan(p, txp);
#endif
local_irq_restore(flags);
if (err)
mvOsPrintf("%s: error %d\n", __func__, err);
return err ? -EINVAL : len;
}
static DEVICE_ATTR(l2fw, S_IWUSR, l2fw_show, l2fw_store);
static DEVICE_ATTR(l2fw_xor, S_IWUSR, l2fw_show, l2fw_store);
static DEVICE_ATTR(l2fw_add, S_IWUSR, l2fw_show, l2fw_hex_store);
static DEVICE_ATTR(l2fw_add_ip, S_IWUSR, l2fw_show, l2fw_hex_store);
static DEVICE_ATTR(help, S_IRUSR, l2fw_show, NULL);
static DEVICE_ATTR(dump, S_IRUSR, l2fw_show, NULL);
static DEVICE_ATTR(numHashEntries, S_IRUSR, l2fw_show, NULL);
#ifdef CONFIG_MV_ETH_L2SEC
static DEVICE_ATTR(stats, S_IRUSR, l2fw_show, NULL);
static DEVICE_ATTR(esp, S_IWUSR, l2fw_show, l2fw_hex_store);
static DEVICE_ATTR(cesa_chan, S_IWUSR, NULL, l2fw_store);
#endif
static DEVICE_ATTR(flush, S_IWUSR, NULL, l2fw_hex_store);
static struct attribute *l2fw_attrs[] = {
&dev_attr_l2fw.attr,
&dev_attr_l2fw_xor.attr,
&dev_attr_l2fw_add.attr,
&dev_attr_l2fw_add_ip.attr,
&dev_attr_help.attr,
&dev_attr_dump.attr,
&dev_attr_flush.attr,
#ifdef CONFIG_MV_ETH_L2SEC
&dev_attr_esp.attr,
&dev_attr_stats.attr,
&dev_attr_cesa_chan.attr,
#endif
&dev_attr_numHashEntries.attr,
NULL
};
static struct attribute_group l2fw_group = {
.name = "l2fw",
.attrs = l2fw_attrs,
};
#ifdef CONFIG_MV_ETH_L2FW
int __devinit mv_l2fw_sysfs_init(void)
{
int err;
struct device *pd;
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, &l2fw_group);
if (err) {
printk(KERN_ERR "sysfs group failed %d\n", err);
goto out;
}
out:
return err;
}
#endif
module_init(mv_l2fw_sysfs_init);
MODULE_AUTHOR("Rami Rosen");
MODULE_DESCRIPTION("sysfs for marvell l2fw");
MODULE_LICENSE("GPL");