netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/8] Add irq controller support to Marvell switches
@ 2016-03-14  0:33 Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 1/8] net: dsa: Add parsing of an interrupt property Andrew Lunn
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

The Marvell switches contain one or two interrupt controllers,
depending on switch features. If the switch contains embedded PHYs,
one of these controllers contains the interrupts from these PHYs. In
order that the phylib can make use of these interrupts, they need to
be exported from the driver so a phandle can be used to reference
them. So this patchset make use of the core interrupt infrastructure
to implement one or two interrupt drivers within the switch
driver. The device controller, which contains the PHY interrupts, has
a IRQ domain associated to it, so it can be accessed outside of the
switch driver.

I have a further patch to a dts file to make use of this, but that
board has not yet been accepted into arm-soc.

It would be good if somebody with core IRQ knowledge could review
the second patch. Hi Jason :-)

    Andrew

Andrew Lunn (8):
  net: dsa: Add parsing of an interrupt property
  dsa: mv88e6xxx: Add support for switch and device interrupts
  dsa: mv88e6352: Wire up the mv88e6xxx interrupt code
  dsa: mv88e6171: Wire up the mv88e6xxx interrupt code
  dsa: mv88e6123_61_65: Wire up the mv88e6xxx interrupt code
  dsa: mv88e6131: Wire up the mv88e6xxx interrupt code
  net: dsa: Support phy interrupt property for switch ports.
  net: phy: Use threaded IRQ, to allow IRQ from sleeping devices

 Documentation/devicetree/bindings/net/dsa/dsa.txt |  10 +-
 drivers/net/dsa/mv88e6123_61_65.c                 |   6 +-
 drivers/net/dsa/mv88e6131.c                       |   7 +-
 drivers/net/dsa/mv88e6171.c                       |   6 +-
 drivers/net/dsa/mv88e6352.c                       |   6 +-
 drivers/net/dsa/mv88e6xxx.c                       | 312 ++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.h                       |  22 ++
 drivers/net/phy/phy.c                             |   5 +-
 include/net/dsa.h                                 |   6 +
 net/dsa/dsa.c                                     |   8 +
 net/dsa/dsa_priv.h                                |   1 +
 net/dsa/slave.c                                   |  11 +-
 12 files changed, 389 insertions(+), 11 deletions(-)

-- 
2.7.0

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC PATCH 1/8] net: dsa: Add parsing of an interrupt property
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 2/8] dsa: mv88e6xxx: Add support for switch and device interrupts Andrew Lunn
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Some switch chips have an interrupt line, which can be connected to
a GPIO line and used to indicate interrupts. Add parsing of such
an interrupt to the DSA framework.

Also, update the binding, which already listed an interrupt.  However,
interrupts are a property of the chip, not the cluster, so move it
into the chip level of the hierarchy.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 Documentation/devicetree/bindings/net/dsa/dsa.txt | 7 +++----
 include/net/dsa.h                                 | 6 ++++++
 net/dsa/dsa.c                                     | 8 ++++++++
 3 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index 5fdbbcdf8c4b..90a4fe115e50 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -10,10 +10,6 @@ Required properties:
 - dsa,ethernet		: Should be a phandle to a valid Ethernet device node
 - dsa,mii-bus		: Should be a phandle to a valid MDIO bus device node
 
-Optional properties:
-- interrupts		: property with a value describing the switch
-			  interrupt number (not supported by the driver)
-
 A DSA node can contain multiple switch chips which are therefore child nodes of
 the parent DSA node. The maximum number of allowed child nodes is 4
 (DSA_MAX_SWITCHES).
@@ -34,6 +30,9 @@ A switch child node has the following optional property:
 - reset-gpios		: phandle and specifier to a gpio line connected to
 			  reset pin of the switch chip.
 
