diff options
Diffstat (limited to 'net/dsa')
| -rw-r--r-- | net/dsa/Kconfig | 54 | ||||
| -rw-r--r-- | net/dsa/Makefile | 19 | ||||
| -rw-r--r-- | net/dsa/dsa.c | 296 | ||||
| -rw-r--r-- | net/dsa/dsa_priv.h | 127 | ||||
| -rw-r--r-- | net/dsa/mv88e6060.c | 287 | ||||
| -rw-r--r-- | net/dsa/mv88e6123_61_65.c | 447 | ||||
| -rw-r--r-- | net/dsa/mv88e6131.c | 408 | ||||
| -rw-r--r-- | net/dsa/mv88e6xxx.c | 522 | ||||
| -rw-r--r-- | net/dsa/mv88e6xxx.h | 93 | ||||
| -rw-r--r-- | net/dsa/slave.c | 34 | ||||
| -rw-r--r-- | net/dsa/tag_dsa.c | 15 | ||||
| -rw-r--r-- | net/dsa/tag_edsa.c | 15 | ||||
| -rw-r--r-- | net/dsa/tag_trailer.c | 15 | 
13 files changed, 302 insertions, 2030 deletions
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 87bb5f4de0e..f5eede1d6cb 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -1,60 +1,24 @@ -menuconfig NET_DSA -	bool "Distributed Switch Architecture support" -	default n -	depends on EXPERIMENTAL && NETDEVICES && !S390 -	select PHYLIB -	---help--- -	  This allows you to use hardware switch chips that use -	  the Distributed Switch Architecture. +config HAVE_NET_DSA +	def_bool y +	depends on NETDEVICES && !S390 + +# Drivers must select NET_DSA and the appropriate tagging format +config NET_DSA +	tristate +	depends on HAVE_NET_DSA +	select PHYLIB  if NET_DSA  # tagging formats  config NET_DSA_TAG_DSA  	bool -	default n  config NET_DSA_TAG_EDSA  	bool -	default n  config NET_DSA_TAG_TRAILER  	bool -	default n - - -# switch drivers -config NET_DSA_MV88E6XXX -	bool -	default n - -config NET_DSA_MV88E6060 -	bool "Marvell 88E6060 ethernet switch chip support" -	select NET_DSA_TAG_TRAILER -	---help--- -	  This enables support for the Marvell 88E6060 ethernet switch -	  chip. - -config NET_DSA_MV88E6XXX_NEED_PPU -	bool -	default n - -config NET_DSA_MV88E6131 -	bool "Marvell 88E6095/6095F/6131 ethernet switch chip support" -	select NET_DSA_MV88E6XXX -	select NET_DSA_MV88E6XXX_NEED_PPU -	select NET_DSA_TAG_DSA -	---help--- -	  This enables support for the Marvell 88E6095/6095F/6131 -	  ethernet switch chips. - -config NET_DSA_MV88E6123_61_65 -	bool "Marvell 88E6123/6161/6165 ethernet switch chip support" -	select NET_DSA_MV88E6XXX -	select NET_DSA_TAG_EDSA -	---help--- -	  This enables support for the Marvell 88E6123/6161/6165 -	  ethernet switch chips.  endif diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 2374faff4de..7b9fcbbeda5 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -1,13 +1,8 @@ -# tagging formats -obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o -obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o -obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o - -# switch drivers -obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o -obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o -obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o -obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o -  # the core -obj-$(CONFIG_NET_DSA) += dsa.o slave.o +obj-$(CONFIG_NET_DSA) += dsa_core.o +dsa_core-y += dsa.o slave.o + +# tagging formats +dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o +dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o +dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 6112a12578b..5db37cef50a 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -1,6 +1,7 @@  /*   * net/dsa/dsa.c - Hardware switch handling   * Copyright (c) 2008-2009 Marvell Semiconductor + * Copyright (c) 2013 Florian Fainelli <florian@openwrt.org>   *   * 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 @@ -12,7 +13,11 @@  #include <linux/netdevice.h>  #include <linux/platform_device.h>  #include <linux/slab.h> +#include <linux/module.h>  #include <net/dsa.h> +#include <linux/of.h> +#include <linux/of_mdio.h> +#include <linux/of_platform.h>  #include "dsa_priv.h"  char dsa_driver_version[] = "0.1"; @@ -28,6 +33,7 @@ void register_switch_driver(struct dsa_switch_driver *drv)  	list_add_tail(&drv->list, &dsa_switch_drivers);  	mutex_unlock(&dsa_switch_drivers_mutex);  } +EXPORT_SYMBOL_GPL(register_switch_driver);  void unregister_switch_driver(struct dsa_switch_driver *drv)  { @@ -35,6 +41,7 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)  	list_del_init(&drv->list);  	mutex_unlock(&dsa_switch_drivers_mutex);  } +EXPORT_SYMBOL_GPL(unregister_switch_driver);  static struct dsa_switch_driver *  dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name) @@ -77,6 +84,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,  	int ret;  	char *name;  	int i; +	bool valid_name_found = false;  	/*  	 * Probe for switch model. @@ -128,8 +136,13 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,  		} else {  			ds->phys_port_mask |= 1 << i;  		} +		valid_name_found = true;  	} +	if (!valid_name_found && i == DSA_MAX_PORTS) { +		ret = -EINVAL; +		goto out; +	}  	/*  	 * If the CPU connects to this switch, set the switch tree @@ -198,29 +211,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds)  } -/* hooks for ethertype-less tagging formats *********************************/ -/* - * The original DSA tag format and some other tag formats have no - * ethertype, which means that we need to add a little hack to the - * networking receive path to make sure that received frames get - * the right ->protocol assigned to them when one of those tag - * formats is in use. - */ -bool dsa_uses_dsa_tags(void *dsa_ptr) -{ -	struct dsa_switch_tree *dst = dsa_ptr; - -	return !!(dst->tag_protocol == htons(ETH_P_DSA)); -} - -bool dsa_uses_trailer_tags(void *dsa_ptr) -{ -	struct dsa_switch_tree *dst = dsa_ptr; - -	return !!(dst->tag_protocol == htons(ETH_P_TRAILER)); -} - -  /* link polling *************************************************************/  static void dsa_link_poll_work(struct work_struct *ugly)  { @@ -301,34 +291,240 @@ static struct net_device *dev_to_net_device(struct device *dev)  	return NULL;  } +#ifdef CONFIG_OF +static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, +					struct dsa_chip_data *cd, +					int chip_index, +					struct device_node *link) +{ +	int ret; +	const __be32 *reg; +	int link_port_addr; +	int link_sw_addr; +	struct device_node *parent_sw; +	int len; + +	parent_sw = of_get_parent(link); +	if (!parent_sw) +		return -EINVAL; + +	reg = of_get_property(parent_sw, "reg", &len); +	if (!reg || (len != sizeof(*reg) * 2)) +		return -EINVAL; + +	link_sw_addr = be32_to_cpup(reg + 1); + +	if (link_sw_addr >= pd->nr_chips) +		return -EINVAL; + +	/* First time routing table allocation */ +	if (!cd->rtable) { +		cd->rtable = kmalloc(pd->nr_chips * sizeof(s8), GFP_KERNEL); +		if (!cd->rtable) +			return -ENOMEM; + +		/* default to no valid uplink/downlink */ +		memset(cd->rtable, -1, pd->nr_chips * sizeof(s8)); +	} + +	reg = of_get_property(link, "reg", NULL); +	if (!reg) { +		ret = -EINVAL; +		goto out; +	} + +	link_port_addr = be32_to_cpup(reg); + +	cd->rtable[link_sw_addr] = link_port_addr; + +	return 0; +out: +	kfree(cd->rtable); +	return ret; +} + +static void dsa_of_free_platform_data(struct dsa_platform_data *pd) +{ +	int i; +	int port_index; + +	for (i = 0; i < pd->nr_chips; i++) { +		port_index = 0; +		while (port_index < DSA_MAX_PORTS) { +			if (pd->chip[i].port_names[port_index]) +				kfree(pd->chip[i].port_names[port_index]); +			port_index++; +		} +		kfree(pd->chip[i].rtable); +	} +	kfree(pd->chip); +} + +static int dsa_of_probe(struct platform_device *pdev) +{ +	struct device_node *np = pdev->dev.of_node; +	struct device_node *child, *mdio, *ethernet, *port, *link; +	struct mii_bus *mdio_bus; +	struct platform_device *ethernet_dev; +	struct dsa_platform_data *pd; +	struct dsa_chip_data *cd; +	const char *port_name; +	int chip_index, port_index; +	const unsigned int *sw_addr, *port_reg; +	int ret; + +	mdio = of_parse_phandle(np, "dsa,mii-bus", 0); +	if (!mdio) +		return -EINVAL; + +	mdio_bus = of_mdio_find_bus(mdio); +	if (!mdio_bus) +		return -EINVAL; + +	ethernet = of_parse_phandle(np, "dsa,ethernet", 0); +	if (!ethernet) +		return -EINVAL; + +	ethernet_dev = of_find_device_by_node(ethernet); +	if (!ethernet_dev) +		return -ENODEV; + +	pd = kzalloc(sizeof(*pd), GFP_KERNEL); +	if (!pd) +		return -ENOMEM; + +	pdev->dev.platform_data = pd; +	pd->netdev = ðernet_dev->dev; +	pd->nr_chips = of_get_child_count(np); +	if (pd->nr_chips > DSA_MAX_SWITCHES) +		pd->nr_chips = DSA_MAX_SWITCHES; + +	pd->chip = kzalloc(pd->nr_chips * sizeof(struct dsa_chip_data), +			GFP_KERNEL); +	if (!pd->chip) { +		ret = -ENOMEM; +		goto out_free; +	} + +	chip_index = -1; +	for_each_available_child_of_node(np, child) { +		chip_index++; +		cd = &pd->chip[chip_index]; + +		cd->mii_bus = &mdio_bus->dev; + +		sw_addr = of_get_property(child, "reg", NULL); +		if (!sw_addr) +			continue; + +		cd->sw_addr = be32_to_cpup(sw_addr); +		if (cd->sw_addr > PHY_MAX_ADDR) +			continue; + +		for_each_available_child_of_node(child, port) { +			port_reg = of_get_property(port, "reg", NULL); +			if (!port_reg) +				continue; + +			port_index = be32_to_cpup(port_reg); + +			port_name = of_get_property(port, "label", NULL); +			if (!port_name) +				continue; + +			cd->port_names[port_index] = kstrdup(port_name, +					GFP_KERNEL); +			if (!cd->port_names[port_index]) { +				ret = -ENOMEM; +				goto out_free_chip; +			} + +			link = of_parse_phandle(port, "link", 0); + +			if (!strcmp(port_name, "dsa") && link && +					pd->nr_chips > 1) { +				ret = dsa_of_setup_routing_table(pd, cd, +						chip_index, link); +				if (ret) +					goto out_free_chip; +			} + +			if (port_index == DSA_MAX_PORTS) +				break; +		} +	} + +	return 0; + +out_free_chip: +	dsa_of_free_platform_data(pd); +out_free: +	kfree(pd); +	pdev->dev.platform_data = NULL; +	return ret; +} + +static void dsa_of_remove(struct platform_device *pdev) +{ +	struct dsa_platform_data *pd = pdev->dev.platform_data; + +	if (!pdev->dev.of_node) +		return; + +	dsa_of_free_platform_data(pd); +	kfree(pd); +} +#else +static inline int dsa_of_probe(struct platform_device *pdev) +{ +	return 0; +} + +static inline void dsa_of_remove(struct platform_device *pdev) +{ +} +#endif +  static int dsa_probe(struct platform_device *pdev)  {  	static int dsa_version_printed;  	struct dsa_platform_data *pd = pdev->dev.platform_data;  	struct net_device *dev;  	struct dsa_switch_tree *dst; -	int i; +	int i, ret;  	if (!dsa_version_printed++)  		printk(KERN_NOTICE "Distributed Switch Architecture "  			"driver version %s\n", dsa_driver_version); +	if (pdev->dev.of_node) { +		ret = dsa_of_probe(pdev); +		if (ret) +			return ret; + +		pd = pdev->dev.platform_data; +	} +  	if (pd == NULL || pd->netdev == NULL)  		return -EINVAL;  	dev = dev_to_net_device(pd->netdev); -	if (dev == NULL) -		return -EINVAL; +	if (dev == NULL) { +		ret = -EINVAL; +		goto out; +	}  	if (dev->dsa_ptr != NULL) {  		dev_put(dev); -		return -EEXIST; +		ret = -EEXIST; +		goto out;  	}  	dst = kzalloc(sizeof(*dst), GFP_KERNEL);  	if (dst == NULL) {  		dev_put(dev); -		return -ENOMEM; +		ret = -ENOMEM; +		goto out;  	}  	platform_set_drvdata(pdev, dst); @@ -380,6 +576,11 @@ static int dsa_probe(struct platform_device *pdev)  	}  	return 0; + +out: +	dsa_of_remove(pdev); + +	return ret;  }  static int dsa_remove(struct platform_device *pdev) @@ -390,7 +591,7 @@ static int dsa_remove(struct platform_device *pdev)  	if (dst->link_poll_needed)  		del_timer_sync(&dst->link_poll_timer); -	flush_scheduled_work(); +	flush_work(&dst->link_poll_work);  	for (i = 0; i < dst->pd->nr_chips; i++) {  		struct dsa_switch *ds = dst->ds[i]; @@ -399,6 +600,8 @@ static int dsa_remove(struct platform_device *pdev)  			dsa_switch_destroy(ds);  	} +	dsa_of_remove(pdev); +  	return 0;  } @@ -406,6 +609,12 @@ static void dsa_shutdown(struct platform_device *pdev)  {  } +static const struct of_device_id dsa_of_match_table[] = { +	{ .compatible = "marvell,dsa", }, +	{} +}; +MODULE_DEVICE_TABLE(of, dsa_of_match_table); +  static struct platform_driver dsa_driver = {  	.probe		= dsa_probe,  	.remove		= dsa_remove, @@ -413,22 +622,47 @@ static struct platform_driver dsa_driver = {  	.driver = {  		.name	= "dsa",  		.owner	= THIS_MODULE, +		.of_match_table = dsa_of_match_table,  	},  };  static int __init dsa_init_module(void)  { -	return platform_driver_register(&dsa_driver); +	int rc; + +	rc = platform_driver_register(&dsa_driver); +	if (rc) +		return rc; + +#ifdef CONFIG_NET_DSA_TAG_DSA +	dev_add_pack(&dsa_packet_type); +#endif +#ifdef CONFIG_NET_DSA_TAG_EDSA +	dev_add_pack(&edsa_packet_type); +#endif +#ifdef CONFIG_NET_DSA_TAG_TRAILER +	dev_add_pack(&trailer_packet_type); +#endif +	return 0;  }  module_init(dsa_init_module);  static void __exit dsa_cleanup_module(void)  { +#ifdef CONFIG_NET_DSA_TAG_TRAILER +	dev_remove_pack(&trailer_packet_type); +#endif +#ifdef CONFIG_NET_DSA_TAG_EDSA +	dev_remove_pack(&edsa_packet_type); +#endif +#ifdef CONFIG_NET_DSA_TAG_DSA +	dev_remove_pack(&dsa_packet_type); +#endif  	platform_driver_unregister(&dsa_driver);  }  module_exit(dsa_cleanup_module); -MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>") +MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");  MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips");  MODULE_LICENSE("GPL");  MODULE_ALIAS("platform:dsa"); diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 4b0ea054044..d4cf5cc747e 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -11,97 +11,9 @@  #ifndef __DSA_PRIV_H  #define __DSA_PRIV_H -#include <linux/list.h>  #include <linux/phy.h> -#include <linux/timer.h> -#include <linux/workqueue.h>  #include <net/dsa.h> -struct dsa_switch { -	/* -	 * Parent switch tree, and switch index. -	 */ -	struct dsa_switch_tree	*dst; -	int			index; - -	/* -	 * Configuration data for this switch. -	 */ -	struct dsa_chip_data	*pd; - -	/* -	 * The used switch driver. -	 */ -	struct dsa_switch_driver	*drv; - -	/* -	 * Reference to mii bus to use. -	 */ -	struct mii_bus		*master_mii_bus; - -	/* -	 * Slave mii_bus and devices for the individual ports. -	 */ -	u32			dsa_port_mask; -	u32			phys_port_mask; -	struct mii_bus		*slave_mii_bus; -	struct net_device	*ports[DSA_MAX_PORTS]; -}; - -struct dsa_switch_tree { -	/* -	 * Configuration data for the platform device that owns -	 * this dsa switch tree instance. -	 */ -	struct dsa_platform_data	*pd; - -	/* -	 * Reference to network device to use, and which tagging -	 * protocol to use. -	 */ -	struct net_device	*master_netdev; -	__be16			tag_protocol; - -	/* -	 * The switch and port to which the CPU is attached. -	 */ -	s8			cpu_switch; -	s8			cpu_port; - -	/* -	 * Link state polling. -	 */ -	int			link_poll_needed; -	struct work_struct	link_poll_work; -	struct timer_list	link_poll_timer; - -	/* -	 * Data for the individual switch chips. -	 */ -	struct dsa_switch	*ds[DSA_MAX_SWITCHES]; -}; - -static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) -{ -	return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); -} - -static inline u8 dsa_upstream_port(struct dsa_switch *ds) -{ -	struct dsa_switch_tree *dst = ds->dst; - -	/* -	 * If this is the root switch (i.e. the switch that connects -	 * to the CPU), return the cpu port number on this switch. -	 * Else return the (DSA) port number that connects to the -	 * switch that is one hop closer to the cpu. -	 */ -	if (dst->cpu_switch == ds->index) -		return dst->cpu_port; -	else -		return ds->pd->rtable[dst->cpu_switch]; -} -  struct dsa_slave_priv {  	/*  	 * The linux network interface corresponding to this @@ -123,44 +35,8 @@ struct dsa_slave_priv {  	struct phy_device	*phy;  }; -struct dsa_switch_driver { -	struct list_head	list; - -	__be16			tag_protocol; -	int			priv_size; - -	/* -	 * Probing and setup. -	 */ -	char	*(*probe)(struct mii_bus *bus, int sw_addr); -	int	(*setup)(struct dsa_switch *ds); -	int	(*set_addr)(struct dsa_switch *ds, u8 *addr); - -	/* -	 * Access to the switch's PHY registers. -	 */ -	int	(*phy_read)(struct dsa_switch *ds, int port, int regnum); -	int	(*phy_write)(struct dsa_switch *ds, int port, -			     int regnum, u16 val); - -	/* -	 * Link state polling and IRQ handling. -	 */ -	void	(*poll_link)(struct dsa_switch *ds); - -	/* -	 * ethtool hardware statistics. -	 */ -	void	(*get_strings)(struct dsa_switch *ds, int port, uint8_t *data); -	void	(*get_ethtool_stats)(struct dsa_switch *ds, -				     int port, uint64_t *data); -	int	(*get_sset_count)(struct dsa_switch *ds); -}; -  /* dsa.c */  extern char dsa_driver_version[]; -void register_switch_driver(struct dsa_switch_driver *type); -void unregister_switch_driver(struct dsa_switch_driver *type);  /* slave.c */  void dsa_slave_mii_bus_init(struct dsa_switch *ds); @@ -170,12 +46,15 @@ struct net_device *dsa_slave_create(struct dsa_switch *ds,  /* tag_dsa.c */  netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev); +extern struct packet_type dsa_packet_type;  /* tag_edsa.c */  netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev); +extern struct packet_type edsa_packet_type;  /* tag_trailer.c */  netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev); +extern struct packet_type trailer_packet_type;  #endif diff --git a/net/dsa/mv88e6060.c b/net/dsa/mv88e6060.c deleted file mode 100644 index 83277f463af..00000000000 --- a/net/dsa/mv88e6060.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips - * Copyright (c) 2008-2009 Marvell Semiconductor - * - * 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. - */ - -#include <linux/list.h> -#include <linux/netdevice.h> -#include <linux/phy.h> -#include "dsa_priv.h" - -#define REG_PORT(p)		(8 + (p)) -#define REG_GLOBAL		0x0f - -static int reg_read(struct dsa_switch *ds, int addr, int reg) -{ -	return mdiobus_read(ds->master_mii_bus, addr, reg); -} - -#define REG_READ(addr, reg)					\ -	({							\ -		int __ret;					\ -								\ -		__ret = reg_read(ds, addr, reg);		\ -		if (__ret < 0)					\ -			return __ret;				\ -		__ret;						\ -	}) - - -static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) -{ -	return mdiobus_write(ds->master_mii_bus, addr, reg, val); -} - -#define REG_WRITE(addr, reg, val)				\ -	({							\ -		int __ret;					\ -								\ -		__ret = reg_write(ds, addr, reg, val);		\ -		if (__ret < 0)					\ -			return __ret;				\ -	}) - -static char *mv88e6060_probe(struct mii_bus *bus, int sw_addr) -{ -	int ret; - -	ret = mdiobus_read(bus, REG_PORT(0), 0x03); -	if (ret >= 0) { -		ret &= 0xfff0; -		if (ret == 0x0600) -			return "Marvell 88E6060"; -	} - -	return NULL; -} - -static int mv88e6060_switch_reset(struct dsa_switch *ds) -{ -	int i; -	int ret; - -	/* -	 * Set all ports to the disabled state. -	 */ -	for (i = 0; i < 6; i++) { -		ret = REG_READ(REG_PORT(i), 0x04); -		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); -	} - -	/* -	 * Wait for transmit queues to drain. -	 */ -	msleep(2); - -	/* -	 * Reset the switch. -	 */ -	REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); - -	/* -	 * Wait up to one second for reset to complete. -	 */ -	for (i = 0; i < 1000; i++) { -		ret = REG_READ(REG_GLOBAL, 0x00); -		if ((ret & 0x8000) == 0x0000) -			break; - -		msleep(1); -	} -	if (i == 1000) -		return -ETIMEDOUT; - -	return 0; -} - -static int mv88e6060_setup_global(struct dsa_switch *ds) -{ -	/* -	 * Disable discarding of frames with excessive collisions, -	 * set the maximum frame size to 1536 bytes, and mask all -	 * interrupt sources. -	 */ -	REG_WRITE(REG_GLOBAL, 0x04, 0x0800); - -	/* -	 * Enable automatic address learning, set the address -	 * database size to 1024 entries, and set the default aging -	 * time to 5 minutes. -	 */ -	REG_WRITE(REG_GLOBAL, 0x0a, 0x2130); - -	return 0; -} - -static int mv88e6060_setup_port(struct dsa_switch *ds, int p) -{ -	int addr = REG_PORT(p); - -	/* -	 * Do not force flow control, disable Ingress and Egress -	 * Header tagging, disable VLAN tunneling, and set the port -	 * state to Forwarding.  Additionally, if this is the CPU -	 * port, enable Ingress and Egress Trailer tagging mode. -	 */ -	REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ?  0x4103 : 0x0003); - -	/* -	 * Port based VLAN map: give each port its own address -	 * database, allow the CPU port to talk to each of the 'real' -	 * ports, and allow each of the 'real' ports to only talk to -	 * the CPU port. -	 */ -	REG_WRITE(addr, 0x06, -			((p & 0xf) << 12) | -			 (dsa_is_cpu_port(ds, p) ? -				ds->phys_port_mask : -				(1 << ds->dst->cpu_port))); - -	/* -	 * Port Association Vector: when learning source addresses -	 * of packets, add the address to the address database using -	 * a port bitmap that has only the bit for this port set and -	 * the other bits clear. -	 */ -	REG_WRITE(addr, 0x0b, 1 << p); - -	return 0; -} - -static int mv88e6060_setup(struct dsa_switch *ds) -{ -	int i; -	int ret; - -	ret = mv88e6060_switch_reset(ds); -	if (ret < 0) -		return ret; - -	/* @@@ initialise atu */ - -	ret = mv88e6060_setup_global(ds); -	if (ret < 0) -		return ret; - -	for (i = 0; i < 6; i++) { -		ret = mv88e6060_setup_port(ds, i); -		if (ret < 0) -			return ret; -	} - -	return 0; -} - -static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr) -{ -	REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); -	REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); -	REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); - -	return 0; -} - -static int mv88e6060_port_to_phy_addr(int port) -{ -	if (port >= 0 && port <= 5) -		return port; -	return -1; -} - -static int mv88e6060_phy_read(struct dsa_switch *ds, int port, int regnum) -{ -	int addr; - -	addr = mv88e6060_port_to_phy_addr(port); -	if (addr == -1) -		return 0xffff; - -	return reg_read(ds, addr, regnum); -} - -static int -mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) -{ -	int addr; - -	addr = mv88e6060_port_to_phy_addr(port); -	if (addr == -1) -		return 0xffff; - -	return reg_write(ds, addr, regnum, val); -} - -static void mv88e6060_poll_link(struct dsa_switch *ds) -{ -	int i; - -	for (i = 0; i < DSA_MAX_PORTS; i++) { -		struct net_device *dev; -		int uninitialized_var(port_status); -		int link; -		int speed; -		int duplex; -		int fc; - -		dev = ds->ports[i]; -		if (dev == NULL) -			continue; - -		link = 0; -		if (dev->flags & IFF_UP) { -			port_status = reg_read(ds, REG_PORT(i), 0x00); -			if (port_status < 0) -				continue; - -			link = !!(port_status & 0x1000); -		} - -		if (!link) { -			if (netif_carrier_ok(dev)) { -				printk(KERN_INFO "%s: link down\n", dev->name); -				netif_carrier_off(dev); -			} -			continue; -		} - -		speed = (port_status & 0x0100) ? 100 : 10; -		duplex = (port_status & 0x0200) ? 1 : 0; -		fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0; - -		if (!netif_carrier_ok(dev)) { -			printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " -					 "flow control %sabled\n", dev->name, -					 speed, duplex ? "full" : "half", -					 fc ? "en" : "dis"); -			netif_carrier_on(dev); -		} -	} -} - -static struct dsa_switch_driver mv88e6060_switch_driver = { -	.tag_protocol	= htons(ETH_P_TRAILER), -	.probe		= mv88e6060_probe, -	.setup		= mv88e6060_setup, -	.set_addr	= mv88e6060_set_addr, -	.phy_read	= mv88e6060_phy_read, -	.phy_write	= mv88e6060_phy_write, -	.poll_link	= mv88e6060_poll_link, -}; - -static int __init mv88e6060_init(void) -{ -	register_switch_driver(&mv88e6060_switch_driver); -	return 0; -} -module_init(mv88e6060_init); - -static void __exit mv88e6060_cleanup(void) -{ -	unregister_switch_driver(&mv88e6060_switch_driver); -} -module_exit(mv88e6060_cleanup); diff --git a/net/dsa/mv88e6123_61_65.c b/net/dsa/mv88e6123_61_65.c deleted file mode 100644 index 52faaa21a4d..00000000000 --- a/net/dsa/mv88e6123_61_65.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support - * Copyright (c) 2008-2009 Marvell Semiconductor - * - * 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. - */ - -#include <linux/list.h> -#include <linux/netdevice.h> -#include <linux/phy.h> -#include "dsa_priv.h" -#include "mv88e6xxx.h" - -static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr) -{ -	int ret; - -	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); -	if (ret >= 0) { -		ret &= 0xfff0; -		if (ret == 0x1210) -			return "Marvell 88E6123"; -		if (ret == 0x1610) -			return "Marvell 88E6161"; -		if (ret == 0x1650) -			return "Marvell 88E6165"; -	} - -	return NULL; -} - -static int mv88e6123_61_65_switch_reset(struct dsa_switch *ds) -{ -	int i; -	int ret; - -	/* -	 * Set all ports to the disabled state. -	 */ -	for (i = 0; i < 8; i++) { -		ret = REG_READ(REG_PORT(i), 0x04); -		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); -	} - -	/* -	 * Wait for transmit queues to drain. -	 */ -	msleep(2); - -	/* -	 * Reset the switch. -	 */ -	REG_WRITE(REG_GLOBAL, 0x04, 0xc400); - -	/* -	 * Wait up to one second for reset to complete. -	 */ -	for (i = 0; i < 1000; i++) { -		ret = REG_READ(REG_GLOBAL, 0x00); -		if ((ret & 0xc800) == 0xc800) -			break; - -		msleep(1); -	} -	if (i == 1000) -		return -ETIMEDOUT; - -	return 0; -} - -static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) -{ -	int ret; -	int i; - -	/* -	 * Disable the PHY polling unit (since there won't be any -	 * external PHYs to poll), don't discard packets with -	 * excessive collisions, and mask all interrupt sources. -	 */ -	REG_WRITE(REG_GLOBAL, 0x04, 0x0000); - -	/* -	 * Set the default address aging time to 5 minutes, and -	 * enable address learn messages to be sent to all message -	 * ports. -	 */ -	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148); - -	/* -	 * Configure the priority mapping registers. -	 */ -	ret = mv88e6xxx_config_prio(ds); -	if (ret < 0) -		return ret; - -	/* -	 * Configure the upstream port, and configure the upstream -	 * port as the port to which ingress and egress monitor frames -	 * are to be sent. -	 */ -	REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); - -	/* -	 * Disable remote management for now, and set the switch's -	 * DSA device number. -	 */ -	REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); - -	/* -	 * Send all frames with destination addresses matching -	 * 01:80:c2:00:00:2x to the CPU port. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x02, 0xffff); - -	/* -	 * Send all frames with destination addresses matching -	 * 01:80:c2:00:00:0x to the CPU port. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff); - -	/* -	 * Disable the loopback filter, disable flow control -	 * messages, disable flood broadcast override, disable -	 * removing of provider tags, disable ATU age violation -	 * interrupts, disable tag flow control, force flow -	 * control priority to the highest, and send all special -	 * multicast frames to the CPU at the highest priority. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); - -	/* -	 * Program the DSA routing table. -	 */ -	for (i = 0; i < 32; i++) { -		int nexthop; - -		nexthop = 0x1f; -		if (i != ds->index && i < ds->dst->pd->nr_chips) -			nexthop = ds->pd->rtable[i] & 0x1f; - -		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); -	} - -	/* -	 * Clear all trunk masks. -	 */ -	for (i = 0; i < 8; i++) -		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); - -	/* -	 * Clear all trunk mappings. -	 */ -	for (i = 0; i < 16; i++) -		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11)); - -	/* -	 * Disable ingress rate limiting by resetting all ingress -	 * rate limit registers to their initial state. -	 */ -	for (i = 0; i < 6; i++) -		REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8)); - -	/* -	 * Initialise cross-chip port VLAN table to reset defaults. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000); - -	/* -	 * Clear the priority override table. -	 */ -	for (i = 0; i < 16; i++) -		REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8)); - -	/* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */ - -	return 0; -} - -static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p) -{ -	int addr = REG_PORT(p); -	u16 val; - -	/* -	 * MAC Forcing register: don't force link, speed, duplex -	 * or flow control state to any particular values on physical -	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s -	 * full duplex. -	 */ -	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) -		REG_WRITE(addr, 0x01, 0x003e); -	else -		REG_WRITE(addr, 0x01, 0x0003); - -	/* -	 * Do not limit the period of time that this port can be -	 * paused for by the remote end or the period of time that -	 * this port can pause the remote end. -	 */ -	REG_WRITE(addr, 0x02, 0x0000); - -	/* -	 * Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, -	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN -	 * tunneling, determine priority by looking at 802.1p and IP -	 * priority fields (IP prio has precedence), and set STP state -	 * to Forwarding. -	 * -	 * If this is the CPU link, use DSA or EDSA tagging depending -	 * on which tagging mode was configured. -	 * -	 * If this is a link to another switch, use DSA tagging mode. -	 * -	 * If this is the upstream port for this switch, enable -	 * forwarding of unknown unicasts and multicasts. -	 */ -	val = 0x0433; -	if (dsa_is_cpu_port(ds, p)) { -		if (ds->dst->tag_protocol == htons(ETH_P_EDSA)) -			val |= 0x3300; -		else -			val |= 0x0100; -	} -	if (ds->dsa_port_mask & (1 << p)) -		val |= 0x0100; -	if (p == dsa_upstream_port(ds)) -		val |= 0x000c; -	REG_WRITE(addr, 0x04, val); - -	/* -	 * Port Control 1: disable trunking.  Also, if this is the -	 * CPU port, enable learn messages to be sent to this port. -	 */ -	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000); - -	/* -	 * Port based VLAN map: give each port its own address -	 * database, allow the CPU port to talk to each of the 'real' -	 * ports, and allow each of the 'real' ports to only talk to -	 * the upstream port. -	 */ -	val = (p & 0xf) << 12; -	if (dsa_is_cpu_port(ds, p)) -		val |= ds->phys_port_mask; -	else -		val |= 1 << dsa_upstream_port(ds); -	REG_WRITE(addr, 0x06, val); - -	/* -	 * Default VLAN ID and priority: don't set a default VLAN -	 * ID, and set the default packet priority to zero. -	 */ -	REG_WRITE(addr, 0x07, 0x0000); - -	/* -	 * Port Control 2: don't force a good FCS, set the maximum -	 * frame size to 10240 bytes, don't let the switch add or -	 * strip 802.1q tags, don't discard tagged or untagged frames -	 * on this port, do a destination address lookup on all -	 * received packets as usual, disable ARP mirroring and don't -	 * send a copy of all transmitted/received frames on this port -	 * to the CPU. -	 */ -	REG_WRITE(addr, 0x08, 0x2080); - -	/* -	 * Egress rate control: disable egress rate control. -	 */ -	REG_WRITE(addr, 0x09, 0x0001); - -	/* -	 * Egress rate control 2: disable egress rate control. -	 */ -	REG_WRITE(addr, 0x0a, 0x0000); - -	/* -	 * Port Association Vector: when learning source addresses -	 * of packets, add the address to the address database using -	 * a port bitmap that has only the bit for this port set and -	 * the other bits clear. -	 */ -	REG_WRITE(addr, 0x0b, 1 << p); - -	/* -	 * Port ATU control: disable limiting the number of address -	 * database entries that this port is allowed to use. -	 */ -	REG_WRITE(addr, 0x0c, 0x0000); - -	/* -	 * Priorit Override: disable DA, SA and VTU priority override. -	 */ -	REG_WRITE(addr, 0x0d, 0x0000); - -	/* -	 * Port Ethertype: use the Ethertype DSA Ethertype value. -	 */ -	REG_WRITE(addr, 0x0f, ETH_P_EDSA); - -	/* -	 * Tag Remap: use an identity 802.1p prio -> switch prio -	 * mapping. -	 */ -	REG_WRITE(addr, 0x18, 0x3210); - -	/* -	 * Tag Remap 2: use an identity 802.1p prio -> switch prio -	 * mapping. -	 */ -	REG_WRITE(addr, 0x19, 0x7654); - -	return 0; -} - -static int mv88e6123_61_65_setup(struct dsa_switch *ds) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int i; -	int ret; - -	mutex_init(&ps->smi_mutex); -	mutex_init(&ps->stats_mutex); - -	ret = mv88e6123_61_65_switch_reset(ds); -	if (ret < 0) -		return ret; - -	/* @@@ initialise vtu and atu */ - -	ret = mv88e6123_61_65_setup_global(ds); -	if (ret < 0) -		return ret; - -	for (i = 0; i < 6; i++) { -		ret = mv88e6123_61_65_setup_port(ds, i); -		if (ret < 0) -			return ret; -	} - -	return 0; -} - -static int mv88e6123_61_65_port_to_phy_addr(int port) -{ -	if (port >= 0 && port <= 4) -		return port; -	return -1; -} - -static int -mv88e6123_61_65_phy_read(struct dsa_switch *ds, int port, int regnum) -{ -	int addr = mv88e6123_61_65_port_to_phy_addr(port); -	return mv88e6xxx_phy_read(ds, addr, regnum); -} - -static int -mv88e6123_61_65_phy_write(struct dsa_switch *ds, -			      int port, int regnum, u16 val) -{ -	int addr = mv88e6123_61_65_port_to_phy_addr(port); -	return mv88e6xxx_phy_write(ds, addr, regnum, val); -} - -static struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = { -	{ "in_good_octets", 8, 0x00, }, -	{ "in_bad_octets", 4, 0x02, }, -	{ "in_unicast", 4, 0x04, }, -	{ "in_broadcasts", 4, 0x06, }, -	{ "in_multicasts", 4, 0x07, }, -	{ "in_pause", 4, 0x16, }, -	{ "in_undersize", 4, 0x18, }, -	{ "in_fragments", 4, 0x19, }, -	{ "in_oversize", 4, 0x1a, }, -	{ "in_jabber", 4, 0x1b, }, -	{ "in_rx_error", 4, 0x1c, }, -	{ "in_fcs_error", 4, 0x1d, }, -	{ "out_octets", 8, 0x0e, }, -	{ "out_unicast", 4, 0x10, }, -	{ "out_broadcasts", 4, 0x13, }, -	{ "out_multicasts", 4, 0x12, }, -	{ "out_pause", 4, 0x15, }, -	{ "excessive", 4, 0x11, }, -	{ "collisions", 4, 0x1e, }, -	{ "deferred", 4, 0x05, }, -	{ "single", 4, 0x14, }, -	{ "multiple", 4, 0x17, }, -	{ "out_fcs_error", 4, 0x03, }, -	{ "late", 4, 0x1f, }, -	{ "hist_64bytes", 4, 0x08, }, -	{ "hist_65_127bytes", 4, 0x09, }, -	{ "hist_128_255bytes", 4, 0x0a, }, -	{ "hist_256_511bytes", 4, 0x0b, }, -	{ "hist_512_1023bytes", 4, 0x0c, }, -	{ "hist_1024_max_bytes", 4, 0x0d, }, -}; - -static void -mv88e6123_61_65_get_strings(struct dsa_switch *ds, int port, uint8_t *data) -{ -	mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats), -			      mv88e6123_61_65_hw_stats, port, data); -} - -static void -mv88e6123_61_65_get_ethtool_stats(struct dsa_switch *ds, -				  int port, uint64_t *data) -{ -	mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats), -				    mv88e6123_61_65_hw_stats, port, data); -} - -static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds) -{ -	return ARRAY_SIZE(mv88e6123_61_65_hw_stats); -} - -static struct dsa_switch_driver mv88e6123_61_65_switch_driver = { -	.tag_protocol		= cpu_to_be16(ETH_P_EDSA), -	.priv_size		= sizeof(struct mv88e6xxx_priv_state), -	.probe			= mv88e6123_61_65_probe, -	.setup			= mv88e6123_61_65_setup, -	.set_addr		= mv88e6xxx_set_addr_indirect, -	.phy_read		= mv88e6123_61_65_phy_read, -	.phy_write		= mv88e6123_61_65_phy_write, -	.poll_link		= mv88e6xxx_poll_link, -	.get_strings		= mv88e6123_61_65_get_strings, -	.get_ethtool_stats	= mv88e6123_61_65_get_ethtool_stats, -	.get_sset_count		= mv88e6123_61_65_get_sset_count, -}; - -static int __init mv88e6123_61_65_init(void) -{ -	register_switch_driver(&mv88e6123_61_65_switch_driver); -	return 0; -} -module_init(mv88e6123_61_65_init); - -static void __exit mv88e6123_61_65_cleanup(void) -{ -	unregister_switch_driver(&mv88e6123_61_65_switch_driver); -} -module_exit(mv88e6123_61_65_cleanup); diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c deleted file mode 100644 index bb2b41bc854..00000000000 --- a/net/dsa/mv88e6131.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support - * Copyright (c) 2008-2009 Marvell Semiconductor - * - * 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. - */ - -#include <linux/list.h> -#include <linux/netdevice.h> -#include <linux/phy.h> -#include "dsa_priv.h" -#include "mv88e6xxx.h" - -static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) -{ -	int ret; - -	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); -	if (ret >= 0) { -		ret &= 0xfff0; -		if (ret == 0x0950) -			return "Marvell 88E6095/88E6095F"; -		if (ret == 0x1060) -			return "Marvell 88E6131"; -	} - -	return NULL; -} - -static int mv88e6131_switch_reset(struct dsa_switch *ds) -{ -	int i; -	int ret; - -	/* -	 * Set all ports to the disabled state. -	 */ -	for (i = 0; i < 11; i++) { -		ret = REG_READ(REG_PORT(i), 0x04); -		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); -	} - -	/* -	 * Wait for transmit queues to drain. -	 */ -	msleep(2); - -	/* -	 * Reset the switch. -	 */ -	REG_WRITE(REG_GLOBAL, 0x04, 0xc400); - -	/* -	 * Wait up to one second for reset to complete. -	 */ -	for (i = 0; i < 1000; i++) { -		ret = REG_READ(REG_GLOBAL, 0x00); -		if ((ret & 0xc800) == 0xc800) -			break; - -		msleep(1); -	} -	if (i == 1000) -		return -ETIMEDOUT; - -	return 0; -} - -static int mv88e6131_setup_global(struct dsa_switch *ds) -{ -	int ret; -	int i; - -	/* -	 * Enable the PHY polling unit, don't discard packets with -	 * excessive collisions, use a weighted fair queueing scheme -	 * to arbitrate between packet queues, set the maximum frame -	 * size to 1632, and mask all interrupt sources. -	 */ -	REG_WRITE(REG_GLOBAL, 0x04, 0x4400); - -	/* -	 * Set the default address aging time to 5 minutes, and -	 * enable address learn messages to be sent to all message -	 * ports. -	 */ -	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148); - -	/* -	 * Configure the priority mapping registers. -	 */ -	ret = mv88e6xxx_config_prio(ds); -	if (ret < 0) -		return ret; - -	/* -	 * Set the VLAN ethertype to 0x8100. -	 */ -	REG_WRITE(REG_GLOBAL, 0x19, 0x8100); - -	/* -	 * Disable ARP mirroring, and configure the upstream port as -	 * the port to which ingress and egress monitor frames are to -	 * be sent. -	 */ -	REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0); - -	/* -	 * Disable cascade port functionality, and set the switch's -	 * DSA device number. -	 */ -	REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f)); - -	/* -	 * Send all frames with destination addresses matching -	 * 01:80:c2:00:00:0x to the CPU port. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff); - -	/* -	 * Ignore removed tag data on doubly tagged packets, disable -	 * flow control messages, force flow control priority to the -	 * highest, and send all special multicast frames to the CPU -	 * port at the higest priority. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); - -	/* -	 * Program the DSA routing table. -	 */ -	for (i = 0; i < 32; i++) { -		int nexthop; - -		nexthop = 0x1f; -		if (i != ds->index && i < ds->dst->pd->nr_chips) -			nexthop = ds->pd->rtable[i] & 0x1f; - -		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); -	} - -	/* -	 * Clear all trunk masks. -	 */ -	for (i = 0; i < 8; i++) -		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff); - -	/* -	 * Clear all trunk mappings. -	 */ -	for (i = 0; i < 16; i++) -		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11)); - -	/* -	 * Force the priority of IGMP/MLD snoop frames and ARP frames -	 * to the highest setting. -	 */ -	REG_WRITE(REG_GLOBAL2, 0x0f, 0x00ff); - -	return 0; -} - -static int mv88e6131_setup_port(struct dsa_switch *ds, int p) -{ -	int addr = REG_PORT(p); -	u16 val; - -	/* -	 * MAC Forcing register: don't force link, speed, duplex -	 * or flow control state to any particular values on physical -	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s -	 * full duplex. -	 */ -	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) -		REG_WRITE(addr, 0x01, 0x003e); -	else -		REG_WRITE(addr, 0x01, 0x0003); - -	/* -	 * Port Control: disable Core Tag, disable Drop-on-Lock, -	 * transmit frames unmodified, disable Header mode, -	 * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN -	 * tunneling, determine priority by looking at 802.1p and -	 * IP priority fields (IP prio has precedence), and set STP -	 * state to Forwarding. -	 * -	 * If this is the upstream port for this switch, enable -	 * forwarding of unknown unicasts, and enable DSA tagging -	 * mode. -	 * -	 * If this is the link to another switch, use DSA tagging -	 * mode, but do not enable forwarding of unknown unicasts. -	 */ -	val = 0x0433; -	if (p == dsa_upstream_port(ds)) -		val |= 0x0104; -	if (ds->dsa_port_mask & (1 << p)) -		val |= 0x0100; -	REG_WRITE(addr, 0x04, val); - -	/* -	 * Port Control 1: disable trunking.  Also, if this is the -	 * CPU port, enable learn messages to be sent to this port. -	 */ -	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000); - -	/* -	 * Port based VLAN map: give each port its own address -	 * database, allow the CPU port to talk to each of the 'real' -	 * ports, and allow each of the 'real' ports to only talk to -	 * the upstream port. -	 */ -	val = (p & 0xf) << 12; -	if (dsa_is_cpu_port(ds, p)) -		val |= ds->phys_port_mask; -	else -		val |= 1 << dsa_upstream_port(ds); -	REG_WRITE(addr, 0x06, val); - -	/* -	 * Default VLAN ID and priority: don't set a default VLAN -	 * ID, and set the default packet priority to zero. -	 */ -	REG_WRITE(addr, 0x07, 0x0000); - -	/* -	 * Port Control 2: don't force a good FCS, don't use -	 * VLAN-based, source address-based or destination -	 * address-based priority overrides, don't let the switch -	 * add or strip 802.1q tags, don't discard tagged or -	 * untagged frames on this port, do a destination address -	 * lookup on received packets as usual, don't send a copy -	 * of all transmitted/received frames on this port to the -	 * CPU, and configure the upstream port number. -	 * -	 * If this is the upstream port for this switch, enable -	 * forwarding of unknown multicast addresses. -	 */ -	val = 0x0080 | dsa_upstream_port(ds); -	if (p == dsa_upstream_port(ds)) -		val |= 0x0040; -	REG_WRITE(addr, 0x08, val); - -	/* -	 * Rate Control: disable ingress rate limiting. -	 */ -	REG_WRITE(addr, 0x09, 0x0000); - -	/* -	 * Rate Control 2: disable egress rate limiting. -	 */ -	REG_WRITE(addr, 0x0a, 0x0000); - -	/* -	 * Port Association Vector: when learning source addresses -	 * of packets, add the address to the address database using -	 * a port bitmap that has only the bit for this port set and -	 * the other bits clear. -	 */ -	REG_WRITE(addr, 0x0b, 1 << p); - -	/* -	 * Tag Remap: use an identity 802.1p prio -> switch prio -	 * mapping. -	 */ -	REG_WRITE(addr, 0x18, 0x3210); - -	/* -	 * Tag Remap 2: use an identity 802.1p prio -> switch prio -	 * mapping. -	 */ -	REG_WRITE(addr, 0x19, 0x7654); - -	return 0; -} - -static int mv88e6131_setup(struct dsa_switch *ds) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int i; -	int ret; - -	mutex_init(&ps->smi_mutex); -	mv88e6xxx_ppu_state_init(ds); -	mutex_init(&ps->stats_mutex); - -	ret = mv88e6131_switch_reset(ds); -	if (ret < 0) -		return ret; - -	/* @@@ initialise vtu and atu */ - -	ret = mv88e6131_setup_global(ds); -	if (ret < 0) -		return ret; - -	for (i = 0; i < 11; i++) { -		ret = mv88e6131_setup_port(ds, i); -		if (ret < 0) -			return ret; -	} - -	return 0; -} - -static int mv88e6131_port_to_phy_addr(int port) -{ -	if (port >= 0 && port <= 11) -		return port; -	return -1; -} - -static int -mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum) -{ -	int addr = mv88e6131_port_to_phy_addr(port); -	return mv88e6xxx_phy_read_ppu(ds, addr, regnum); -} - -static int -mv88e6131_phy_write(struct dsa_switch *ds, -			      int port, int regnum, u16 val) -{ -	int addr = mv88e6131_port_to_phy_addr(port); -	return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val); -} - -static struct mv88e6xxx_hw_stat mv88e6131_hw_stats[] = { -	{ "in_good_octets", 8, 0x00, }, -	{ "in_bad_octets", 4, 0x02, }, -	{ "in_unicast", 4, 0x04, }, -	{ "in_broadcasts", 4, 0x06, }, -	{ "in_multicasts", 4, 0x07, }, -	{ "in_pause", 4, 0x16, }, -	{ "in_undersize", 4, 0x18, }, -	{ "in_fragments", 4, 0x19, }, -	{ "in_oversize", 4, 0x1a, }, -	{ "in_jabber", 4, 0x1b, }, -	{ "in_rx_error", 4, 0x1c, }, -	{ "in_fcs_error", 4, 0x1d, }, -	{ "out_octets", 8, 0x0e, }, -	{ "out_unicast", 4, 0x10, }, -	{ "out_broadcasts", 4, 0x13, }, -	{ "out_multicasts", 4, 0x12, }, -	{ "out_pause", 4, 0x15, }, -	{ "excessive", 4, 0x11, }, -	{ "collisions", 4, 0x1e, }, -	{ "deferred", 4, 0x05, }, -	{ "single", 4, 0x14, }, -	{ "multiple", 4, 0x17, }, -	{ "out_fcs_error", 4, 0x03, }, -	{ "late", 4, 0x1f, }, -	{ "hist_64bytes", 4, 0x08, }, -	{ "hist_65_127bytes", 4, 0x09, }, -	{ "hist_128_255bytes", 4, 0x0a, }, -	{ "hist_256_511bytes", 4, 0x0b, }, -	{ "hist_512_1023bytes", 4, 0x0c, }, -	{ "hist_1024_max_bytes", 4, 0x0d, }, -}; - -static void -mv88e6131_get_strings(struct dsa_switch *ds, int port, uint8_t *data) -{ -	mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6131_hw_stats), -			      mv88e6131_hw_stats, port, data); -} - -static void -mv88e6131_get_ethtool_stats(struct dsa_switch *ds, -				  int port, uint64_t *data) -{ -	mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6131_hw_stats), -				    mv88e6131_hw_stats, port, data); -} - -static int mv88e6131_get_sset_count(struct dsa_switch *ds) -{ -	return ARRAY_SIZE(mv88e6131_hw_stats); -} - -static struct dsa_switch_driver mv88e6131_switch_driver = { -	.tag_protocol		= cpu_to_be16(ETH_P_DSA), -	.priv_size		= sizeof(struct mv88e6xxx_priv_state), -	.probe			= mv88e6131_probe, -	.setup			= mv88e6131_setup, -	.set_addr		= mv88e6xxx_set_addr_direct, -	.phy_read		= mv88e6131_phy_read, -	.phy_write		= mv88e6131_phy_write, -	.poll_link		= mv88e6xxx_poll_link, -	.get_strings		= mv88e6131_get_strings, -	.get_ethtool_stats	= mv88e6131_get_ethtool_stats, -	.get_sset_count		= mv88e6131_get_sset_count, -}; - -static int __init mv88e6131_init(void) -{ -	register_switch_driver(&mv88e6131_switch_driver); -	return 0; -} -module_init(mv88e6131_init); - -static void __exit mv88e6131_cleanup(void) -{ -	unregister_switch_driver(&mv88e6131_switch_driver); -} -module_exit(mv88e6131_cleanup); diff --git a/net/dsa/mv88e6xxx.c b/net/dsa/mv88e6xxx.c deleted file mode 100644 index efe661a9def..00000000000 --- a/net/dsa/mv88e6xxx.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support - * Copyright (c) 2008 Marvell Semiconductor - * - * 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. - */ - -#include <linux/list.h> -#include <linux/netdevice.h> -#include <linux/phy.h> -#include "dsa_priv.h" -#include "mv88e6xxx.h" - -/* - * If the switch's ADDR[4:0] strap pins are strapped to zero, it will - * use all 32 SMI bus addresses on its SMI bus, and all switch registers - * will be directly accessible on some {device address,register address} - * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch - * will only respond to SMI transactions to that specific address, and - * an indirect addressing mechanism needs to be used to access its - * registers. - */ -static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr) -{ -	int ret; -	int i; - -	for (i = 0; i < 16; i++) { -		ret = mdiobus_read(bus, sw_addr, 0); -		if (ret < 0) -			return ret; - -		if ((ret & 0x8000) == 0) -			return 0; -	} - -	return -ETIMEDOUT; -} - -int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) -{ -	int ret; - -	if (sw_addr == 0) -		return mdiobus_read(bus, addr, reg); - -	/* -	 * Wait for the bus to become free. -	 */ -	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); -	if (ret < 0) -		return ret; - -	/* -	 * Transmit the read command. -	 */ -	ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg); -	if (ret < 0) -		return ret; - -	/* -	 * Wait for the read command to complete. -	 */ -	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); -	if (ret < 0) -		return ret; - -	/* -	 * Read the data. -	 */ -	ret = mdiobus_read(bus, sw_addr, 1); -	if (ret < 0) -		return ret; - -	return ret & 0xffff; -} - -int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int ret; - -	mutex_lock(&ps->smi_mutex); -	ret = __mv88e6xxx_reg_read(ds->master_mii_bus, -				   ds->pd->sw_addr, addr, reg); -	mutex_unlock(&ps->smi_mutex); - -	return ret; -} - -int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, -			  int reg, u16 val) -{ -	int ret; - -	if (sw_addr == 0) -		return mdiobus_write(bus, addr, reg, val); - -	/* -	 * Wait for the bus to become free. -	 */ -	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); -	if (ret < 0) -		return ret; - -	/* -	 * Transmit the data to write. -	 */ -	ret = mdiobus_write(bus, sw_addr, 1, val); -	if (ret < 0) -		return ret; - -	/* -	 * Transmit the write command. -	 */ -	ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg); -	if (ret < 0) -		return ret; - -	/* -	 * Wait for the write command to complete. -	 */ -	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); -	if (ret < 0) -		return ret; - -	return 0; -} - -int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int ret; - -	mutex_lock(&ps->smi_mutex); -	ret = __mv88e6xxx_reg_write(ds->master_mii_bus, -				    ds->pd->sw_addr, addr, reg, val); -	mutex_unlock(&ps->smi_mutex); - -	return ret; -} - -int mv88e6xxx_config_prio(struct dsa_switch *ds) -{ -	/* -	 * Configure the IP ToS mapping registers. -	 */ -	REG_WRITE(REG_GLOBAL, 0x10, 0x0000); -	REG_WRITE(REG_GLOBAL, 0x11, 0x0000); -	REG_WRITE(REG_GLOBAL, 0x12, 0x5555); -	REG_WRITE(REG_GLOBAL, 0x13, 0x5555); -	REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa); -	REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa); -	REG_WRITE(REG_GLOBAL, 0x16, 0xffff); -	REG_WRITE(REG_GLOBAL, 0x17, 0xffff); - -	/* -	 * Configure the IEEE 802.1p priority mapping register. -	 */ -	REG_WRITE(REG_GLOBAL, 0x18, 0xfa41); - -	return 0; -} - -int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) -{ -	REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); -	REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); -	REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); - -	return 0; -} - -int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) -{ -	int i; -	int ret; - -	for (i = 0; i < 6; i++) { -		int j; - -		/* -		 * Write the MAC address byte. -		 */ -		REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]); - -		/* -		 * Wait for the write to complete. -		 */ -		for (j = 0; j < 16; j++) { -			ret = REG_READ(REG_GLOBAL2, 0x0d); -			if ((ret & 0x8000) == 0) -				break; -		} -		if (j == 16) -			return -ETIMEDOUT; -	} - -	return 0; -} - -int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) -{ -	if (addr >= 0) -		return mv88e6xxx_reg_read(ds, addr, regnum); -	return 0xffff; -} - -int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val) -{ -	if (addr >= 0) -		return mv88e6xxx_reg_write(ds, addr, regnum, val); -	return 0; -} - -#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU -static int mv88e6xxx_ppu_disable(struct dsa_switch *ds) -{ -	int ret; -	int i; - -	ret = REG_READ(REG_GLOBAL, 0x04); -	REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000); - -	for (i = 0; i < 1000; i++) { -	        ret = REG_READ(REG_GLOBAL, 0x00); -	        msleep(1); -	        if ((ret & 0xc000) != 0xc000) -	                return 0; -	} - -	return -ETIMEDOUT; -} - -static int mv88e6xxx_ppu_enable(struct dsa_switch *ds) -{ -	int ret; -	int i; - -	ret = REG_READ(REG_GLOBAL, 0x04); -	REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000); - -	for (i = 0; i < 1000; i++) { -	        ret = REG_READ(REG_GLOBAL, 0x00); -	        msleep(1); -	        if ((ret & 0xc000) == 0xc000) -	                return 0; -	} - -	return -ETIMEDOUT; -} - -static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly) -{ -	struct mv88e6xxx_priv_state *ps; - -	ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work); -	if (mutex_trylock(&ps->ppu_mutex)) { -	        struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1; - -	        if (mv88e6xxx_ppu_enable(ds) == 0) -	                ps->ppu_disabled = 0; -	        mutex_unlock(&ps->ppu_mutex); -	} -} - -static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps) -{ -	struct mv88e6xxx_priv_state *ps = (void *)_ps; - -	schedule_work(&ps->ppu_work); -} - -static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int ret; - -	mutex_lock(&ps->ppu_mutex); - -	/* -	 * If the PHY polling unit is enabled, disable it so that -	 * we can access the PHY registers.  If it was already -	 * disabled, cancel the timer that is going to re-enable -	 * it. -	 */ -	if (!ps->ppu_disabled) { -	        ret = mv88e6xxx_ppu_disable(ds); -	        if (ret < 0) { -	                mutex_unlock(&ps->ppu_mutex); -	                return ret; -	        } -	        ps->ppu_disabled = 1; -	} else { -	        del_timer(&ps->ppu_timer); -	        ret = 0; -	} - -	return ret; -} - -static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); - -	/* -	 * Schedule a timer to re-enable the PHY polling unit. -	 */ -	mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10)); -	mutex_unlock(&ps->ppu_mutex); -} - -void mv88e6xxx_ppu_state_init(struct dsa_switch *ds) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); - -	mutex_init(&ps->ppu_mutex); -	INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work); -	init_timer(&ps->ppu_timer); -	ps->ppu_timer.data = (unsigned long)ps; -	ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer; -} - -int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum) -{ -	int ret; - -	ret = mv88e6xxx_ppu_access_get(ds); -	if (ret >= 0) { -	        ret = mv88e6xxx_reg_read(ds, addr, regnum); -	        mv88e6xxx_ppu_access_put(ds); -	} - -	return ret; -} - -int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, -			    int regnum, u16 val) -{ -	int ret; - -	ret = mv88e6xxx_ppu_access_get(ds); -	if (ret >= 0) { -	        ret = mv88e6xxx_reg_write(ds, addr, regnum, val); -	        mv88e6xxx_ppu_access_put(ds); -	} - -	return ret; -} -#endif - -void mv88e6xxx_poll_link(struct dsa_switch *ds) -{ -	int i; - -	for (i = 0; i < DSA_MAX_PORTS; i++) { -		struct net_device *dev; -		int uninitialized_var(port_status); -		int link; -		int speed; -		int duplex; -		int fc; - -		dev = ds->ports[i]; -		if (dev == NULL) -			continue; - -		link = 0; -		if (dev->flags & IFF_UP) { -			port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00); -			if (port_status < 0) -				continue; - -			link = !!(port_status & 0x0800); -		} - -		if (!link) { -			if (netif_carrier_ok(dev)) { -				printk(KERN_INFO "%s: link down\n", dev->name); -				netif_carrier_off(dev); -			} -			continue; -		} - -		switch (port_status & 0x0300) { -		case 0x0000: -			speed = 10; -			break; -		case 0x0100: -			speed = 100; -			break; -		case 0x0200: -			speed = 1000; -			break; -		default: -			speed = -1; -			break; -		} -		duplex = (port_status & 0x0400) ? 1 : 0; -		fc = (port_status & 0x8000) ? 1 : 0; - -		if (!netif_carrier_ok(dev)) { -			printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " -					 "flow control %sabled\n", dev->name, -					 speed, duplex ? "full" : "half", -					 fc ? "en" : "dis"); -			netif_carrier_on(dev); -		} -	} -} - -static int mv88e6xxx_stats_wait(struct dsa_switch *ds) -{ -	int ret; -	int i; - -	for (i = 0; i < 10; i++) { -		ret = REG_READ(REG_GLOBAL, 0x1d); -		if ((ret & 0x8000) == 0) -			return 0; -	} - -	return -ETIMEDOUT; -} - -static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port) -{ -	int ret; - -	/* -	 * Snapshot the hardware statistics counters for this port. -	 */ -	REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port); - -	/* -	 * Wait for the snapshotting to complete. -	 */ -	ret = mv88e6xxx_stats_wait(ds); -	if (ret < 0) -		return ret; - -	return 0; -} - -static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val) -{ -	u32 _val; -	int ret; - -	*val = 0; - -	ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat); -	if (ret < 0) -		return; - -	ret = mv88e6xxx_stats_wait(ds); -	if (ret < 0) -		return; - -	ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e); -	if (ret < 0) -		return; - -	_val = ret << 16; - -	ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f); -	if (ret < 0) -		return; - -	*val = _val | ret; -} - -void mv88e6xxx_get_strings(struct dsa_switch *ds, -			   int nr_stats, struct mv88e6xxx_hw_stat *stats, -			   int port, uint8_t *data) -{ -	int i; - -	for (i = 0; i < nr_stats; i++) { -		memcpy(data + i * ETH_GSTRING_LEN, -		       stats[i].string, ETH_GSTRING_LEN); -	} -} - -void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, -				 int nr_stats, struct mv88e6xxx_hw_stat *stats, -				 int port, uint64_t *data) -{ -	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); -	int ret; -	int i; - -	mutex_lock(&ps->stats_mutex); - -	ret = mv88e6xxx_stats_snapshot(ds, port); -	if (ret < 0) { -		mutex_unlock(&ps->stats_mutex); -		return; -	} - -	/* -	 * Read each of the counters. -	 */ -	for (i = 0; i < nr_stats; i++) { -		struct mv88e6xxx_hw_stat *s = stats + i; -		u32 low; -		u32 high; - -		mv88e6xxx_stats_read(ds, s->reg, &low); -		if (s->sizeof_stat == 8) -			mv88e6xxx_stats_read(ds, s->reg + 1, &high); -		else -			high = 0; - -		data[i] = (((u64)high) << 32) | low; -	} - -	mutex_unlock(&ps->stats_mutex); -} diff --git a/net/dsa/mv88e6xxx.h b/net/dsa/mv88e6xxx.h deleted file mode 100644 index eb0e0aaa9f1..00000000000 --- a/net/dsa/mv88e6xxx.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * net/dsa/mv88e6xxx.h - Marvell 88e6xxx switch chip support - * Copyright (c) 2008 Marvell Semiconductor - * - * 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. - */ - -#ifndef __MV88E6XXX_H -#define __MV88E6XXX_H - -#define REG_PORT(p)		(0x10 + (p)) -#define REG_GLOBAL		0x1b -#define REG_GLOBAL2		0x1c - -struct mv88e6xxx_priv_state { -	/* -	 * When using multi-chip addressing, this mutex protects -	 * access to the indirect access registers.  (In single-chip -	 * mode, this mutex is effectively useless.) -	 */ -	struct mutex	smi_mutex; - -#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU -	/* -	 * Handles automatic disabling and re-enabling of the PHY -	 * polling unit. -	 */ -	struct mutex		ppu_mutex; -	int			ppu_disabled; -	struct work_struct	ppu_work; -	struct timer_list	ppu_timer; -#endif - -	/* -	 * This mutex serialises access to the statistics unit. -	 * Hold this mutex over snapshot + dump sequences. -	 */ -	struct mutex	stats_mutex; -}; - -struct mv88e6xxx_hw_stat { -	char string[ETH_GSTRING_LEN]; -	int sizeof_stat; -	int reg; -}; - -int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg); -int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg); -int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, -                          int reg, u16 val); -int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val); -int mv88e6xxx_config_prio(struct dsa_switch *ds); -int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr); -int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr); -int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum); -int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val); -void mv88e6xxx_ppu_state_init(struct dsa_switch *ds); -int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum); -int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, -			    int regnum, u16 val); -void mv88e6xxx_poll_link(struct dsa_switch *ds); -void mv88e6xxx_get_strings(struct dsa_switch *ds, -			   int nr_stats, struct mv88e6xxx_hw_stat *stats, -			   int port, uint8_t *data); -void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, -				 int nr_stats, struct mv88e6xxx_hw_stat *stats, -				 int port, uint64_t *data); - -#define REG_READ(addr, reg)						\ -	({								\ -		int __ret;						\ -									\ -		__ret = mv88e6xxx_reg_read(ds, addr, reg);		\ -		if (__ret < 0)						\ -			return __ret;					\ -		__ret;							\ -	}) - -#define REG_WRITE(addr, reg, val)					\ -	({								\ -		int __ret;						\ -									\ -		__ret = mv88e6xxx_reg_write(ds, addr, reg, val);	\ -		if (__ret < 0)						\ -			return __ret;					\ -	}) - - - -#endif diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 64ca2a6fa0d..64c5af0a10d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -41,8 +41,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)  	ds->slave_mii_bus->name = "dsa slave smi";  	ds->slave_mii_bus->read = dsa_slave_phy_read;  	ds->slave_mii_bus->write = dsa_slave_phy_write; -	snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "%s:%.2x", -			ds->master_mii_bus->id, ds->pd->sw_addr); +	snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", +			ds->index, ds->pd->sw_addr);  	ds->slave_mii_bus->parent = &ds->master_mii_bus->dev;  } @@ -66,7 +66,7 @@ static int dsa_slave_open(struct net_device *dev)  	if (!(master->flags & IFF_UP))  		return -ENETDOWN; -	if (compare_ether_addr(dev->dev_addr, master->dev_addr)) { +	if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) {  		err = dev_uc_add(master, dev->dev_addr);  		if (err < 0)  			goto out; @@ -89,7 +89,7 @@ clear_allmulti:  	if (dev->flags & IFF_ALLMULTI)  		dev_set_allmulti(master, -1);  del_unicast: -	if (compare_ether_addr(dev->dev_addr, master->dev_addr)) +	if (!ether_addr_equal(dev->dev_addr, master->dev_addr))  		dev_uc_del(master, dev->dev_addr);  out:  	return err; @@ -107,7 +107,7 @@ static int dsa_slave_close(struct net_device *dev)  	if (dev->flags & IFF_PROMISC)  		dev_set_promiscuity(master, -1); -	if (compare_ether_addr(dev->dev_addr, master->dev_addr)) +	if (!ether_addr_equal(dev->dev_addr, master->dev_addr))  		dev_uc_del(master, dev->dev_addr);  	return 0; @@ -146,17 +146,17 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a)  	if (!(dev->flags & IFF_UP))  		goto out; -	if (compare_ether_addr(addr->sa_data, master->dev_addr)) { +	if (!ether_addr_equal(addr->sa_data, master->dev_addr)) {  		err = dev_uc_add(master, addr->sa_data);  		if (err < 0)  			return err;  	} -	if (compare_ether_addr(dev->dev_addr, master->dev_addr)) +	if (!ether_addr_equal(dev->dev_addr, master->dev_addr))  		dev_uc_del(master, dev->dev_addr);  out: -	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); +	ether_addr_copy(dev->dev_addr, addr->sa_data);  	return 0;  } @@ -203,10 +203,10 @@ dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)  static void dsa_slave_get_drvinfo(struct net_device *dev,  				  struct ethtool_drvinfo *drvinfo)  { -	strncpy(drvinfo->driver, "dsa", 32); -	strncpy(drvinfo->version, dsa_driver_version, 32); -	strncpy(drvinfo->fw_version, "N/A", 32); -	strncpy(drvinfo->bus_info, "platform", 32); +	strlcpy(drvinfo->driver, "dsa", sizeof(drvinfo->driver)); +	strlcpy(drvinfo->version, dsa_driver_version, sizeof(drvinfo->version)); +	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); +	strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));  }  static int dsa_slave_nway_reset(struct net_device *dev) @@ -288,7 +288,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {  	.get_drvinfo		= dsa_slave_get_drvinfo,  	.nway_reset		= dsa_slave_nway_reset,  	.get_link		= dsa_slave_get_link, -	.set_sg			= ethtool_op_set_sg,  	.get_strings		= dsa_slave_get_strings,  	.get_ethtool_stats	= dsa_slave_get_ethtool_stats,  	.get_sset_count		= dsa_slave_get_sset_count, @@ -302,7 +301,6 @@ static const struct net_device_ops dsa_netdev_ops = {  	.ndo_start_xmit		= dsa_xmit,  	.ndo_change_rx_flags	= dsa_slave_change_rx_flags,  	.ndo_set_rx_mode	= dsa_slave_set_rx_mode, -	.ndo_set_multicast_list = dsa_slave_set_rx_mode,  	.ndo_set_mac_address	= dsa_slave_set_mac_address,  	.ndo_do_ioctl		= dsa_slave_ioctl,  }; @@ -315,7 +313,6 @@ static const struct net_device_ops edsa_netdev_ops = {  	.ndo_start_xmit		= edsa_xmit,  	.ndo_change_rx_flags	= dsa_slave_change_rx_flags,  	.ndo_set_rx_mode	= dsa_slave_set_rx_mode, -	.ndo_set_multicast_list = dsa_slave_set_rx_mode,  	.ndo_set_mac_address	= dsa_slave_set_mac_address,  	.ndo_do_ioctl		= dsa_slave_ioctl,  }; @@ -328,7 +325,6 @@ static const struct net_device_ops trailer_netdev_ops = {  	.ndo_start_xmit		= trailer_xmit,  	.ndo_change_rx_flags	= dsa_slave_change_rx_flags,  	.ndo_set_rx_mode	= dsa_slave_set_rx_mode, -	.ndo_set_multicast_list = dsa_slave_set_rx_mode,  	.ndo_set_mac_address	= dsa_slave_set_mac_address,  	.ndo_do_ioctl		= dsa_slave_ioctl,  }; @@ -350,8 +346,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,  		return slave_dev;  	slave_dev->features = master->vlan_features; -	SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops); -	memcpy(slave_dev->dev_addr, master->dev_addr, ETH_ALEN); +	slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; +	eth_hw_addr_inherit(slave_dev, master);  	slave_dev->tx_queue_len = 0;  	switch (ds->dst->tag_protocol) { @@ -395,7 +391,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,  	if (p->phy != NULL) {  		phy_attach(slave_dev, dev_name(&p->phy->dev), -			   0, PHY_INTERFACE_MODE_GMII); +			   PHY_INTERFACE_MODE_GMII);  		p->phy->autoneg = AUTONEG_ENABLE;  		p->phy->speed = 0; diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index 98dfe80b453..cacce1e22f9 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -186,20 +186,7 @@ out:  	return 0;  } -static struct packet_type dsa_packet_type __read_mostly = { +struct packet_type dsa_packet_type __read_mostly = {  	.type	= cpu_to_be16(ETH_P_DSA),  	.func	= dsa_rcv,  }; - -static int __init dsa_init_module(void) -{ -	dev_add_pack(&dsa_packet_type); -	return 0; -} -module_init(dsa_init_module); - -static void __exit dsa_cleanup_module(void) -{ -	dev_remove_pack(&dsa_packet_type); -} -module_exit(dsa_cleanup_module); diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 6f383322ad2..e70c43c25e6 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -205,20 +205,7 @@ out:  	return 0;  } -static struct packet_type edsa_packet_type __read_mostly = { +struct packet_type edsa_packet_type __read_mostly = {  	.type	= cpu_to_be16(ETH_P_EDSA),  	.func	= edsa_rcv,  }; - -static int __init edsa_init_module(void) -{ -	dev_add_pack(&edsa_packet_type); -	return 0; -} -module_init(edsa_init_module); - -static void __exit edsa_cleanup_module(void) -{ -	dev_remove_pack(&edsa_packet_type); -} -module_exit(edsa_cleanup_module); diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index d6d7d0add3c..94bc260d015 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -114,20 +114,7 @@ out:  	return 0;  } -static struct packet_type trailer_packet_type __read_mostly = { +struct packet_type trailer_packet_type __read_mostly = {  	.type	= cpu_to_be16(ETH_P_TRAILER),  	.func	= trailer_rcv,  }; - -static int __init trailer_init_module(void) -{ -	dev_add_pack(&trailer_packet_type); -	return 0; -} -module_init(trailer_init_module); - -static void __exit trailer_cleanup_module(void) -{ -	dev_remove_pack(&trailer_packet_type); -} -module_exit(trailer_cleanup_module);  | 
