Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db316d57 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-netconsole'



Florian Fainelli says:

====================
net: GENET, SYSTEMPORT and DSA netconsole

This patch series adds support for netconsole in the GENET, SYSTEMPORT and DSA
drivers.

A small refactoring to the DSA transmit path is required to avoid duplicating
the dsa_netpoll_send_skb() into each and every tagging protocol supported.

Testing on e.g: mv643xx_eth and/or e1000e would be much appreciated!

Changes in v2:

- properly disable/enable interrupts in GENET and SYSTEMPORT

- pass the reallocated SKB back to dsa_slave_xmit() in case a tag protocol had to
  alter the original SKB
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0f7bffd9 04ff53f9
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -933,6 +933,21 @@ static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
	return IRQ_HANDLED;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void bcm_sysport_poll_controller(struct net_device *dev)
{
	struct bcm_sysport_priv *priv = netdev_priv(dev);

	disable_irq(priv->irq0);
	bcm_sysport_rx_isr(priv->irq0, priv);
	enable_irq(priv->irq0);

	disable_irq(priv->irq1);
	bcm_sysport_tx_isr(priv->irq1, priv);
	enable_irq(priv->irq1);
}
#endif

static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
					      struct net_device *dev)
{
@@ -1723,6 +1738,9 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
	.ndo_set_features	= bcm_sysport_set_features,
	.ndo_set_rx_mode	= bcm_sysport_set_rx_mode,
	.ndo_set_mac_address	= bcm_sysport_change_mac,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= bcm_sysport_poll_controller,
#endif
};

#define REV_FMT	"v%2x.%02x"
+20 −0
Original line number Diff line number Diff line
@@ -2388,6 +2388,23 @@ static irqreturn_t bcmgenet_wol_isr(int irq, void *dev_id)
	return IRQ_HANDLED;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void bcmgenet_poll_controller(struct net_device *dev)
{
	struct bcmgenet_priv *priv = netdev_priv(dev);

	/* Invoke the main RX/TX interrupt handler */
	disable_irq(priv->irq0);
	bcmgenet_isr0(priv->irq0, priv);
	enable_irq(priv->irq0);

	/* And the interrupt handler for RX/TX priority queues */
	disable_irq(priv->irq1);
	bcmgenet_isr1(priv->irq1, priv);
	enable_irq(priv->irq1);
}
#endif

static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
{
	u32 reg;
@@ -2939,6 +2956,9 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
	.ndo_set_mac_address	= bcmgenet_set_mac_addr,
	.ndo_do_ioctl		= bcmgenet_ioctl,
	.ndo_set_features	= bcmgenet_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= bcmgenet_poll_controller,
#endif
};

/* Array of GENET hardware parameters/characteristics */
+6 −2
Original line number Diff line number Diff line
@@ -13,9 +13,10 @@

#include <linux/phy.h>
#include <linux/netdevice.h>
#include <linux/netpoll.h>

struct dsa_device_ops {
	netdev_tx_t (*xmit)(struct sk_buff *skb, struct net_device *dev);
	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
	int (*rcv)(struct sk_buff *skb, struct net_device *dev,
		   struct packet_type *pt, struct net_device *orig_dev);
};
@@ -26,7 +27,7 @@ struct dsa_slave_priv {
	 * switch port.
	 */
	struct net_device	*dev;
	netdev_tx_t		(*xmit)(struct sk_buff *skb,
	struct sk_buff *	(*xmit)(struct sk_buff *skb,
					struct net_device *dev);

	/*
@@ -47,6 +48,9 @@ struct dsa_slave_priv {
	int			old_duplex;

	struct net_device	*bridge_dev;
#ifdef CONFIG_NET_POLL_CONTROLLER
	struct netpoll		*netpoll;
#endif
};

/* dsa.c */
+86 −8
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <net/rtnetlink.h>
#include <net/switchdev.h>
#include <linux/if_bridge.h>
#include <linux/netpoll.h>
#include "dsa_priv.h"

/* slave mii_bus handling ***************************************************/
@@ -418,24 +419,53 @@ static int dsa_slave_port_attr_get(struct net_device *dev,
	return 0;
}

static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
static inline netdev_tx_t dsa_netpoll_send_skb(struct dsa_slave_priv *p,
					       struct sk_buff *skb)
{
	struct dsa_slave_priv *p = netdev_priv(dev);

	return p->xmit(skb, dev);
#ifdef CONFIG_NET_POLL_CONTROLLER
	if (p->netpoll)
		netpoll_send_skb(p->netpoll, skb);
#else
	BUG();
#endif
	return NETDEV_TX_OK;
}

static netdev_tx_t dsa_slave_notag_xmit(struct sk_buff *skb,
					struct net_device *dev)
static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct dsa_slave_priv *p = netdev_priv(dev);
	struct sk_buff *nskb;

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	/* Transmit function may have to reallocate the original SKB */
	nskb = p->xmit(skb, dev);
	if (!nskb)
		return NETDEV_TX_OK;

	/* SKB for netpoll still need to be mangled with the protocol-specific
	 * tag to be successfully transmitted
	 */
	if (unlikely(netpoll_tx_running(dev)))
		return dsa_netpoll_send_skb(p, nskb);

	skb->dev = p->parent->dst->master_netdev;
	dev_queue_xmit(skb);
	/* Queue the SKB for transmission on the parent interface, but
	 * do not modify its EtherType
	 */
	nskb->dev = p->parent->dst->master_netdev;
	dev_queue_xmit(nskb);

	return NETDEV_TX_OK;
}

static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
					    struct net_device *dev)
{
	/* Just return the original SKB */
	return skb;
}


/* ethtool operations *******************************************************/
static int
@@ -665,6 +695,49 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
	return ret;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static int dsa_slave_netpoll_setup(struct net_device *dev,
				   struct netpoll_info *ni)
{
	struct dsa_slave_priv *p = netdev_priv(dev);
	struct dsa_switch *ds = p->parent;
	struct net_device *master = ds->dst->master_netdev;
	struct netpoll *netpoll;
	int err = 0;

	netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL);
	if (!netpoll)
		return -ENOMEM;

	err = __netpoll_setup(netpoll, master);
	if (err) {
		kfree(netpoll);
		goto out;
	}

	p->netpoll = netpoll;
out:
	return err;
}

static void dsa_slave_netpoll_cleanup(struct net_device *dev)
{
	struct dsa_slave_priv *p = netdev_priv(dev);
	struct netpoll *netpoll = p->netpoll;

	if (!netpoll)
		return;

	p->netpoll = NULL;

	__netpoll_free_async(netpoll);
}

static void dsa_slave_poll_controller(struct net_device *dev)
{
}
#endif

static const struct ethtool_ops dsa_slave_ethtool_ops = {
	.get_settings		= dsa_slave_get_settings,
	.set_settings		= dsa_slave_set_settings,
@@ -697,6 +770,11 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
	.ndo_fdb_dump		= dsa_slave_fdb_dump,
	.ndo_do_ioctl		= dsa_slave_ioctl,
	.ndo_get_iflink		= dsa_slave_get_iflink,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_netpoll_setup	= dsa_slave_netpoll_setup,
	.ndo_netpoll_cleanup	= dsa_slave_netpoll_cleanup,
	.ndo_poll_controller	= dsa_slave_poll_controller,
#endif
};

static const struct switchdev_ops dsa_slave_switchdev_ops = {
+3 −12
Original line number Diff line number Diff line
@@ -58,14 +58,11 @@
#define BRCM_EG_TC_MASK		0x7
#define BRCM_EG_PID_MASK	0x1f

static netdev_tx_t brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct dsa_slave_priv *p = netdev_priv(dev);
	u8 *brcm_tag;

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	if (skb_cow_head(skb, BRCM_TAG_LEN) < 0)
		goto out_free;

@@ -87,17 +84,11 @@ static netdev_tx_t brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
		brcm_tag[2] = BRCM_IG_DSTMAP2_MASK;
	brcm_tag[3] = (1 << p->port) & BRCM_IG_DSTMAP1_MASK;

	/* Queue the SKB for transmission on the parent interface, but
	 * do not modify its EtherType
	 */
	skb->dev = p->parent->dst->master_netdev;
	dev_queue_xmit(skb);

	return NETDEV_TX_OK;
	return skb;

out_free:
	kfree_skb(skb);
	return NETDEV_TX_OK;
	return NULL;
}

static int brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
Loading