+- interrupts		: property with a value describing the switch
+			  interrupt number
+
 A switch may have multiple "port" children nodes
 
 Each port children node must have the following mandatory properties:
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 26c0a3fa009a..ff737781cf8f 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -59,6 +59,12 @@ struct dsa_chip_data {
 	struct device_node *port_dn[DSA_MAX_PORTS];
 
 	/*
+	 * The switch may have an interrupt line, which can be used
+	 * to indicate events have occurred in the switch.
+	 */
+	int irq;
+
+	/*
 	 * An array (with nr_chips elements) of which element [a]
 	 * indicates which port on this switch should be used to
 	 * send packets to that are destined for switch a.  Can be
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8fb47fcad05..980aa10fc3a1 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/of_net.h>
 #include <linux/of_gpio.h>
 #include <linux/sysfs.h>
@@ -667,6 +668,7 @@ static int dsa_of_probe(struct device *dev)
 	unsigned long flags;
 	u32 eeprom_len;
 	int ret;
+	int irq;
 
 	mdio = of_parse_phandle(np, "dsa,mii-bus", 0);
 	if (!mdio)
@@ -728,6 +730,12 @@ static int dsa_of_probe(struct device *dev)
 		if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
 			cd->eeprom_len = eeprom_len;
 
+		irq = of_irq_get(child, 0);
+		if (irq == -EPROBE_DEFER)
+			goto out_free_chip;
+		if (irq > 0)
+			cd->irq = irq;
+
 		mdio = of_parse_phandle(child, "mii-bus", 0);
 		if (mdio) {
 			mdio_bus_switch = of_mdio_find_bus(mdio);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 2/8] dsa: mv88e6xxx: Add support for switch and device interrupts
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 1/8] net: dsa: Add parsing of an interrupt property Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 3/8] dsa: mv88e6352: Wire up the mv88e6xxx interrupt code Andrew Lunn
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

The switch contains an interrupt controller. This then has a chained
device interrupt controller, which contains interrupts from the
embedded PHYs. Add support for these interrupt controllers.
---
 drivers/net/dsa/mv88e6xxx.c | 312 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.h |  22 ++++
 2 files changed, 334 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 5f07524083c3..2301dfbc3582 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -21,6 +21,9 @@
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
 #include <linux/phy.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <net/dsa.h>
 #include <net/switchdev.h>
 #include "mv88e6xxx.h"
@@ -2536,6 +2539,315 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
 	return 0;
 }
 
+static int mv88e6xxx_nirqs(struct dsa_switch *ds)
+{
+	int nirqs = 8;
+
+	if (mv88e6xxx_6165_family(ds) ||
+	    mv88e6xxx_6351_family(ds) ||
+	    mv88e6xxx_6352_family(ds))
+		nirqs = 9;
+
+	return nirqs;
+}
+
+static void mv88e6xxx_switch_irq_mask(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned int n = d->hwirq;
+
+	ps->switch_irq_masked |= (1 << n);
+}
+
+static void mv88e6xxx_switch_irq_unmask(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned int n = d->hwirq;
+
+	ps->switch_irq_masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_switch_irq_thread_fn(int irq, void *dev_id)
+{
+	struct dsa_switch *ds = (struct dsa_switch *)dev_id;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned nhandled = 0;
+	unsigned sub_irq;
+	unsigned n;
+	int val;
+
+	val = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS);
+	if (val < 0)
+		goto out;
+
+	for (n = 0; n < ps->switch_nirqs; ++n) {
+		if (val & (1 << n)) {
+			sub_irq = irq_find_mapping(ps->switch_irq_domain, n);
+			handle_nested_irq(sub_irq);
+			++nhandled;
+		}
+	}
+out:
+	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_switch_irq_bus_lock(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	mutex_lock(&ps->smi_mutex);
+}
+
+static void mv88e6xxx_switch_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u16 mask = GENMASK(ps->switch_nirqs, 0);
+	int reg, ret;
+
+	reg = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+	if (reg < 0)
+		goto out;
+
+	reg &= ~mask;
+	reg |= (~ps->switch_irq_masked & mask);
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, reg);
+	if (ret < 0)
+		goto out;
+
+out:
+	mutex_unlock(&ps->smi_mutex);
+}
+
+static struct irq_chip mv88e6xxx_switch_irq_chip = {
+	.name			= "mv88e6xxx-switch",
+	.irq_mask		= mv88e6xxx_switch_irq_mask,
+	.irq_unmask		= mv88e6xxx_switch_irq_unmask,
+	.irq_bus_lock		= mv88e6xxx_switch_irq_bus_lock,
+	.irq_bus_sync_unlock	= mv88e6xxx_switch_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_switch_irq_domain_map(struct irq_domain *d,
+					   unsigned int irq,
+					   irq_hw_number_t hwirq)
+{
+	struct dsa_switch *ds = d->host_data;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	irq_set_chip_data(irq, d->host_data);
+	irq_set_chip_and_handler(irq, &ps->switch_irq_chip, handle_level_irq);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_switch_irq_domain_ops = {
+	.map	= mv88e6xxx_switch_irq_domain_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+int mv88e6xxx_setup_switch_irq(struct dsa_switch *ds)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u16 mask = GENMASK(ps->switch_nirqs, 0);
+	int err, irq, reg;
+
+	ps->switch_nirqs = mv88e6xxx_nirqs(ds);
+	ps->switch_irq_domain = irq_domain_add_simple(
+		NULL, ps->switch_nirqs, 0,
+		&mv88e6xxx_switch_irq_domain_ops, ds);
+	if (!ps->switch_irq_domain)
+		return -ENOMEM;
+
+	for (irq = 0; irq < ps->switch_nirqs; irq++)
+		irq_create_mapping(ps->switch_irq_domain, irq);
+
+	ps->switch_irq_chip = mv88e6xxx_switch_irq_chip;
+	ps->switch_irq_masked = ~0;
+
+	reg = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL);
+	if (reg < 0) {
+		err = reg;
+		goto out;
+	}
+
+	reg &= ~mask;
+
+	err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, reg);
+	if (err < 0)
+		goto out;
+
+	/* Reading the interrupt status clears (most of) them */
+	reg = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS);
+	if (reg < 0) {
+		err = reg;
+		goto out;
+	}
+
+	err = request_threaded_irq(ds->pd->irq, NULL,
+				   mv88e6xxx_switch_irq_thread_fn,
+				   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+				   "mv88e6xxx-switch", ds);
+
+	if (err)
+		goto out;
+
+	return 0;
+
+out:
+	irq_domain_remove(ps->switch_irq_domain);
+	return err;
+}
+
+static void mv88e6xxx_device_irq_mask(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned int n = d->hwirq;
+
+	ps->device_irq_masked |= (1 << n);
+}
+
+static void mv88e6xxx_device_irq_unmask(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned int n = d->hwirq;
+
+	ps->device_irq_masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_device_irq_thread_fn(int irq, void *dev_id)
+{
+	struct dsa_switch *ds = (struct dsa_switch *)dev_id;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	unsigned nhandled = 0;
+	unsigned sub_irq;
+	unsigned n;
+	int val;
+
+	val = _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_INT_SOURCE);
+	if (val < 0)
+		goto out;
+
+	for (n = 0; n < 16; ++n) {
+		if (val & (1 << n)) {
+			sub_irq = irq_find_mapping(ps->device_irq_domain, n);
+			handle_nested_irq(sub_irq);
+			++nhandled;
+		}
+	}
+out:
+	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_device_irq_bus_lock(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	mutex_lock(&ps->smi_mutex);
+}
+
+static void mv88e6xxx_device_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct dsa_switch *ds = irq_data_get_irq_chip_data(d);
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_INT_MASK,
+				   ~ps->device_irq_masked);
+	if (ret < 0)
+		goto out;
+
+out:
+	mutex_unlock(&ps->smi_mutex);
+}
+
+static struct irq_chip mv88e6xxx_device_irq_chip = {
+	.name			= "mv88e6xxx-device",
+	.irq_mask		= mv88e6xxx_device_irq_mask,
+	.irq_unmask		= mv88e6xxx_device_irq_unmask,
+	.irq_bus_lock		= mv88e6xxx_device_irq_bus_lock,
+	.irq_bus_sync_unlock	= mv88e6xxx_device_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_device_irq_domain_map(struct irq_domain *d,
+					   unsigned int irq,
+					   irq_hw_number_t hwirq)
+{
+	struct dsa_switch *ds = d->host_data;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	irq_set_chip_data(irq, d->host_data);
+	irq_set_chip_and_handler(irq, &ps->device_irq_chip, handle_level_irq);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_device_irq_domain_ops = {
+	.map	= mv88e6xxx_device_irq_domain_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+int mv88e6xxx_setup_device_irq(struct dsa_switch *ds)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	struct device_node *np = ds->pd->of_node;
+	int device_irq;
+	int err, irq;
+
+	ps->device_irq_domain = irq_domain_add_simple(
+		np, 16, 0, &mv88e6xxx_device_irq_domain_ops, ds);
+	if (!ps->device_irq_domain)
+		return -ENOMEM;
+
+	for (irq = 0; irq < 16; irq++)
+		irq_create_mapping(ps->device_irq_domain, irq);
+
+	ps->device_irq_chip = mv88e6xxx_device_irq_chip;
+	ps->device_irq_masked = ~0;
+
+	device_irq = irq_find_mapping(ps->switch_irq_domain,
+				      GLOBAL_STATUS_IRQ_DEVICE);
+	if (device_irq < 0) {
+		err = device_irq;
+		goto out;
+	}
+
+	err = request_threaded_irq(device_irq, NULL,
+				   mv88e6xxx_device_irq_thread_fn,
+				   IRQF_ONESHOT, "mv88e6xxx-device", ds);
+	if (err)
+		goto out;
+
+	return 0;
+out:
+	irq_domain_remove(ps->device_irq_domain);
+	return err;
+}
+
+int mv88e6xxx_setup_irqs(struct dsa_switch *ds)
+{
+	int err;
+
+	if (ds->pd->irq) {
+		err = mv88e6xxx_setup_switch_irq(ds);
+		if (err)
+			return err;
+
+		if (mv88e6xxx_6165_family(ds) || mv88e6xxx_6351_family(ds) ||
+		    mv88e6xxx_6352_family(ds))
+			return mv88e6xxx_setup_device_irq(ds);
+	}
+	return 0;
+}
+
 int mv88e6xxx_setup_common(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 3425616987ed..bb97fdc21e0e 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -12,6 +12,7 @@
 #define __MV88E6XXX_H
 
 #include <linux/if_vlan.h>
+#include <linux/irq.h>
 
 #ifndef UINT64_MAX
 #define UINT64_MAX		(u64)(~((u64)0))
@@ -185,6 +186,15 @@
 #define GLOBAL_STATUS_PPU_INITIALIZING	(0x1 << 14)
 #define GLOBAL_STATUS_PPU_DISABLED	(0x2 << 14)
 #define GLOBAL_STATUS_PPU_POLLING	(0x3 << 14)
+#define GLOBAL_STATUS_IRQ_AVB		8
+#define GLOBAL_STATUS_IRQ_DEVICE	7
+#define GLOBAL_STATUS_IRQ_STATS		6
+#define GLOBAL_STATUS_IRQ_VTU_PROBLEM	5
+#define GLOBAL_STATUS_IRQ_VTU_DONE	4
+#define GLOBAL_STATUS_IRQ_ATU_PROBLEM	3
+#define GLOBAL_STATUS_IRQ_ATU_DONE	2
+#define GLOBAL_STATUS_IRQ_TCAM_DONE	1
+#define GLOBAL_STATUS_IRQ_EEPROM_DONE	0
 #define GLOBAL_MAC_01		0x01
 #define GLOBAL_MAC_23		0x02
 #define GLOBAL_MAC_45		0x03
@@ -428,6 +438,17 @@ struct mv88e6xxx_priv_state {
 
 	DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS);
 
+	/* Main switch interrupt controller */
+	u16 switch_irq_masked;
+	struct irq_chip switch_irq_chip;
+	struct irq_domain *switch_irq_domain;
+	unsigned switch_nirqs;
+
+	/* Device interrupt controller */
+	u16 device_irq_masked;
+	struct irq_chip device_irq_chip;
+	struct irq_domain *device_irq_domain;
+
 	struct work_struct bridge_work;
 };
 
@@ -451,6 +472,7 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
 int mv88e6xxx_setup_ports(struct dsa_switch *ds);
 int mv88e6xxx_setup_common(struct dsa_switch *ds);
 int mv88e6xxx_setup_global(struct dsa_switch *ds);
+int mv88e6xxx_setup_irqs(struct dsa_switch *ds);
 int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
 int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
 int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 3/8] dsa: mv88e6352: Wire up the mv88e6xxx interrupt code
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 1/8] net: dsa: Add parsing of an interrupt property Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 2/8] dsa: mv88e6xxx: Add support for switch and device interrupts Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 4/8] dsa: mv88e6171: " Andrew Lunn
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Make use of the shared interrupt code, so for example phy interrupts
can be passed onto the phylib.
---
 drivers/net/dsa/mv88e6352.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index a41fa5043d77..7f83013a61f6 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -97,7 +97,11 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	return mv88e6xxx_setup_ports(ds);
