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

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
......@@ -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"
......
......@@ -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 */
......
......@@ -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 */
......
......@@ -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 = {
......
......@@ -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,
......
......@@ -15,14 +15,11 @@
#define DSA_HLEN 4
static netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
u8 *dsa_header;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
/*
* Convert the outermost 802.1q tag to a DSA tag for tagged
* packets, or insert a DSA tag between the addresses and
......@@ -63,14 +60,11 @@ static netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev)
dsa_header[3] = 0x00;
}
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 dsa_rcv(struct sk_buff *skb, struct net_device *dev,
......
......@@ -16,14 +16,11 @@
#define DSA_HLEN 4
#define EDSA_HLEN 8
static netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
u8 *edsa_header;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
/*
* Convert the outermost 802.1q tag to a DSA tag and prepend
* a DSA ethertype field is the packet is tagged, or insert
......@@ -76,14 +73,11 @@ static netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev)
edsa_header[7] = 0x00;
}
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 edsa_rcv(struct sk_buff *skb, struct net_device *dev,
......
......@@ -13,16 +13,13 @@
#include <linux/slab.h>
#include "dsa_priv.h"
static netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct sk_buff *nskb;
int padlen;
u8 *trailer;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
/*
* We have to make sure that the trailer ends up as the very
* last 4 bytes of the packet. This means that we have to pad
......@@ -36,7 +33,7 @@ static netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev)
nskb = alloc_skb(NET_IP_ALIGN + skb->len + padlen + 4, GFP_ATOMIC);
if (nskb == NULL) {
kfree_skb(skb);
return NETDEV_TX_OK;
return NULL;
}
skb_reserve(nskb, NET_IP_ALIGN);
......@@ -57,10 +54,7 @@ static netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev)
trailer[2] = 0x10;
trailer[3] = 0x00;
nskb->dev = p->parent->dst->master_netdev;
dev_queue_xmit(nskb);
return NETDEV_TX_OK;
return nskb;
}
static int trailer_rcv(struct sk_buff *skb, struct net_device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment