summaryrefslogtreecommitdiff
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2016-04-18 12:18:55 +0300
committerJiri Kosina <jkosina@suse.cz>2016-04-18 12:18:55 +0300
commit9938b04472d5c59f8bd8152a548533a8599596a2 (patch)
tree0fc8318100878c5e446076613ec02a97aa179119 /net/dsa/dsa.c
parentbd7ced98812dbb906950d8b0ec786f14f631cede (diff)
parentc3b46c73264b03000d1e18b22f5caf63332547c9 (diff)
downloadlinux-9938b04472d5c59f8bd8152a548533a8599596a2.tar.xz
Merge branch 'master' into for-next
Sync with Linus' tree so that patches against newer codebase can be applied. Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c99
1 files changed, 40 insertions, 59 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 1eba07feb34a..c28c47463b7e 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -21,8 +21,10 @@
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
#include <linux/of_net.h>
+#include <linux/of_gpio.h>
#include <linux/sysfs.h>
#include <linux/phy_fixed.h>
+#include <linux/gpio/consumer.h>
#include "dsa_priv.h"
char dsa_driver_version[] = "0.1";
@@ -428,36 +430,30 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
hwmon_device_unregister(ds->hwmon_dev);
#endif
- /* Disable configuration of the CPU and DSA ports */
+ /* Destroy network devices for physical switch ports. */
for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
+ if (!(ds->phys_port_mask & (1 << port)))
continue;
+ if (!ds->ports[port])
+ continue;
+
+ dsa_slave_destroy(ds->ports[port]);
+ }
+
+ /* Remove any fixed link PHYs */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
port_dn = cd->port_dn[port];
if (of_phy_is_fixed_link(port_dn)) {
phydev = of_phy_find_device(port_dn);
if (phydev) {
- int addr = phydev->addr;
-
phy_device_free(phydev);
of_node_put(port_dn);
- fixed_phy_del(addr);
+ fixed_phy_unregister(phydev);
}
}
}
- /* Destroy network devices for physical switch ports. */
- for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(ds->phys_port_mask & (1 << port)))
- continue;
-
- if (!ds->ports[port])
- continue;
-
- unregister_netdev(ds->ports[port]);
- free_netdev(ds->ports[port]);
- }
-
mdiobus_unregister(ds->slave_mii_bus);
}
@@ -506,33 +502,6 @@ static int dsa_switch_resume(struct dsa_switch *ds)
}
#endif
-
-/* link polling *************************************************************/
-static void dsa_link_poll_work(struct work_struct *ugly)
-{
- struct dsa_switch_tree *dst;
- int i;
-
- dst = container_of(ugly, struct dsa_switch_tree, link_poll_work);
-
- for (i = 0; i < dst->pd->nr_chips; i++) {
- struct dsa_switch *ds = dst->ds[i];
-
- if (ds != NULL && ds->drv->poll_link != NULL)
- ds->drv->poll_link(ds);
- }
-
- mod_timer(&dst->link_poll_timer, round_jiffies(jiffies + HZ));
-}
-
-static void dsa_link_poll_timer(unsigned long _dst)
-{
- struct dsa_switch_tree *dst = (void *)_dst;
-
- schedule_work(&dst->link_poll_work);
-}
-
-
/* platform driver init and cleanup *****************************************/
static int dev_is_class(struct device *dev, void *class)
{
@@ -688,6 +657,9 @@ static int dsa_of_probe(struct device *dev)
const char *port_name;
int chip_index, port_index;
const unsigned int *sw_addr, *port_reg;
+ int gpio;
+ enum of_gpio_flags of_flags;
+ unsigned long flags;
u32 eeprom_len;
int ret;
@@ -766,6 +738,19 @@ static int dsa_of_probe(struct device *dev)
put_device(cd->host_dev);
cd->host_dev = &mdio_bus_switch->dev;
}
+ gpio = of_get_named_gpio_flags(child, "reset-gpios", 0,
+ &of_flags);
+ if (gpio_is_valid(gpio)) {
+ flags = (of_flags == OF_GPIO_ACTIVE_LOW ?
+ GPIOF_ACTIVE_LOW : 0);
+ ret = devm_gpio_request_one(dev, gpio, flags,
+ "switch_reset");
+ if (ret)
+ goto out_free_chip;
+
+ cd->reset = gpio_to_desc(gpio);
+ gpiod_direction_output(cd->reset, 0);
+ }
for_each_available_child_of_node(child, port) {
port_reg = of_get_property(port, "reg", NULL);
@@ -859,8 +844,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
}
dst->ds[i] = ds;
- if (ds->drv->poll_link != NULL)
- dst->link_poll_needed = 1;
++configured;
}
@@ -879,15 +862,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
wmb();
dev->dsa_ptr = (void *)dst;
- if (dst->link_poll_needed) {
- INIT_WORK(&dst->link_poll_work, dsa_link_poll_work);
- init_timer(&dst->link_poll_timer);
- dst->link_poll_timer.data = (unsigned long)dst;
- dst->link_poll_timer.function = dsa_link_poll_timer;
- dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
- add_timer(&dst->link_poll_timer);
- }
-
return 0;
}
@@ -939,8 +913,10 @@ static int dsa_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dst);
ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
- if (ret)
+ if (ret) {
+ dev_put(dev);
goto out;
+ }
return 0;
@@ -954,10 +930,13 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
{
int i;
- if (dst->link_poll_needed)
- del_timer_sync(&dst->link_poll_timer);
+ dst->master_netdev->dsa_ptr = NULL;
- flush_work(&dst->link_poll_work);
+ /* If we used a tagging format that doesn't have an ethertype
+ * field, make sure that all packets from this point get sent
+ * without the tag and go through the regular receive path.
+ */
+ wmb();
for (i = 0; i < dst->pd->nr_chips; i++) {
struct dsa_switch *ds = dst->ds[i];
@@ -965,6 +944,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
if (ds)
dsa_switch_destroy(ds);
}
+
+ dev_put(dst->master_netdev);
}
static int dsa_remove(struct platform_device *pdev)