+	ret = mv88e6xxx_setup_ports(ds);
+	if (ret < 0)
+		return ret;
+
+	return mv88e6xxx_setup_irqs(ds);
 }
 
 static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 4/8] dsa: mv88e6171: Wire up the mv88e6xxx interrupt code
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
                   ` (2 preceding siblings ...)
  2016-03-14  0:33 ` [RFC PATCH 3/8] dsa: mv88e6352: Wire up the mv88e6xxx interrupt code Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 5/8] dsa: mv88e6123_61_65: " Andrew Lunn
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Make use of the shared interrupt code, so for example phy interrupts
can be passed onto the phylib.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6171.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index d72ccbdf53ec..5ed174ff533f 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -83,7 +83,11 @@ static int mv88e6171_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	return mv88e6xxx_setup_ports(ds);
+	ret = mv88e6xxx_setup_ports(ds);
+	if (ret < 0)
+		return ret;
+
+	return mv88e6xxx_setup_irqs(ds);
 }
 
 struct dsa_switch_driver mv88e6171_switch_driver = {
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 5/8] dsa: mv88e6123_61_65: Wire up the mv88e6xxx interrupt code
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
                   ` (3 preceding siblings ...)
  2016-03-14  0:33 ` [RFC PATCH 4/8] dsa: mv88e6171: " Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 6/8] dsa: mv88e6131: " Andrew Lunn
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Make use of the shared interrupt code, so for example phy interrupts
can be passed onto the phylib.
---
 drivers/net/dsa/mv88e6123_61_65.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index d4fcf4570d95..c8111007ef24 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -97,7 +97,11 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	return mv88e6xxx_setup_ports(ds);
