mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-06 13:55:08 +08:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
db316d57b6
@ -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 inline netdev_tx_t dsa_netpoll_send_skb(struct dsa_slave_priv *p,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
#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_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||
struct sk_buff *nskb;
|
||||
|
||||
return p->xmit(skb, dev);
|
||||
}
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
static netdev_tx_t dsa_slave_notag_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||
/* Transmit function may have to reallocate the original SKB */
|
||||
nskb = p->xmit(skb, dev);
|
||||
if (!nskb)
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
skb->dev = p->parent->dst->master_netdev;
|
||||
dev_queue_xmit(skb);
|
||||
/* 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);
|
||||
|
||||
/* 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,
|
||||
|
Loading…
Reference in New Issue
Block a user