+	ret = mv88e6xxx_setup_ports(ds);
+	if (ret < 0)
+		return ret;
+
+	return mv88e6xxx_setup_irqs(ds);
 }
 
 struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 6/8] dsa: mv88e6131: Wire up the mv88e6xxx interrupt code
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
                   ` (4 preceding siblings ...)
  2016-03-14  0:33 ` [RFC PATCH 5/8] dsa: mv88e6123_61_65: " Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 7/8] net: dsa: Support phy interrupt property for switch ports Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 8/8] net: phy: Use threaded IRQ, to allow IRQ from sleeping devices Andrew Lunn
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Make use of the shared interrupt code, so for example phy interrupts
can be passed onto the phylib.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6131.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index a92ca651c399..03031afbcb10 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -121,7 +121,12 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	return mv88e6xxx_setup_ports(ds);
+	ret = mv88e6xxx_setup_ports(ds);
+
+	if (ret < 0)
+		return ret;
+
+	return mv88e6xxx_setup_irqs(ds);
 }
 
 static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 7/8] net: dsa: Support phy interrupt property for switch ports.
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
                   ` (5 preceding siblings ...)
  2016-03-14  0:33 ` [RFC PATCH 6/8] dsa: mv88e6131: " Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  2016-03-14  0:33 ` [RFC PATCH 8/8] net: phy: Use threaded IRQ, to allow IRQ from sleeping devices Andrew Lunn
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

Switch ports can be connected to phys. These phys can support
interrupts when the link goes up/down. Allow the phy interrupt to be
expressed in device tree, and pass it to the phylib when the phy is
bound to the switch port.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 Documentation/devicetree/bindings/net/dsa/dsa.txt |  3 +++
 net/dsa/dsa_priv.h                                |  1 +
 net/dsa/slave.c                                   | 11 ++++++++++-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index 90a4fe115e50..780c96f37508 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -55,6 +55,9 @@ Optionnal property:
 			  Documentation/devicetree/bindings/net/ethernet.txt
 			  for details.
 
+- interrupt-parent	: property with a value describing the phy
+- interrupts		  interrupt number. See Documentation/devicetree/bindings/net/phy.txt
+
 - phy-mode		: String representing the connection to the designated
 			  PHY node specified by the 'phy-handle' property. See
 			  Documentation/devicetree/bindings/net/ethernet.txt
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 1d1a54687e4a..5ce368ea0464 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -46,6 +46,7 @@ struct dsa_slave_priv {
 	int			old_link;
 	int			old_pause;
 	int			old_duplex;
+	int			phy_irq;
 
 	struct net_device	*bridge_dev;
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 27bf03d11670..155bddc43624 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -13,6 +13,7 @@
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
+#include <linux/of_irq.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
 #include <linux/mdio.h>
@@ -921,6 +922,10 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
 	/* Use already configured phy mode */
 	if (p->phy_interface == PHY_INTERFACE_MODE_NA)
 		p->phy_interface = p->phy->interface;
+
+	if (p->phy_irq)
+		p->phy->irq = p->phy_irq;
+
 	phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
 			   p->phy_interface);
 
@@ -935,7 +940,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
 	struct device_node *phy_dn, *port_dn;
 	bool phy_is_fixed = false;
 	u32 phy_flags = 0;
-	int mode, ret;
+	int mode, ret, irq;
 
 	port_dn = cd->port_dn[p->port];
 	mode = of_get_phy_mode(port_dn);
@@ -943,6 +948,10 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
 		mode = PHY_INTERFACE_MODE_NA;
 	p->phy_interface = mode;
 
+	irq = irq_of_parse_and_map(port_dn, 0);
+	if (irq > 0)
+		p->phy_irq = irq;
+
 	phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
 	if (of_phy_is_fixed_link(port_dn)) {
 		/* In the case of a fixed PHY, the DT node associated
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 8/8] net: phy: Use threaded IRQ, to allow IRQ from sleeping devices
  2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
                   ` (6 preceding siblings ...)
  2016-03-14  0:33 ` [RFC PATCH 7/8] net: dsa: Support phy interrupt property for switch ports Andrew Lunn
@ 2016-03-14  0:33 ` Andrew Lunn
  7 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2016-03-14  0:33 UTC (permalink / raw)
  To: netdev, Florian Fainelli, Jason Cooper, Vivien Didelot; +Cc: Andrew Lunn

The interrupt lines from PHYs maybe connected to I2C bus expanders, or
from switches on MDIO busses. Such interrupts are sourced from devices
which sleep, so use threaded interrupts. Threaded require that the
interrupt requester also uses the threaded API. Change the phylib to
use the threaded API, which is backwards compatible with none-threaded
IRQs.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/phy.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 5590b9c182c9..54a623c93e49 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -641,8 +641,9 @@ phy_err:
 int phy_start_interrupts(struct phy_device *phydev)
 {
 	atomic_set(&phydev->irq_disable, 0);
-	if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
-			phydev) < 0) {
+	if (request_threaded_irq(phydev->irq, NULL, phy_interrupt,
+				 IRQF_ONESHOT, "phy_interrupt",
+				 phydev) < 0) {
 		pr_warn("%s: Can't get IRQ %d (PHY)\n",
 			phydev->mdio.bus->name, phydev->irq);
 		phydev->irq = PHY_POLL;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-03-14  0:35 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-14  0:33 [RFC PATCH 0/8] Add irq controller support to Marvell switches Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 1/8] net: dsa: Add parsing of an interrupt property Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 2/8] dsa: mv88e6xxx: Add support for switch and device interrupts Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 3/8] dsa: mv88e6352: Wire up the mv88e6xxx interrupt code Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 4/8] dsa: mv88e6171: " Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 5/8] dsa: mv88e6123_61_65: " Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 6/8] dsa: mv88e6131: " Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 7/8] net: dsa: Support phy interrupt property for switch ports Andrew Lunn
2016-03-14  0:33 ` [RFC PATCH 8/8] net: phy: Use threaded IRQ, to allow IRQ from sleeping devices Andrew Lunn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).