* [PATCH 2/5] ARM: sunxi: Add wemac to sun4i dtsi
From: Maxime Ripard @ 2013-03-15 20:50 UTC (permalink / raw)
To: linux-arm-kernel; +Cc: Russell King, netdev, linux-kernel, sunny, shuge, kevin
In-Reply-To: <1363380605-6577-1-git-send-email-maxime.ripard@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 03d2b53..f3c2158 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -47,5 +47,12 @@
allwinner,pull = <0>;
};
};
+
+ wemac: ethernet@01c0b000 {
+ compatible = "davicom,wemac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <55>;
+ status = "disabled";
+ };
};
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/5] net: Add davicom wemac ethernet driver found on Allwinner A10 SoC's
From: Maxime Ripard @ 2013-03-15 20:50 UTC (permalink / raw)
To: linux-arm-kernel
Cc: kevin, sunny, shuge, netdev, Stefan Roese, Grant Likely,
Rob Herring, Rob Landley, devicetree-discuss, linux-doc,
linux-kernel
In-Reply-To: <1363380605-6577-1-git-send-email-maxime.ripard@free-electrons.com>
From: Stefan Roese <sr@denx.de>
The Allwinner A10 has an ethernet controller that is advertised as
coming from Davicom.
The exact feature set of this controller is unknown, since there is no
public documentation for this IP, and this driver is mostly the one
published by Allwinner that has been heavily cleaned up.
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../devicetree/bindings/net/davicom-wemac.txt | 20 +
drivers/net/ethernet/Makefile | 2 +-
drivers/net/ethernet/davicom/Kconfig | 31 +
drivers/net/ethernet/davicom/Makefile | 1 +
drivers/net/ethernet/davicom/wemac.c | 1033 ++++++++++++++++++++
drivers/net/ethernet/davicom/wemac.h | 130 +++
6 files changed, 1216 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/net/davicom-wemac.txt
create mode 100644 drivers/net/ethernet/davicom/wemac.c
create mode 100644 drivers/net/ethernet/davicom/wemac.h
diff --git a/Documentation/devicetree/bindings/net/davicom-wemac.txt b/Documentation/devicetree/bindings/net/davicom-wemac.txt
new file mode 100644
index 0000000..516cf31
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/davicom-wemac.txt
@@ -0,0 +1,20 @@
+* Marvell Armada 370 / Armada XP Ethernet Controller (NETA)
+
+Required properties:
+- compatible: should be "marvell,armada-370-neta".
+- reg: address and length of the register set for the device.
+- interrupts: interrupt for the device
+
+Optional properties:
+- allwinner,power-gpios: gpio pointer if the phy needs to be
+ enabled through a GPIO.
+- (local-)mac-address: mac address to be used by this driver
+
+Example:
+
+wemac: ethernet@01c0b000 {
+ compatible = "davicom,wemac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <55>;
+ allwinner,power-gpios = <&pio 7 19 0>;
+};
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 8268d85..5871143 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_NET_CALXEDA_XGMAC) += calxeda/
obj-$(CONFIG_NET_VENDOR_CHELSIO) += chelsio/
obj-$(CONFIG_NET_VENDOR_CIRRUS) += cirrus/
obj-$(CONFIG_NET_VENDOR_CISCO) += cisco/
-obj-$(CONFIG_DM9000) += davicom/
+obj-$(CONFIG_NET_VENDOR_DAVICOM) += davicom/
obj-$(CONFIG_DNET) += dnet.o
obj-$(CONFIG_NET_VENDOR_DEC) += dec/
obj-$(CONFIG_NET_VENDOR_DLINK) += dlink/
diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
index 9745fe5..0185e62 100644
--- a/drivers/net/ethernet/davicom/Kconfig
+++ b/drivers/net/ethernet/davicom/Kconfig
@@ -2,6 +2,23 @@
# Davicom device configuration
#
+config NET_VENDOR_DAVICOM
+ bool "Davicom devices"
+ default y
+ depends on ARM || BLACKFIN || MIPS || COLDFIRE
+ ---help---
+ If you have a network (Ethernet) card belonging to this
+ class, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly
+ affect the kernel: saying N will just cause the configurator
+ to skip all the questions about Davicom cards. If you say Y,
+ you will be asked for your specific card in the following
+ questions.
+
+if NET_VENDOR_DAVICOM
+
config DM9000
tristate "DM9000 support"
depends on ARM || BLACKFIN || MIPS || COLDFIRE
@@ -22,3 +39,17 @@ config DM9000_FORCE_SIMPLE_PHY_POLL
bit to determine if the link is up or down instead of the more
costly MII PHY reads. Note, this will not work if the chip is
operating with an external PHY.
+
+config WEMAC
+ tristate "WEMAC support"
+ depends on OF
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Support for Davicom WEMAC ethernet driver.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wemac.
+
+endif # NET_VENDOR_DAVICOM
diff --git a/drivers/net/ethernet/davicom/Makefile b/drivers/net/ethernet/davicom/Makefile
index 74b31f0..803297e 100644
--- a/drivers/net/ethernet/davicom/Makefile
+++ b/drivers/net/ethernet/davicom/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_DM9000) += dm9000.o
+obj-$(CONFIG_WEMAC) += wemac.o
diff --git a/drivers/net/ethernet/davicom/wemac.c b/drivers/net/ethernet/davicom/wemac.c
new file mode 100644
index 0000000..8468baf
--- /dev/null
+++ b/drivers/net/ethernet/davicom/wemac.c
@@ -0,0 +1,1033 @@
+/*
+ * Allwinner WEMAC Fast Ethernet driver for Linux.
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on the Linux driver provided by Allwinner:
+ * Copyright (C) 1997 Sten Wang
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include "wemac.h"
+
+#define DRV_NAME "wemac"
+#define DRV_VERSION "1.01"
+
+#define WEMAC_MAX_FRAME_LEN 0x0600
+#define WEMAC_PHY 0x100 /* PHY address 0x01 */
+
+/* Transmit timeout, default 5 seconds. */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+/* WEMAC register address locking.
+ *
+ * The WEMAC uses an address register to control where data written
+ * to the data register goes. This means that the address register
+ * must be preserved over interrupts or similar calls.
+ *
+ * During interrupt and other critical calls, a spinlock is used to
+ * protect the system, but the calls themselves save the address
+ * in the address register in case they are interrupting another
+ * access to the device.
+ *
+ * For general accesses a lock is provided so that calls which are
+ * allowed to sleep are serialised so that the address register does
+ * not need to be saved. This lock also serves to serialise access
+ * to the EEPROM and PHY access registers which are shared between
+ * these two devices.
+ */
+
+/* The driver supports the original WEMACE, and now the two newer
+ * devices, WEMACA and WEMACB.
+ */
+
+struct wemac_board_info {
+ struct clk *clk;
+ struct device *dev;
+ spinlock_t lock;
+ void __iomem *membase;
+ struct mii_if_info mii;
+ u32 msg_enable;
+ struct net_device *ndev;
+ struct mutex phy_lock;
+ struct delayed_work phy_poll;
+ unsigned power_gpio;
+ struct sk_buff *skb_last;
+ u16 tx_fifo_stat;
+};
+
+static inline struct wemac_board_info *to_wemac_board(struct net_device *dev)
+{
+ return netdev_priv(dev);
+}
+
+static int wemac_phy_read(struct net_device *dev, int phyaddr, int reg)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ unsigned long flags;
+ int ret;
+
+ mutex_lock(&db->phy_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+ /* issue the phy address and reg */
+ writel(phyaddr | reg, db->membase + EMAC_MAC_MADR_REG);
+ /* pull up the phy io line */
+ writel(0x1, db->membase + EMAC_MAC_MCMD_REG);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ /* Wait read complete */
+ mdelay(1);
+
+ /* push down the phy io line and read data */
+ spin_lock_irqsave(&db->lock, flags);
+ /* push down the phy io line */
+ writel(0x0, db->membase + EMAC_MAC_MCMD_REG);
+ /* and read data */
+ ret = readl(db->membase + EMAC_MAC_MRDD_REG);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->phy_lock);
+
+ return ret;
+}
+
+/* Write a word to phyxcer */
+static void wemac_phy_write(struct net_device *dev,
+ int phyaddr, int reg, int value)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ unsigned long flags;
+
+ mutex_lock(&db->phy_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+ /* issue the phy address and reg */
+ writel(phyaddr | reg, db->membase + EMAC_MAC_MADR_REG);
+ /* pull up the phy io line */
+ writel(0x1, db->membase + EMAC_MAC_MCMD_REG);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ /* Wait write complete */
+ mdelay(1);
+
+ spin_lock_irqsave(&db->lock, flags);
+ /* push down the phy io line */
+ writel(0x0, db->membase + EMAC_MAC_MCMD_REG);
+ /* and write data */
+ writel(value, db->membase + EMAC_MAC_MWTD_REG);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->phy_lock);
+}
+
+static int emacrx_completed_flag = 1;
+
+static void wemac_reset(struct wemac_board_info *db)
+{
+ dev_dbg(db->dev, "resetting device\n");
+
+ /* RESET device */
+ writel(0, db->membase + EMAC_CTL_REG);
+ udelay(200);
+ writel(EMAC_CTL_RESET, db->membase + EMAC_CTL_REG);
+ udelay(200);
+}
+
+static void wemac_outblk_32bit(void __iomem *reg, void *data, int count)
+{
+ writesl(reg, data, round_up(count, 4) / 4);
+}
+
+static void wemac_inblk_32bit(void __iomem *reg, void *data, int count)
+{
+ readsl(reg, data, round_up(count, 4) / 4);
+}
+
+static void wemac_dumpblk_32bit(void __iomem *reg, int count)
+{
+ int i;
+ int tmp;
+
+ for (i = 0; i < (round_up(count, 4) / 4); i++)
+ tmp = readl(reg);
+}
+
+static void wemac_schedule_poll(struct wemac_board_info *db)
+{
+ schedule_delayed_work(&db->phy_poll, HZ * 2);
+}
+
+static int wemac_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+}
+
+/* ethtool ops */
+static void wemac_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+}
+
+static u32 wemac_get_msglevel(struct net_device *dev)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ return dm->msg_enable;
+}
+
+static void wemac_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ dm->msg_enable = value;
+}
+
+static int wemac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ mii_ethtool_gset(&dm->mii, cmd);
+
+ return 0;
+}
+
+static int wemac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ return mii_ethtool_sset(&dm->mii, cmd);
+}
+
+static int wemac_nway_reset(struct net_device *dev)
+{
+ struct wemac_board_info *dm = to_wemac_board(dev);
+
+ return mii_nway_restart(&dm->mii);
+}
+
+static u32 wemac_get_link(struct net_device *dev)
+{
+ return wemac_phy_read(dev, WEMAC_PHY, 1) & 0x04 ? 1 : 0;
+}
+
+static const struct ethtool_ops wemac_ethtool_ops = {
+ .get_drvinfo = wemac_get_drvinfo,
+ .get_settings = wemac_get_settings,
+ .set_settings = wemac_set_settings,
+ .get_msglevel = wemac_get_msglevel,
+ .set_msglevel = wemac_set_msglevel,
+ .nway_reset = wemac_nway_reset,
+ .get_link = wemac_get_link,
+};
+
+unsigned int phy_link_check(struct net_device *dev)
+{
+ unsigned int reg_val;
+
+ reg_val = wemac_phy_read(dev, WEMAC_PHY, 1);
+
+ if (reg_val & 0x4) {
+ netdev_info(dev, "EMAC PHY Linked...\n");
+ return 1;
+ } else {
+ netdev_info(dev, "EMAC PHY Link waiting......\n");
+ return 0;
+ }
+}
+
+unsigned int emac_setup(struct net_device *ndev)
+{
+ unsigned int reg_val;
+ unsigned int phy_val;
+ unsigned int duplex_flag;
+ struct wemac_board_info *db = netdev_priv(ndev);
+
+ /* set up TX */
+ reg_val = readl(db->membase + EMAC_TX_MODE_REG);
+
+ writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN,
+ db->membase + EMAC_TX_MODE_REG);
+
+ /* set up RX */
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+
+ writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN |
+ EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN |
+ EMAC_RX_CTL_ACCEPT_MULTICAST_EN |
+ EMAC_RX_CTL_ACCEPT_BROADCAST_EN,
+ db->membase + EMAC_RX_CTL_REG);
+
+ /* set MAC */
+ /* set MAC CTL0 */
+ reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
+ writel(reg_val | EMAC_MAC_CTL0_RX_FLOW_CTL_EN |
+ EMAC_MAC_CTL0_TX_FLOW_CTL_EN,
+ db->membase + EMAC_MAC_CTL0_REG);
+
+ /* set MAC CTL1 */
+ reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
+ phy_val = wemac_phy_read(ndev, WEMAC_PHY, 0);
+ dev_dbg(db->dev, "PHY SETUP, reg 0 value: %x\n", phy_val);
+ duplex_flag = !!(phy_val & EMAC_PHY_DUPLEX);
+
+ if (duplex_flag)
+ reg_val |= EMAC_MAC_CTL1_DUPLEX_EN;
+
+ reg_val |= EMAC_MAC_CTL1_LEN_CHECK_EN;
+ reg_val |= EMAC_MAC_CTL1_CRC_EN;
+ reg_val |= EMAC_MAC_CTL1_PAD_EN;
+ writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
+
+ /* set up IPGT */
+ writel(EMAC_MAC_IPGT_FULL_DUPLEX, db->membase + EMAC_MAC_IPGT_REG);
+
+ /* set up IPGR */
+ writel((EMAC_MAC_IPGR_IPG1 << 8) | EMAC_MAC_IPGR_IPG2,
+ db->membase + EMAC_MAC_IPGR_REG);
+
+ /* set up Collison window */
+ writel((EMAC_MAC_CLRT_COLLISION_WINDOW << 8) | EMAC_MAC_CLRT_RM,
+ db->membase + EMAC_MAC_CLRT_REG);
+
+ /* set up Max Frame Length */
+ writel(WEMAC_MAX_FRAME_LEN,
+ db->membase + EMAC_MAC_MAXF_REG);
+
+ return 0;
+}
+
+unsigned int wemac_powerup(struct net_device *ndev)
+{
+ struct wemac_board_info *db = netdev_priv(ndev);
+ unsigned int reg_val;
+
+ /* initial EMAC */
+ /* flush RX FIFO */
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val |= 0x8;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+ udelay(1);
+
+ /* initial MAC */
+ /* soft reset MAC */
+ reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
+ reg_val &= ~EMAC_MAC_CTL0_SOFT_RESET;
+ writel(reg_val, db->membase + EMAC_MAC_CTL0_REG);
+
+ /* set MII clock */
+ reg_val = readl(db->membase + EMAC_MAC_MCFG_REG);
+ reg_val &= (~(0xf << 2));
+ reg_val |= (0xD << 2);
+ writel(reg_val, db->membase + EMAC_MAC_MCFG_REG);
+
+ /* clear RX counter */
+ writel(0x0, db->membase + EMAC_RX_FBC_REG);
+
+ /* disable all interrupt and clear interrupt status */
+ writel(0, db->membase + EMAC_INT_CTL_REG);
+ reg_val = readl(db->membase + EMAC_INT_STA_REG);
+ writel(reg_val, db->membase + EMAC_INT_STA_REG);
+
+ udelay(1);
+
+ /* set up EMAC */
+ emac_setup(ndev);
+
+ /* set mac_address to chip */
+ writel(ndev->dev_addr[0] << 16 | ndev->dev_addr[1] << 8 | ndev->
+ dev_addr[2], db->membase + EMAC_MAC_A1_REG);
+ writel(ndev->dev_addr[3] << 16 | ndev->dev_addr[4] << 8 | ndev->
+ dev_addr[5], db->membase + EMAC_MAC_A0_REG);
+
+ mdelay(1);
+
+ return 1;
+}
+
+static void wemac_poll_work(struct work_struct *w)
+{
+ struct delayed_work *dw = container_of(w, struct delayed_work, work);
+ struct wemac_board_info *db = container_of(dw,
+ struct wemac_board_info,
+ phy_poll);
+ struct net_device *ndev = db->ndev;
+
+ mii_check_media(&db->mii, netif_msg_link(db), 0);
+
+ if (netif_running(ndev))
+ wemac_schedule_poll(db);
+}
+
+static int wemac_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+ struct wemac_board_info *db = netdev_priv(dev);
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+
+ writel(dev->dev_addr[0] << 16 | dev->dev_addr[1] << 8 | dev->
+ dev_addr[2], db->membase + EMAC_MAC_A1_REG);
+ writel(dev->dev_addr[3] << 16 | dev->dev_addr[4] << 8 | dev->
+ dev_addr[5], db->membase + EMAC_MAC_A0_REG);
+
+ return 0;
+}
+
+/* Initialize wemac board */
+static void wemac_init_wemac(struct net_device *dev)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ unsigned int phy_reg;
+ unsigned int reg_val;
+
+ if (gpio_is_valid(db->power_gpio))
+ gpio_set_value(db->power_gpio, 1);
+
+ /* PHY POWER UP */
+ phy_reg = wemac_phy_read(dev, WEMAC_PHY, 0);
+ wemac_phy_write(dev, WEMAC_PHY, 0, phy_reg & (~(1 << 11)));
+ mdelay(1);
+
+ phy_reg = wemac_phy_read(dev, WEMAC_PHY, 0);
+
+ /* set EMAC SPEED, depend on PHY */
+ reg_val = readl(db->membase + EMAC_MAC_SUPP_REG);
+ reg_val &= (~(0x1 << 8));
+ reg_val |= (((phy_reg & (1 << 13)) >> 13) << 8);
+ writel(reg_val, db->membase + EMAC_MAC_SUPP_REG);
+
+ /* set duplex depend on phy */
+ reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
+ reg_val &= (~(0x1 << 0));
+ reg_val |= (((phy_reg & (1 << 8)) >> 8) << 0);
+ writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
+
+ /* enable RX/TX */
+ reg_val = readl(db->membase + EMAC_CTL_REG);
+ writel(reg_val | EMAC_CTL_RESET | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN,
+ db->membase + EMAC_CTL_REG);
+
+ /* enable RX/TX0/RX Hlevel interrup */
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0) | (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+ /* Init Driver variable */
+ db->tx_fifo_stat = 0;
+ dev->trans_start = 0;
+}
+
+/* Our watchdog timed out. Called by the networking layer */
+static void wemac_timeout(struct net_device *dev)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ unsigned long flags;
+
+ if (netif_msg_timer(db))
+ dev_err(db->dev, "tx time out.\n");
+
+ /* Save previous register address */
+ spin_lock_irqsave(&db->lock, flags);
+
+ netif_stop_queue(dev);
+ wemac_reset(db);
+ wemac_init_wemac(dev);
+ /* We can accept TX packets again */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+
+ /* Restore previous register address */
+ spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/* Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+static int wemac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ unsigned long channel;
+ unsigned long flags;
+
+ channel = db->tx_fifo_stat & 3;
+ if (channel == 3)
+ return 1;
+
+ channel = (channel == 1 ? 1 : 0);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ writel(channel, db->membase + EMAC_TX_INS_REG);
+
+ wemac_outblk_32bit(db->membase + EMAC_TX_IO_DATA_REG,
+ skb->data, skb->len);
+ dev->stats.tx_bytes += skb->len;
+
+ db->tx_fifo_stat |= 1 << channel;
+ /* TX control: First packet immediately send, second packet queue */
+ if (channel == 0) {
+ /* set TX len */
+ writel(skb->len, db->membase + EMAC_TX_PL0_REG);
+ /* start translate from fifo to phy */
+ writel(readl(db->membase + EMAC_TX_CTL0_REG) | 1,
+ db->membase + EMAC_TX_CTL0_REG);
+
+ /* save the time stamp */
+ dev->trans_start = jiffies;
+ } else if (channel == 1) {
+ /* set TX len */
+ writel(skb->len, db->membase + EMAC_TX_PL1_REG);
+ /* start translate from fifo to phy */
+ writel(readl(db->membase + EMAC_TX_CTL1_REG) | 1,
+ db->membase + EMAC_TX_CTL1_REG);
+
+ /* save the time stamp */
+ dev->trans_start = jiffies;
+ }
+
+ if ((db->tx_fifo_stat & 3) == 3) {
+ /* Second packet */
+ netif_stop_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ /* free this SKB */
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+/* WEMAC interrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+static void wemac_tx_done(struct net_device *dev, struct wemac_board_info *db,
+ unsigned int tx_status)
+{
+ /* One packet sent complete */
+ db->tx_fifo_stat &= ~(tx_status & 3);
+ if (3 == (tx_status & 3))
+ dev->stats.tx_packets += 2;
+ else
+ dev->stats.tx_packets++;
+
+ if (netif_msg_tx_done(db))
+ dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
+
+ netif_wake_queue(dev);
+}
+
+/* Received a packet and pass to upper layer
+ */
+static void wemac_rx(struct net_device *dev)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+ struct sk_buff *skb;
+ u8 *rdptr;
+ bool good_packet;
+ static int rxlen_last;
+ unsigned int reg_val;
+ u32 rxhdr, rxstatus, rxcount, rxlen;
+
+ /* Check packet ready or not */
+ while (1) {
+ /* race warning: the first packet might arrive with
+ * the interrupts disabled, but the second will fix
+ * it
+ */
+ rxcount = readl(db->membase + EMAC_RX_FBC_REG);
+
+ if (netif_msg_rx_status(db))
+ dev_dbg(db->dev, "RXCount: %x\n", rxcount);
+
+ if ((db->skb_last != NULL) && (rxlen_last > 0)) {
+ dev->stats.rx_bytes += rxlen_last;
+
+ /* Pass to upper layer */
+ db->skb_last->protocol = eth_type_trans(db->skb_last,
+ dev);
+ netif_rx(db->skb_last);
+ dev->stats.rx_packets++;
+ db->skb_last = NULL;
+ rxlen_last = 0;
+
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ reg_val &= ~EMAC_RX_CTL_DMA_EN;
+ writel(reg_val, db->membase + EMAC_RX_CTL_REG);
+ }
+
+ if (!rxcount) {
+ emacrx_completed_flag = 1;
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0) | (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+ /* had one stuck? */
+ rxcount = readl(db->membase + EMAC_RX_FBC_REG);
+ if (!rxcount)
+ return;
+ }
+
+ reg_val = readl(db->membase + EMAC_RX_IO_DATA_REG);
+ if (netif_msg_rx_status(db))
+ dev_dbg(db->dev, "receive header: %x\n", reg_val);
+ if (reg_val != 0x0143414d) {
+ /* disable RX */
+ reg_val = readl(db->membase + EMAC_CTL_REG);
+ writel(reg_val & ~EMAC_CTL_RX_EN,
+ db->membase + EMAC_CTL_REG);
+
+ /* Flush RX FIFO */
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ writel(reg_val | (1 << 3),
+ db->membase + EMAC_RX_CTL_REG);
+
+ do {
+ reg_val = readl(db->membase + EMAC_RX_CTL_REG);
+ } while (reg_val & (1 << 3));
+
+ /* enable RX */
+ reg_val = readl(db->membase + EMAC_CTL_REG);
+ writel(reg_val | EMAC_CTL_RX_EN,
+ db->membase + EMAC_CTL_REG);
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0) | (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+
+ emacrx_completed_flag = 1;
+
+ return;
+ }
+
+ /* A packet ready now & Get status/length */
+ good_packet = true;
+
+ wemac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+ &rxhdr, sizeof(rxhdr));
+
+ if (netif_msg_rx_status(db))
+ dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr)));
+
+ rxlen = EMAC_RX_IO_DATA_LEN(rxhdr);
+ rxstatus = EMAC_RX_IO_DATA_STATUS(rxhdr);
+
+ if (netif_msg_rx_status(db))
+ dev_dbg(db->dev, "RX: status %02x, length %04x\n",
+ rxstatus, rxlen);
+
+ /* Packet Status check */
+ if (rxlen < 0x40) {
+ good_packet = false;
+ if (netif_msg_rx_err(db))
+ dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
+ }
+
+ if (unlikely(!(rxstatus & EMAC_RX_IO_DATA_STATUS_OK))) {
+ good_packet = false;
+
+ if (rxstatus & EMAC_RX_IO_DATA_STATUS_CRC_ERR) {
+ if (netif_msg_rx_err(db))
+ dev_dbg(db->dev, "crc error\n");
+ dev->stats.rx_crc_errors++;
+ }
+
+ if (rxstatus & EMAC_RX_IO_DATA_STATUS_LEN_ERR) {
+ if (netif_msg_rx_err(db))
+ dev_dbg(db->dev, "length error\n");
+ dev->stats.rx_length_errors++;
+ }
+ }
+
+ /* Move data from WEMAC */
+ skb = dev_alloc_skb(rxlen + 4);
+ if (good_packet && skb) {
+ skb_reserve(skb, 2);
+ rdptr = (u8 *) skb_put(skb, rxlen - 4);
+
+ /* Read received packet from RX SRAM */
+ if (netif_msg_rx_status(db))
+ dev_dbg(db->dev, "RxLen %x\n", rxlen);
+
+ wemac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+ rdptr, rxlen);
+ dev->stats.rx_bytes += rxlen;
+
+ /* Pass to upper layer */
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ } else {
+ /* need to dump the packet's data */
+ wemac_dumpblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
+ rxlen);
+ }
+ }
+}
+
+static irqreturn_t wemac_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct wemac_board_info *db = netdev_priv(dev);
+ int int_status;
+ unsigned long flags;
+ unsigned int reg_val;
+
+ /* A real interrupt coming */
+
+ /* holders of db->lock must always block IRQs */
+ spin_lock_irqsave(&db->lock, flags);
+
+ /* Disable all interrupts */
+ writel(0, db->membase + EMAC_INT_CTL_REG);
+
+ /* Got WEMAC interrupt status */
+ /* Got ISR */
+ int_status = readl(db->membase + EMAC_INT_STA_REG);
+ /* Clear ISR status */
+ writel(int_status, db->membase + EMAC_INT_STA_REG);
+
+ if (netif_msg_intr(db))
+ dev_dbg(db->dev, "emac interrupt %02x\n", int_status);
+
+ /* Received the coming packet */
+ if ((int_status & 0x100) && (emacrx_completed_flag == 1)) {
+ /* carrier lost */
+ emacrx_completed_flag = 0;
+ wemac_rx(dev);
+ }
+
+ /* Transmit Interrupt check */
+ if (int_status & (0x01 | 0x02))
+ wemac_tx_done(dev, db, int_status);
+
+ if (int_status & (0x04 | 0x08))
+ netdev_info(dev, " ab : %x\n", int_status);
+
+ /* Re-enable interrupt mask */
+ if (emacrx_completed_flag == 1) {
+ reg_val = readl(db->membase + EMAC_INT_CTL_REG);
+ reg_val |= (0xf << 0) | (0x01 << 8);
+ writel(reg_val, db->membase + EMAC_INT_CTL_REG);
+ }
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Used by netconsole
+ */
+static void wemac_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ wemac_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
+/* Open the interface.
+ * The interface is opened whenever "ifconfig" actives it.
+ */
+static int wemac_open(struct net_device *dev)
+{
+ struct wemac_board_info *db = netdev_priv(dev);
+
+ if (netif_msg_ifup(db))
+ dev_dbg(db->dev, "enabling %s\n", dev->name);
+
+ if (devm_request_irq(db->dev, dev->irq, &wemac_interrupt,
+ 0, dev->name, dev))
+ return -EAGAIN;
+
+ /* Initialize WEMAC board */
+ wemac_reset(db);
+ wemac_init_wemac(dev);
+
+ mii_check_media(&db->mii, netif_msg_link(db), 1);
+ netif_start_queue(dev);
+
+ wemac_schedule_poll(db);
+
+ return 0;
+}
+
+static void wemac_shutdown(struct net_device *dev)
+{
+ unsigned int reg_val;
+ struct wemac_board_info *db = netdev_priv(dev);
+
+ /* RESET device */
+ reg_val = wemac_phy_read(dev, WEMAC_PHY, 0);
+
+ /* PHY RESET */
+ wemac_phy_write(dev, WEMAC_PHY, 0, reg_val | (1 << 15));
+ udelay(10);
+ reg_val = wemac_phy_read(dev, WEMAC_PHY, 0);
+ if (reg_val & (1 << 15))
+ dev_warn(db->dev, "phy_reset not complete. value of reg0: %x\n",
+ reg_val);
+ /* PHY POWER DOWN */
+ wemac_phy_write(dev, WEMAC_PHY, 0, reg_val | (1 << 11));
+
+ /* Disable all interrupt */
+ writel(0, db->membase + EMAC_INT_CTL_REG);
+
+ /* clear interupt status */
+ reg_val = readl(db->membase + EMAC_INT_STA_REG);
+ writel(reg_val, db->membase + EMAC_INT_STA_REG);
+
+ /* Disable RX/TX */
+ reg_val = readl(db->membase + EMAC_CTL_REG);
+ reg_val &= ~(EMAC_CTL_TX_EN | EMAC_CTL_RX_EN | EMAC_CTL_RESET);
+ writel(reg_val, db->membase + EMAC_CTL_REG);
+}
+
+/* Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+static int wemac_stop(struct net_device *ndev)
+{
+ struct wemac_board_info *db = netdev_priv(ndev);
+
+ if (netif_msg_ifdown(db))
+ dev_dbg(db->dev, "shutting down %s\n", ndev->name);
+
+ cancel_delayed_work_sync(&db->phy_poll);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ wemac_shutdown(ndev);
+
+ return 0;
+}
+
+static const struct net_device_ops wemac_netdev_ops = {
+ .ndo_open = wemac_open,
+ .ndo_stop = wemac_stop,
+ .ndo_start_xmit = wemac_start_xmit,
+ .ndo_tx_timeout = wemac_timeout,
+ .ndo_do_ioctl = wemac_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = wemac_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = wemac_poll_controller,
+#endif
+};
+
+/* Search WEMAC board, allocate space and register it
+ */
+static int wemac_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct wemac_board_info *db;
+ struct net_device *ndev;
+ int ret = 0;
+ const char *mac_addr;
+
+ ndev = alloc_etherdev(sizeof(struct wemac_board_info));
+ if (!ndev) {
+ dev_err(&pdev->dev, "could not allocate device.\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ db = netdev_priv(ndev);
+ memset(db, 0, sizeof(*db));
+
+ db->dev = &pdev->dev;
+ db->ndev = ndev;
+
+ spin_lock_init(&db->lock);
+ mutex_init(&db->phy_lock);
+
+ INIT_DELAYED_WORK(&db->phy_poll, wemac_poll_work);
+
+ db->membase = of_iomap(np, 0);
+ if (!db->membase) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ return -ENOMEM;
+ goto out;
+ }
+
+ /* fill in parameters for net-dev structure */
+ ndev->base_addr = (unsigned long)db->membase;
+ ndev->irq = irq_of_parse_and_map(np, 0);
+ if (ndev->irq == -ENXIO) {
+ netdev_err(ndev, "No irq resource\n");
+ ret = ndev->irq;
+ goto out;
+ }
+
+ /* Read MAC-address from DT */
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+
+ /* Check if the MAC address is valid, if not get a random one */
+ if (!is_valid_ether_addr(ndev->dev_addr)) {
+ eth_hw_addr_random(ndev);
+ dev_warn(&ndev->dev, "using random MAC address %pM\n",
+ ndev->dev_addr);
+ }
+
+ db->power_gpio = of_get_named_gpio(np, "allwinner,power-gpios", 0);
+ if (gpio_is_valid(db->power_gpio)) {
+ ret = devm_gpio_request_one(&pdev->dev, db->power_gpio,
+ GPIOF_OUT_INIT_LOW, "wemac_power");
+ if (ret)
+ goto out;
+ } else {
+ if (db->power_gpio == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ }
+
+ wemac_powerup(ndev);
+ wemac_reset(db);
+
+ ether_setup(ndev);
+
+ ndev->netdev_ops = &wemac_netdev_ops;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+ ndev->ethtool_ops = &wemac_ethtool_ops;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = &wemac_poll_controller;
+#endif
+
+ db->msg_enable =
+ 0xffffffff & (~NETIF_MSG_TX_DONE) & (~NETIF_MSG_INTR) &
+ (~NETIF_MSG_RX_STATUS);
+ db->mii.phy_id = WEMAC_PHY;
+ db->mii.phy_id_mask = 0x1f;
+ db->mii.reg_num_mask = 0x1f;
+ /* change force_media value to 0 to force check link status */
+ db->mii.force_media = 0;
+ /* change full_duplex value to 0 to set initial duplex as half */
+ db->mii.full_duplex = 0;
+ db->mii.dev = ndev;
+ db->mii.mdio_read = wemac_phy_read;
+ db->mii.mdio_write = wemac_phy_write;
+
+ platform_set_drvdata(pdev, ndev);
+ ret = register_netdev(ndev);
+ if (ret) {
+ dev_err(&pdev->dev, "Registering netdev failed!\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n",
+ ndev->name, db->membase, ndev->irq, ndev->dev_addr);
+
+ return 0;
+
+out:
+ dev_err(db->dev, "not found (%d).\n", ret);
+
+ free_netdev(ndev);
+
+ return ret;
+}
+
+static int wemac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+
+ dev_dbg(&pdev->dev, "released and freed device\n");
+ return 0;
+}
+
+static int wemac_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(dev);
+ struct wemac_board_info *db = netdev_priv(ndev);
+
+ if (mii_link_ok(&db->mii))
+ netif_carrier_off(ndev);
+ netif_device_detach(ndev);
+ wemac_shutdown(ndev);
+
+ return 0;
+}
+
+static int wemac_resume(struct platform_device *dev)
+{
+ struct net_device *ndev = platform_get_drvdata(dev);
+ struct wemac_board_info *db = netdev_priv(ndev);
+
+ wemac_reset(db);
+ wemac_init_wemac(ndev);
+ netif_device_attach(ndev);
+ if (mii_link_ok(&db->mii))
+ netif_carrier_on(ndev);
+
+ return 0;
+}
+
+static const struct of_device_id wemac_of_match[] = {
+ {.compatible = "davicom,wemac",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, wemac_of_match);
+
+static struct platform_driver wemac_driver = {
+ .driver = {
+ .name = "davicom-wemac",
+ .of_match_table = wemac_of_match,
+ },
+ .probe = wemac_probe,
+ .remove = wemac_remove,
+ .suspend = wemac_suspend,
+ .resume = wemac_resume,
+};
+
+module_platform_driver(wemac_driver);
+
+MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner sunxi wemac network driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/davicom/wemac.h b/drivers/net/ethernet/davicom/wemac.h
new file mode 100644
index 0000000..5758c7d
--- /dev/null
+++ b/drivers/net/ethernet/davicom/wemac.h
@@ -0,0 +1,130 @@
+/*
+ * drivers/net/sun4i/sun4i_wemac.h
+ *
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _WEMAC_H_
+#define _WEMAC_H_
+
+#define EMAC_CTL_REG (0x00)
+#define EMAC_CTL_RESET (1 << 0)
+#define EMAC_CTL_TX_EN (1 << 1)
+#define EMAC_CTL_RX_EN (1 << 2)
+#define EMAC_TX_MODE_REG (0x04)
+#define EMAC_TX_MODE_ABORTED_FRAME_EN (1 << 0)
+#define EMAC_TX_MODE_DMA_EN (1 << 1)
+#define EMAC_TX_FLOW_REG (0x08)
+#define EMAC_TX_CTL0_REG (0x0c)
+#define EMAC_TX_CTL1_REG (0x10)
+#define EMAC_TX_INS_REG (0x14)
+#define EMAC_TX_PL0_REG (0x18)
+#define EMAC_TX_PL1_REG (0x1c)
+#define EMAC_TX_STA_REG (0x20)
+#define EMAC_TX_IO_DATA_REG (0x24)
+#define EMAC_TX_IO_DATA1_REG (0x28)
+#define EMAC_TX_TSVL0_REG (0x2c)
+#define EMAC_TX_TSVH0_REG (0x30)
+#define EMAC_TX_TSVL1_REG (0x34)
+#define EMAC_TX_TSVH1_REG (0x38)
+#define EMAC_RX_CTL_REG (0x3c)
+#define EMAC_RX_CTL_AUTO_DRQ_EN (1 << 1)
+#define EMAC_RX_CTL_DMA_EN (1 << 2)
+#define EMAC_RX_CTL_PASS_ALL_EN (1 << 4)
+#define EMAC_RX_CTL_PASS_CTL_EN (1 << 5)
+#define EMAC_RX_CTL_PASS_CRC_ERR_EN (1 << 6)
+#define EMAC_RX_CTL_PASS_LEN_ERR_EN (1 << 7)
+#define EMAC_RX_CTL_PASS_LEN_OOR_EN (1 << 8)
+#define EMAC_RX_CTL_ACCEPT_UNICAST_EN (1 << 16)
+#define EMAC_RX_CTL_DA_FILTER_EN (1 << 17)
+#define EMAC_RX_CTL_ACCEPT_MULTICAST_EN (1 << 20)
+#define EMAC_RX_CTL_HASH_FILTER_EN (1 << 21)
+#define EMAC_RX_CTL_ACCEPT_BROADCAST_EN (1 << 22)
+#define EMAC_RX_CTL_SA_FILTER_EN (1 << 24)
+#define EMAC_RX_CTL_SA_FILTER_INVERT_EN (1 << 25)
+#define EMAC_RX_HASH0_REG (0x40)
+#define EMAC_RX_HASH1_REG (0x44)
+#define EMAC_RX_STA_REG (0x48)
+#define EMAC_RX_IO_DATA_REG (0x4c)
+#define EMAC_RX_IO_DATA_LEN(x) (x & 0xffff)
+#define EMAC_RX_IO_DATA_STATUS(x) ((x >> 16) & 0xffff)
+#define EMAC_RX_IO_DATA_STATUS_CRC_ERR (1 << 4)
+#define EMAC_RX_IO_DATA_STATUS_LEN_ERR (3 << 5)
+#define EMAC_RX_IO_DATA_STATUS_OK (1 << 7)
+#define EMAC_RX_FBC_REG (0x50)
+#define EMAC_INT_CTL_REG (0x54)
+#define EMAC_INT_STA_REG (0x58)
+#define EMAC_MAC_CTL0_REG (0x5c)
+#define EMAC_MAC_CTL0_RX_FLOW_CTL_EN (1 << 2)
+#define EMAC_MAC_CTL0_TX_FLOW_CTL_EN (1 << 3)
+#define EMAC_MAC_CTL0_SOFT_RESET (1 << 15)
+#define EMAC_MAC_CTL1_REG (0x60)
+#define EMAC_MAC_CTL1_DUPLEX_EN (1 << 0)
+#define EMAC_MAC_CTL1_LEN_CHECK_EN (1 << 1)
+#define EMAC_MAC_CTL1_HUGE_FRAME_EN (1 << 2)
+#define EMAC_MAC_CTL1_DELAYED_CRC_EN (1 << 3)
+#define EMAC_MAC_CTL1_CRC_EN (1 << 4)
+#define EMAC_MAC_CTL1_PAD_EN (1 << 5)
+#define EMAC_MAC_CTL1_PAD_CRC_EN (1 << 6)
+#define EMAC_MAC_CTL1_AD_SHORT_FRAME_EN (1 << 7)
+#define EMAC_MAC_CTL1_BACKOFF_DIS (1 << 12)
+#define EMAC_MAC_IPGT_REG (0x64)
+#define EMAC_MAC_IPGT_HALF_DUPLEX (0x12)
+#define EMAC_MAC_IPGT_FULL_DUPLEX (0x15)
+#define EMAC_MAC_IPGR_REG (0x68)
+#define EMAC_MAC_IPGR_IPG1 (0x0c)
+#define EMAC_MAC_IPGR_IPG2 (0x12)
+#define EMAC_MAC_CLRT_REG (0x6c)
+#define EMAC_MAC_CLRT_COLLISION_WINDOW (0x37)
+#define EMAC_MAC_CLRT_RM (0x0f)
+#define EMAC_MAC_MAXF_REG (0x70)
+#define EMAC_MAC_SUPP_REG (0x74)
+#define EMAC_MAC_TEST_REG (0x78)
+#define EMAC_MAC_MCFG_REG (0x7c)
+#define EMAC_MAC_MCMD_REG (0x80)
+#define EMAC_MAC_MADR_REG (0x84)
+#define EMAC_MAC_MWTD_REG (0x88)
+#define EMAC_MAC_MRDD_REG (0x8c)
+#define EMAC_MAC_MIND_REG (0x90)
+#define EMAC_MAC_SSRR_REG (0x94)
+#define EMAC_MAC_A0_REG (0x98)
+#define EMAC_MAC_A1_REG (0x9c)
+#define EMAC_MAC_A2_REG (0xa0)
+#define EMAC_SAFX_L_REG0 (0xa4)
+#define EMAC_SAFX_H_REG0 (0xa8)
+#define EMAC_SAFX_L_REG1 (0xac)
+#define EMAC_SAFX_H_REG1 (0xb0)
+#define EMAC_SAFX_L_REG2 (0xb4)
+#define EMAC_SAFX_H_REG2 (0xb8)
+#define EMAC_SAFX_L_REG3 (0xbc)
+#define EMAC_SAFX_H_REG3 (0xc0)
+
+#define EMAC_PHY_DUPLEX (1 << 8)
+
+#define WEMAC_PLATF_8BITONLY (1 << 0)
+#define WEMAC_PLATF_16BITONLY (1 << 1)
+#define WEMAC_PLATF_32BITONLY (1 << 2)
+#define WEMAC_PLATF_EXT_PHY (1 << 3)
+#define WEMAC_PLATF_NO_EEPROM (1 << 4)
+/* Use NSR to find LinkStatus */
+#define WEMAC_PLATF_SIMPLE_PHY (1 << 5)
+
+#define EMAC_EEPROM_MAGIC (0x444D394B)
+
+#endif /* _WEMAC_H_ */
--
1.7.10.4
^ permalink raw reply related
* Re: RFC crap-patch [PATCH] net: Per CPU separate frag mem accounting
From: Hannes Frederic Sowa @ 2013-03-15 20:09 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Jesper Dangaard Brouer, Eric Dumazet, netdev, yoshfuji
In-Reply-To: <1363304384.2695.42.camel@bwh-desktop.uk.solarflarecom.com>
On Thu, Mar 14, 2013 at 11:39:44PM +0000, Ben Hutchings wrote:
> On Fri, 2013-03-15 at 00:12 +0100, Hannes Frederic Sowa wrote:
> > On Thu, Mar 14, 2013 at 08:59:03PM +0000, Ben Hutchings wrote:
> > > On Thu, 2013-03-14 at 09:59 +0100, Jesper Dangaard Brouer wrote:
> > > > On Thu, 2013-03-14 at 08:25 +0100, Jesper Dangaard Brouer wrote:
> > > > > This is NOT the patch I just mentioned in the other thread, of removing
> > > > > the LRU list. This patch does real per cpu mem acct, and LRU per CPU.
> > > > >
> > > > > I get really good performance number with this patch, but I still think
> > > > > this might not be the correct solution.
> > > >
> > > > The reason is this depend on fragments entering the same HW queue, some
> > > > NICs might not put the first fragment (which have the full header
> > > > tuples) and the remaining fragments on the same queue. In which case
> > > > this patch will loose its performance gain.
> > > [...]
> > >
> > > The Microsoft RSS spec only includes port numbers in the flow hash for
> > > TCP, presumably because TCP avoids IP fragmentation whereas datagram
> > > protocols cannot. Some Linux drivers allow UDP ports to be included in
> > > the flow hash but I don't think this is the default for any of them.
> > >
> > > In Solarflare hardware the IPv4 MF bit inhibits layer 4 flow steering,
> > > so all fragments will be unsteered. I don't know whether everyone else
> > > got that right though. :-)
> >
> > Shouldn't they be steered by the IPv4 2-tuple then (if ipv4 hashing is enabled
> > on the card)?
>
> IP fragments should get a flow hash based on the 2-tuple, yes.
Thanks for clearing this up!
Hm, if we seperate the fragmentation caches per cpu perhaps it would
make sense to recalculate rxhash as soon as we know that we processed the
first fragment with more-fragments flag set and reroute it to another cpu
once (much like rps). It would burn caches but the next packets would
already arrive at the correct cpu. This would perhaps be benficial if
(like I think Jesper said) a common scenario is where packets are split in
minimum 3 fragments. I don't think there would be latency problems either
because we cannot deliver the first fragment up the stack (given no packet
reordering). So we would not have cross cpu fragment lookups anymore, but I
don't know if the overhead is worth it.
This could be done conditionally by a blacklist where we check if the nic
does generate broken udp/fragment checksums. The in-kernel flow dissector
already does handle this case correctly. We would "just" have to verify if
the network cards handle this case correctly. Heh, thats something where
the kernel could tune itself and deactivate cross fragment cache lookups
as soon as it knows that a given interface handles this case correctly. :)
But this also seems to be very complex just for handling fragments. :/
^ permalink raw reply
* Re: Trying to implement secondary loopback
From: Martitz, Thomas @ 2013-03-15 19:48 UTC (permalink / raw)
To: Benjamin LaHaise
Cc: richard -rw- weinberger, Eric W. Biederman,
netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
herbert@gondor.apana.org.au
In-Reply-To: <20130315153740.GR8869@kvack.org>
>
> ________________________________________
> Von: Benjamin LaHaise [bcrl@kvack.org]
> Gesendet: Freitag, 15. März 2013 16:37
> An: Martitz, Thomas
> Cc: richard -rw- weinberger; Eric W. Biederman; netdev@vger.kernel.org; davem@davemloft.net; edumazet@google.com; herbert@gondor.apana.org.au
> Betreff: Re: Trying to implement secondary loopback
>
> On Fri, Mar 15, 2013 at 04:07:32PM +0100, Thomas Martitz wrote:
> > Same result. I assumed the kernel treats lo in a special way for
> > localhost-connections and that it would be impossible to achieve the
> > same with a custom interface.
> >
> > I did the following:
> >
> > ifconfig lo down
> > insmod ./mykmod.ko
> > ifconfig eth2 up
> > ifconfig eth2 127.0.0.1
> >
> > At this point ifconfig prints the same information for eth2 that it had
> > printed for lo before (except for the LOOPBACK flag, but I can enable
> > that one as well by adding IFF_LOOPBACK to the interface flags in the
> > module). Yet my test application only works with lo, not eth2.
>
> Don't use loopback ip addresses; it makes no sense to do so. I've worked
> on a couple opf nic implementations on FPGAs for a while now (a gige
> implementation that works, and now a 10G nic), and it's easy enough to
> develop it as a regular ethernet driver. You can write test programs that
> use raw sockets to send/receive packets over the ethernet device, or use
> pktgen to send packets. You don't even need to configure an ip address for
> testing with raw packets. Testing with IP is a lot harder during early
> bring-up of your hardware as it requires everything to work (that is, you
> need ARP to work successfully before IP can work). Just stick to simple
> packet injection initially, and don't confuse yourself by thinking about
> the loopback device.
Thank you for your very helpful mail. I haven't considered raw sockets, but it makes total sense now you mention it. This should give a lot less hassle.
However, please let us try to clear up my (mis-)understanding. Even when I use non-looback addresses (e.g. 192.168.1.x) it does not work. For the ARP requirement I tried to workaround by using specifying the IFF_NOARP flag, and using the arp command line tool to populate the arp cache with the the MAC. With this, and all other interfaces down'ed, I cannot get transfers to work. The the sendto() (sending UDP datadagrams) call hangs while the ndk_start_xmit() method isn't even called. As works fine with the loopback interface I started to believe that I need to implement a real loopback interface. It is this supposed to work this way isn't it?
Best regards.
-----
visit us at
OFC 2013 / March 19-21 / Anaheim Convention Center, CA, USA / booth 11807
NABSHOW 2013 / April 8-11 / Las Vegas Convention Center, Nevada, USA / booth C7843
www.hhi.fraunhofer.de/events
^ permalink raw reply
* Re: atl1c issues on 3.8.2
From: Michael Büsch @ 2013-03-15 19:44 UTC (permalink / raw)
To: Eric Dumazet
Cc: Pavel Emelyanov, Eric Dumazet, linux-netdev, David S.Miller,
Mel Gorman
In-Reply-To: <1363302362.29475.42.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 978 bytes --]
On Fri, 15 Mar 2013 00:06:02 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> You could try various DEBUGing stuff, like CONFIG_DEBUG_PAGEALLOC and
> CONFIG_SLUB_DEBUG_ON
This bug is so weird, so I did some double-checking.
Just to minimize the mistakes on my side.
I compiled a kernel without the revert of the original commit
and without the skb fix you suggested.
It turns out that I am only able to reproduce the issue, if the ath9k interface is
up while testing the atl1c ethernet.
And I also double-checked that reverting the original commit fixes the issue.
No stalls with up or down ath9k then.
So that confirms my previous results.
I tried to enable pagealloc debug and slub debug on a kernel with the suggested skb
fix, but without the revert of the commit. Nothing special appeared
in the logs. I'm currently building a kernel with almost all debugging options
turned on. I will test that tomorrow.
Thanks for your help.
--
Michael
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Trying to implement secondary loopback
From: Ben Hutchings @ 2013-03-15 18:36 UTC (permalink / raw)
To: Thomas Martitz
Cc: Eric W. Biederman, richard -rw- weinberger,
netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
herbert@gondor.apana.org.au
In-Reply-To: <5142CE23.9070804@hhi.fraunhofer.de>
On Fri, 2013-03-15 at 08:30 +0100, Thomas Martitz wrote:
> Am 13.03.2013 22:21, schrieb Eric W. Biederman:
> > "Martitz, Thomas" <thomas.martitz@hhi.fraunhofer.de> writes:
> >
> >>> Von: Eric W. Biederman [ebiederm@xmission.com]
> >>>
> >>> The easy solution is to setup two network namespaces and two nics.
> >>> And transmit data from one network namespace to another, through your
> >>> nics.
> >
> >>
> >> That sounds a lot more involed than using loopback to send data back
> >> to the same process. And I guess just calling netif_rx() in the xmit()
> >> function wouldn't be sufficient either? Also I wouldn't know how to do
> >> that as I'm not yet very familiar with network namespaces (but that
> >> can clearly get fixed).
> >
> > It may sound involved but it is just a few lines of code to set up.
> >
> > ip netns add ns1
> > ip netns add ns2
> > ip link set nic1 netns ns1
> > ip link set nic2 netns ns2
> >
> > int main(int argc, char **argv)
> > {
> > int netfd1, netfd2;
> > int sk1, sk2;
> > netfd1 = open(/var/run/netns/nic1);
> > netfd2 = open(/var/run/netns/nic2);
> >
> > setns(netfd1, 0);
> > sk1 = socket(...);
> >
> > setns(netfd2, 0);
> > sk2 = socket(...);
> >
> > /* test test test */
> > }
> >
> > And what is partidcularly interesting is that all of this works with
> > your drivers normal code paths without any kernel hacks.
> >
> > Eric
> >
>
>
> I have trouble understanding this approach. Does it mean that I have to
> expose two interfaces from my kernel module. I.e. call register_netdev()
> twice?
[...]
Perhaps you can use macvlan for this. Create one net device in your
driver, then use macvlan to stack two net devices on top of it using
different MAC addresses. I think you'll need to configure them in VEPA
mode so that macvlan doesn't bridge them.
As an alternative to network namespaces, you might find it easier to
assign one or both net devices to virtual machines. virt-manager and
virsh can set up KVM virtual machines using macvlan/macvtap interfaces.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* [PATCH] net: dns_resolver: Use kmemdup instead of kmalloc and memcpy
From: Alexandru Gheorghiu @ 2013-03-15 18:21 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kernel, Alexandru Gheorghiu
Replace use of kmalloc followed by memcpy with kmemdup.
Patch found using coccinelle.
Signed-off-by: Alexandru Gheorghiu <gheorghiuandru@gmail.com>
---
net/dns_resolver/dns_query.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c
index c32be29..4ac62fb 100644
--- a/net/dns_resolver/dns_query.c
+++ b/net/dns_resolver/dns_query.c
@@ -146,11 +146,10 @@ int dns_query(const char *type, const char *name, size_t namelen,
len = upayload->datalen;
ret = -ENOMEM;
- *_result = kmalloc(len + 1, GFP_KERNEL);
+ *_result = kmemdup(upayload->data, len + 1, GFP_KERNEL);
if (!*_result)
goto put;
- memcpy(*_result, upayload->data, len + 1);
if (_expiry)
*_expiry = rkey->expiry;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 3/4 v2] net: mvmdio: enhance driver to support SMI error/done interrupts
From: Russell King - ARM Linux @ 2013-03-15 18:05 UTC (permalink / raw)
To: Florian Fainelli
Cc: davem, Grant Likely, Rob Herring, Rob Landley, Jason Cooper,
Andrew Lunn, Benjamin Herrenschmidt, Paul Mackerras,
Lennert Buytenhek, Thomas Petazzoni, Greg Kroah-Hartman,
devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
linuxppc-dev, netdev
In-Reply-To: <1363284515-9865-4-git-send-email-florian@openwrt.org>
On Thu, Mar 14, 2013 at 07:08:34PM +0100, Florian Fainelli wrote:
> + if (dev->err_interrupt == NO_IRQ) {
...
> + init_waitqueue_head(&dev->smi_busy_wait);
> +
> + dev->err_interrupt = platform_get_irq(pdev, 0);
> + if (dev->err_interrupt != -ENXIO) {
...
> + } else
> + dev->err_interrupt = NO_IRQ;
FYI, NO_IRQ is not supposed to be used anymore (we're supposed to be
removing it). platform_get_irq() returns negative numbers for failure,
so why not test for < 0 in both the above tests, or maybe <= 0 (as
IRQ0 is also not supposed to be valid.)?
^ permalink raw reply
* [PATCH][v3.2.y] xen-netfront: delay gARP until backend switches to Connected
From: Joseph Salisbury @ 2013-03-15 17:56 UTC (permalink / raw)
To: Ben Hutchings
Cc: konrad.wilk, jeremy, xen-devel, virtualization, netdev, stable
Hello,
Please consider including upstream commit
08e34eb14fe4cfd934b5c169a7682a969457c4ea in the next v3.2.y release.
It was included upstream as of v3.3-rc1. It has been tested and
confirmed to resolve http://bugs.launchpad.net/bugs/1154608 .
commit 08e34eb14fe4cfd934b5c169a7682a969457c4ea
Author: Laszlo Ersek <lersek@redhat.com>
Date: Sun Dec 11 01:48:59 2011 +0000
xen-netfront: delay gARP until backend switches to Connected
Sincerely,
Joseph Salisbury
^ permalink raw reply
* [PATCH net-next 5/5] openvswitch: Allow OVS_USERSPACE_ATTR_USERDATA to be variable length.
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, dev, Ben Pfaff, Romain Lenglet, Jesse Gross
In-Reply-To: <1363369131-16830-1-git-send-email-jesse@nicira.com>
From: Ben Pfaff <blp@nicira.com>
Until now, the optional OVS_USERSPACE_ATTR_USERDATA attribute had to be
exactly 64 bits long, if it was present. However, 64 bits is not enough
space to associate as much information with a flow as would be convenient
for some userspace features now under development. This commit generalizes
the attribute, allowing it to be any length.
This generalization is backward-compatible: if userspace only uses 64-bit
attributes, then it will not see any change in behavior.
CC: Romain Lenglet <rlenglet@vmware.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
include/linux/openvswitch.h | 11 ++++++-----
net/openvswitch/datapath.c | 11 ++++++-----
net/openvswitch/datapath.h | 2 +-
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index 99e6414..67d6c7b 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -127,7 +127,8 @@ enum ovs_packet_cmd {
* for %OVS_PACKET_CMD_EXECUTE. It has nested %OVS_ACTION_ATTR_* attributes.
* @OVS_PACKET_ATTR_USERDATA: Present for an %OVS_PACKET_CMD_ACTION
* notification if the %OVS_ACTION_ATTR_USERSPACE action specified an
- * %OVS_USERSPACE_ATTR_USERDATA attribute.
+ * %OVS_USERSPACE_ATTR_USERDATA attribute, with the same length and content
+ * specified there.
*
* These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_PACKET_* commands.
@@ -137,7 +138,7 @@ enum ovs_packet_attr {
OVS_PACKET_ATTR_PACKET, /* Packet data. */
OVS_PACKET_ATTR_KEY, /* Nested OVS_KEY_ATTR_* attributes. */
OVS_PACKET_ATTR_ACTIONS, /* Nested OVS_ACTION_ATTR_* attributes. */
- OVS_PACKET_ATTR_USERDATA, /* u64 OVS_ACTION_ATTR_USERSPACE arg. */
+ OVS_PACKET_ATTR_USERDATA, /* OVS_ACTION_ATTR_USERSPACE arg. */
__OVS_PACKET_ATTR_MAX
};
@@ -389,13 +390,13 @@ enum ovs_sample_attr {
* enum ovs_userspace_attr - Attributes for %OVS_ACTION_ATTR_USERSPACE action.
* @OVS_USERSPACE_ATTR_PID: u32 Netlink PID to which the %OVS_PACKET_CMD_ACTION
* message should be sent. Required.
- * @OVS_USERSPACE_ATTR_USERDATA: If present, its u64 argument is copied to the
- * %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA,
+ * @OVS_USERSPACE_ATTR_USERDATA: If present, its variable-length argument is
+ * copied to the %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA.
*/
enum ovs_userspace_attr {
OVS_USERSPACE_ATTR_UNSPEC,
OVS_USERSPACE_ATTR_PID, /* u32 Netlink PID to receive upcalls. */
- OVS_USERSPACE_ATTR_USERDATA, /* u64 optional user-specified cookie. */
+ OVS_USERSPACE_ATTR_USERDATA, /* Optional user-specified cookie. */
__OVS_USERSPACE_ATTR_MAX
};
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f9d2438..96cd5b2 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -370,8 +370,8 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
len = sizeof(struct ovs_header);
len += nla_total_size(skb->len);
len += nla_total_size(FLOW_BUFSIZE);
- if (upcall_info->cmd == OVS_PACKET_CMD_ACTION)
- len += nla_total_size(8);
+ if (upcall_info->userdata)
+ len += NLA_ALIGN(upcall_info->userdata->nla_len);
user_skb = genlmsg_new(len, GFP_ATOMIC);
if (!user_skb) {
@@ -388,8 +388,9 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
nla_nest_end(user_skb, nla);
if (upcall_info->userdata)
- nla_put_u64(user_skb, OVS_PACKET_ATTR_USERDATA,
- nla_get_u64(upcall_info->userdata));
+ __nla_put(user_skb, OVS_PACKET_ATTR_USERDATA,
+ nla_len(upcall_info->userdata),
+ nla_data(upcall_info->userdata));
nla = __nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, skb->len);
@@ -544,7 +545,7 @@ static int validate_userspace(const struct nlattr *attr)
{
static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
[OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
- [OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_U64 },
+ [OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
};
struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
int error;
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 031dfbf..9125ad5 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -119,7 +119,7 @@ struct ovs_skb_cb {
* struct dp_upcall - metadata to include with a packet to send to userspace
* @cmd: One of %OVS_PACKET_CMD_*.
* @key: Becomes %OVS_PACKET_ATTR_KEY. Must be nonnull.
- * @userdata: If nonnull, its u64 value is extracted and passed to userspace as
+ * @userdata: If nonnull, its variable-length value is passed to userspace as
* %OVS_PACKET_ATTR_USERDATA.
* @pid: Netlink PID to which packet should be sent. If @pid is 0 then no
* packet is sent and the packet is accounted in the datapath's @n_lost
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 3/5] linux/openvswitch.h: Make OVSP_LOCAL 32-bit.
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, dev, Jarno Rajahalme, Jesse Gross
In-Reply-To: <1363369131-16830-1-git-send-email-jesse@nicira.com>
From: Jarno Rajahalme <jarno.rajahalme@nsn.com>
OVS ports are now 32-bit, so OVSP_LOCAL should be too.
(Internally, kernel module still keeps port numbers 16-bit, though.)
Signed-off-by: Jarno Rajahalme <jarno.rajahalme@nsn.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
include/linux/openvswitch.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index d42e174..99e6414 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -94,7 +94,7 @@ struct ovs_vport_stats {
};
/* Fixed logical ports. */
-#define OVSP_LOCAL ((__u16)0)
+#define OVSP_LOCAL ((__u32)0)
/* Packet transfer. */
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 2/5] openvswitch: Avoid useless holes in struct vport
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, dev, Thomas Graf, Jesse Gross
In-Reply-To: <1363369131-16830-1-git-send-email-jesse@nicira.com>
From: Thomas Graf <tgraf@suug.ch>
Having the 16bit port_no in between a set of pointers creates
an unwanted and useless hole in the struct.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/openvswitch/vport.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 3f7961e..aee7d43 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -68,10 +68,10 @@ struct vport_err_stats {
/**
* struct vport - one port within a datapath
* @rcu: RCU callback head for deferred destruction.
- * @port_no: Index into @dp's @ports array.
* @dp: Datapath to which this port belongs.
* @upcall_portid: The Netlink port to use for packets received on this port that
* miss the flow table.
+ * @port_no: Index into @dp's @ports array.
* @hash_node: Element in @dev_table hash table in vport.c.
* @dp_hash_node: Element in @datapath->ports hash table in datapath.c.
* @ops: Class structure.
@@ -81,9 +81,9 @@ struct vport_err_stats {
*/
struct vport {
struct rcu_head rcu;
- u16 port_no;
struct datapath *dp;
u32 upcall_portid;
+ u16 port_no;
struct hlist_node hash_node;
struct hlist_node dp_hash_node;
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 1/5] openvswitch: Use eth_mac_addr() instead of duplicating it
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, dev, Thomas Graf, Jesse Gross
In-Reply-To: <1363369131-16830-1-git-send-email-jesse@nicira.com>
From: Thomas Graf <tgraf@redhat.com>
bonus: if we ever are to use IFF_LIVE_ADDR_CHANGE for
anything further than to check availability in eth_mac_addr(),
Open vSwitch will be ready for that.
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/openvswitch/vport-internal_dev.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 5d460c3..90816c7 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -63,17 +63,6 @@ static struct rtnl_link_stats64 *internal_dev_get_stats(struct net_device *netde
return stats;
}
-static int internal_dev_mac_addr(struct net_device *dev, void *p)
-{
- struct sockaddr *addr = p;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
- dev->addr_assign_type &= ~NET_ADDR_RANDOM;
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- return 0;
-}
-
/* Called with rcu_read_lock_bh. */
static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
{
@@ -127,7 +116,7 @@ static const struct net_device_ops internal_dev_netdev_ops = {
.ndo_open = internal_dev_open,
.ndo_stop = internal_dev_stop,
.ndo_start_xmit = internal_dev_xmit,
- .ndo_set_mac_address = internal_dev_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = internal_dev_change_mtu,
.ndo_get_stats64 = internal_dev_get_stats,
};
@@ -139,6 +128,7 @@ static void do_setup(struct net_device *netdev)
netdev->netdev_ops = &internal_dev_netdev_ops;
netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
netdev->destructor = internal_dev_destructor;
SET_ETHTOOL_OPS(netdev, &internal_dev_ethtool_ops);
netdev->tx_queue_len = 0;
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 4/5] openvswitch: Change ENOENT return value to ENODEV in lookup_vport().
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1363369131-16830-1-git-send-email-jesse-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
From: Jarno Rajahalme <jarno.rajahalme-OYasijW0DpE@public.gmane.org>
This reduces the number of valid "no such device" error values that
need special attention by the caller.
Userspace code will need to keep on checking for both ENODEV and
ENOENT as long as older kernel modules are around.
Signed-off-by: Jarno Rajahalme <jarno.rajahalme-OYasijW0DpE@public.gmane.org>
Signed-off-by: Jesse Gross <jesse-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
---
net/openvswitch/datapath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f996db3..f9d2438 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1628,7 +1628,7 @@ static struct vport *lookup_vport(struct net *net,
vport = ovs_vport_rtnl_rcu(dp, port_no);
if (!vport)
- return ERR_PTR(-ENOENT);
+ return ERR_PTR(-ENODEV);
return vport;
} else
return ERR_PTR(-EINVAL);
--
1.7.10.4
^ permalink raw reply related
* [GIT net-next] Open vSwitch
From: Jesse Gross @ 2013-03-15 17:38 UTC (permalink / raw)
To: David Miller; +Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA
A couple of minor enhancements for net-next/3.10. The largest is an
extension to allow variable length metadata to be passed to userspace
with packets.
There is a merge conflict in net/openvswitch/vport-internal_dev.c:
A existing commit modifies internal_dev_mac_addr() and a new commit
deletes it. The new one is correct, so you can just remove that function.
The following changes since commit a5a81f0b9025867efb999d14a8dfc1907c5a4c3b:
ipv6: Fix default route failover when CONFIG_IPV6_ROUTER_PREF=n (2012-12-03 15:34:47 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch.git master
for you to fetch changes up to 4490108b4a5ada14c7be712260829faecc814ae5:
openvswitch: Allow OVS_USERSPACE_ATTR_USERDATA to be variable length. (2013-02-22 16:29:22 -0800)
----------------------------------------------------------------
Ben Pfaff (1):
openvswitch: Allow OVS_USERSPACE_ATTR_USERDATA to be variable length.
Jarno Rajahalme (2):
linux/openvswitch.h: Make OVSP_LOCAL 32-bit.
openvswitch: Change ENOENT return value to ENODEV in lookup_vport().
Thomas Graf (2):
openvswitch: Use eth_mac_addr() instead of duplicating it
openvswitch: Avoid useless holes in struct vport
include/linux/openvswitch.h | 13 +++++++------
net/openvswitch/datapath.c | 13 +++++++------
net/openvswitch/datapath.h | 2 +-
net/openvswitch/vport-internal_dev.c | 14 ++------------
net/openvswitch/vport.h | 4 ++--
5 files changed, 19 insertions(+), 27 deletions(-)
^ permalink raw reply
* [PATCH net-next] drivers:net: dma_alloc_coherent: use __GFP_ZERO instead of memset(, 0)
From: Joe Perches @ 2013-03-15 17:23 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, e1000-devel, linux-wireless, b43-dev, users
Reduce the number of calls required to alloc
a zeroed block of memory.
Trivially reduces overall object size.
Other changes around these removals
o Neaten call argument alignment
o Remove an unnecessary OOM message after dma_alloc_coherent failure
o Remove unnecessary gfp_t stack variable
Signed-off-by: Joe Perches <joe@perches.com>
---
drivers/net/ethernet/aeroflex/greth.c | 8 ++------
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 8 ++++----
drivers/net/ethernet/broadcom/bnx2.c | 5 ++---
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 9 +++------
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 14 ++++++-------
drivers/net/ethernet/broadcom/tg3.c | 11 +++--------
drivers/net/ethernet/brocade/bna/bnad.c | 5 ++---
drivers/net/ethernet/emulex/benet/be_main.c | 14 ++++++-------
drivers/net/ethernet/faraday/ftgmac100.c | 5 ++---
drivers/net/ethernet/faraday/ftmac100.c | 8 ++++----
drivers/net/ethernet/ibm/emac/mal.c | 3 +--
drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 6 ++----
drivers/net/ethernet/intel/igbvf/netdev.c | 2 --
drivers/net/ethernet/intel/ixgb/ixgb_main.c | 3 +--
drivers/net/ethernet/marvell/pxa168_eth.c | 16 ++++++++-------
drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 3 +--
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 11 +++++------
drivers/net/ethernet/pasemi/pasemi_mac.c | 5 ++---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 23 ++++++++--------------
drivers/net/ethernet/sfc/nic.c | 4 ++--
drivers/net/ethernet/sgi/meth.c | 5 +++--
drivers/net/ethernet/toshiba/spider_net.c | 3 +--
drivers/net/ethernet/tundra/tsi108_eth.c | 15 +++++---------
drivers/net/ethernet/xilinx/ll_temac_main.c | 6 ++----
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++----
drivers/net/fddi/defxx.c | 3 +--
drivers/net/irda/ali-ircc.c | 6 ++----
drivers/net/irda/nsc-ircc.c | 6 ++----
drivers/net/irda/pxaficp_ir.c | 4 ++--
drivers/net/irda/smsc-ircc2.c | 7 ++-----
drivers/net/irda/via-ircc.c | 6 ++----
drivers/net/irda/w83977af_ir.c | 7 ++-----
drivers/net/wireless/b43/dma.c | 9 ++-------
drivers/net/wireless/b43legacy/dma.c | 3 +--
drivers/net/wireless/iwlegacy/4965-mac.c | 4 ++--
drivers/net/wireless/iwlegacy/common.c | 10 ++++------
drivers/net/wireless/iwlegacy/common.h | 5 ++---
drivers/net/wireless/rt2x00/rt2x00pci.c | 4 +---
38 files changed, 104 insertions(+), 168 deletions(-)
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 3a9fbac..2692954 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1466,25 +1466,21 @@ static int greth_of_probe(struct platform_device *ofdev)
/* Allocate TX descriptor ring in coherent memory */
greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024,
&greth->tx_bd_base_phys,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!greth->tx_bd_base) {
err = -ENOMEM;
goto error3;
}
- memset(greth->tx_bd_base, 0, 1024);
-
/* Allocate RX descriptor ring in coherent memory */
greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024,
&greth->rx_bd_base_phys,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!greth->rx_bd_base) {
err = -ENOMEM;
goto error4;
}
- memset(greth->rx_bd_base, 0, 1024);
-
/* Get MAC address from: module param, OF property or ID prom */
for (i = 0; i < 6; i++) {
if (macaddr[i] != 0)
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 79cf620..0b3e23e 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -862,25 +862,25 @@ static int bcm_enet_open(struct net_device *dev)
/* allocate rx dma ring */
size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!p) {
ret = -ENOMEM;
goto out_freeirq_tx;
}
- memset(p, 0, size);
priv->rx_desc_alloc_size = size;
priv->rx_desc_cpu = p;
/* allocate tx dma ring */
size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
- p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+ p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!p) {
ret = -ENOMEM;
goto out_free_rx_ring;
}
- memset(p, 0, size);
priv->tx_desc_alloc_size = size;
priv->tx_desc_cpu = p;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 2f0ba8f..e709296 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -854,12 +854,11 @@ bnx2_alloc_mem(struct bnx2 *bp)
sizeof(struct statistics_block);
status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
- &bp->status_blk_mapping, GFP_KERNEL);
+ &bp->status_blk_mapping,
+ GFP_KERNEL | __GFP_ZERO);
if (status_blk == NULL)
goto alloc_mem_err;
- memset(status_blk, 0, bp->status_stats_size);
-
bnapi = &bp->bnx2_napi[0];
bnapi->status_blk.msi = status_blk;
bnapi->hw_tx_cons_ptr =
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index f865ad5..9e8d195 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1946,12 +1946,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
bool is_pf);
-#define BNX2X_ILT_ZALLOC(x, y, size) \
- do { \
- x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
- if (x) \
- memset(x, 0, size); \
- } while (0)
+#define BNX2X_ILT_ZALLOC(x, y, size) \
+ x = dma_alloc_coherent(&bp->pdev->dev, size, y, \
+ GFP_KERNEL | __GFP_ZERO)
#define BNX2X_ILT_FREE(x, y, size) \
do { \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 4620fa5..8f96372 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -50,13 +50,13 @@ extern int int_mode;
} \
} while (0)
-#define BNX2X_PCI_ALLOC(x, y, size) \
- do { \
- x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
- if (x == NULL) \
- goto alloc_mem_err; \
- memset((void *)x, 0, size); \
- } while (0)
+#define BNX2X_PCI_ALLOC(x, y, size) \
+do { \
+ x = dma_alloc_coherent(&bp->pdev->dev, size, y, \
+ GFP_KERNEL | __GFP_ZERO); \
+ if (x == NULL) \
+ goto alloc_mem_err; \
+} while (0)
#define BNX2X_ALLOC(x, size) \
do { \
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 0c1a2ef..7794883 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8172,11 +8172,9 @@ static int tg3_mem_rx_acquire(struct tg3 *tp)
tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
TG3_RX_RCB_RING_BYTES(tp),
&tnapi->rx_rcb_mapping,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!tnapi->rx_rcb)
goto err_out;
-
- memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
}
return 0;
@@ -8226,12 +8224,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
sizeof(struct tg3_hw_stats),
&tp->stats_mapping,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!tp->hw_stats)
goto err_out;
- memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
-
for (i = 0; i < tp->irq_cnt; i++) {
struct tg3_napi *tnapi = &tp->napi[i];
struct tg3_hw_status *sblk;
@@ -8239,11 +8235,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
TG3_HW_STATUS_SIZE,
&tnapi->status_mapping,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!tnapi->hw_status)
goto err_out;
- memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
sblk = tnapi->hw_status;
if (tg3_flag(tp, ENABLE_RSS)) {
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 7cce42d..d588f84 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -1264,9 +1264,8 @@ bnad_mem_alloc(struct bnad *bnad,
mem_info->mdl[i].len = mem_info->len;
mem_info->mdl[i].kva =
dma_alloc_coherent(&bnad->pcidev->dev,
- mem_info->len, &dma_pa,
- GFP_KERNEL);
-
+ mem_info->len, &dma_pa,
+ GFP_KERNEL);
if (mem_info->mdl[i].kva == NULL)
goto err_return;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 2dfa205..536afa2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -146,10 +146,9 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
q->entry_size = entry_size;
mem->size = len * entry_size;
mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!mem->va)
return -ENOMEM;
- memset(mem->va, 0, mem->size);
return 0;
}
@@ -2569,10 +2568,9 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (cmd.va == NULL)
return -1;
- memset(cmd.va, 0, cmd.size);
if (enable) {
status = pci_write_config_dword(adapter->pdev,
@@ -3794,12 +3792,13 @@ static int be_ctrl_init(struct be_adapter *adapter)
rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
rx_filter->va = dma_alloc_coherent(&adapter->pdev->dev, rx_filter->size,
- &rx_filter->dma, GFP_KERNEL);
+ &rx_filter->dma,
+ GFP_KERNEL | __GFP_ZERO);
if (rx_filter->va == NULL) {
status = -ENOMEM;
goto free_mbox;
}
- memset(rx_filter->va, 0, rx_filter->size);
+
mutex_init(&adapter->mbox_lock);
spin_lock_init(&adapter->mcc_lock);
spin_lock_init(&adapter->mcc_cq_lock);
@@ -3841,10 +3840,9 @@ static int be_stats_init(struct be_adapter *adapter)
cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (cmd->va == NULL)
return -1;
- memset(cmd->va, 0, cmd->size);
return 0;
}
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 7c361d1..0e817e6 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -780,12 +780,11 @@ static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
priv->descs = dma_alloc_coherent(priv->dev,
sizeof(struct ftgmac100_descs),
- &priv->descs_dma_addr, GFP_KERNEL);
+ &priv->descs_dma_addr,
+ GFP_KERNEL | __GFP_ZERO);
if (!priv->descs)
return -ENOMEM;
- memset(priv->descs, 0, sizeof(struct ftgmac100_descs));
-
/* initialize RX ring */
ftgmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index b5ea8fb..a6eda8d 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -732,13 +732,13 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv)
{
int i;
- priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
- &priv->descs_dma_addr, GFP_KERNEL);
+ priv->descs = dma_alloc_coherent(priv->dev,
+ sizeof(struct ftmac100_descs),
+ &priv->descs_dma_addr,
+ GFP_KERNEL | __GFP_ZERO);
if (!priv->descs)
return -ENOMEM;
- memset(priv->descs, 0, sizeof(struct ftmac100_descs));
-
/* initialize RX ring */
ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index cc2db5c..610ed223 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -638,12 +638,11 @@ static int mal_probe(struct platform_device *ofdev)
(NUM_TX_BUFF * mal->num_tx_chans +
NUM_RX_BUFF * mal->num_rx_chans);
mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (mal->bd_virt == NULL) {
err = -ENOMEM;
goto fail_unmap;
}
- memset(mal->bd_virt, 0, bd_size);
for (i = 0; i < mal->num_tx_chans; ++i)
set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 43462d5..a9f9c79 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1020,12 +1020,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
txdr->size = ALIGN(txdr->size, 4096);
txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!txdr->desc) {
ret_val = 2;
goto err_nomem;
}
- memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = txdr->next_to_clean = 0;
ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
@@ -1075,12 +1074,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!rxdr->desc) {
ret_val = 5;
goto err_nomem;
}
- memset(rxdr->desc, 0, rxdr->size);
rxdr->next_to_use = rxdr->next_to_clean = 0;
rctl = er32(RCTL);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index d60cd43..bea46bb 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -447,7 +447,6 @@ int igbvf_setup_tx_resources(struct igbvf_adapter *adapter,
tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
&tx_ring->dma, GFP_KERNEL);
-
if (!tx_ring->desc)
goto err;
@@ -488,7 +487,6 @@ int igbvf_setup_rx_resources(struct igbvf_adapter *adapter,
rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
&rx_ring->dma, GFP_KERNEL);
-
if (!rx_ring->desc)
goto err;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index e23f023..74464c3 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -717,12 +717,11 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
txdr->size = ALIGN(txdr->size, 4096);
txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!txdr->desc) {
vfree(txdr->buffer_info);
return -ENOMEM;
}
- memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = 0;
txdr->next_to_clean = 0;
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 3ae4c7f..339bb32 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -584,12 +584,14 @@ static int init_hash_table(struct pxa168_eth_private *pep)
*/
if (pep->htpr == NULL) {
pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
- HASH_ADDR_TABLE_SIZE,
- &pep->htpr_dma, GFP_KERNEL);
+ HASH_ADDR_TABLE_SIZE,
+ &pep->htpr_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (pep->htpr == NULL)
return -ENOMEM;
+ } else {
+ memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
}
- memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
wrl(pep, HTPR, pep->htpr_dma);
return 0;
}
@@ -1023,11 +1025,11 @@ static int rxq_init(struct net_device *dev)
size = pep->rx_ring_size * sizeof(struct rx_desc);
pep->rx_desc_area_size = size;
pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
- &pep->rx_desc_dma, GFP_KERNEL);
+ &pep->rx_desc_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!pep->p_rx_desc_area)
goto out;
- memset((void *)pep->p_rx_desc_area, 0, size);
/* initialize the next_desc_ptr links in the Rx descriptors ring */
p_rx_desc = pep->p_rx_desc_area;
for (i = 0; i < rx_desc_num; i++) {
@@ -1084,10 +1086,10 @@ static int txq_init(struct net_device *dev)
size = pep->tx_ring_size * sizeof(struct tx_desc);
pep->tx_desc_area_size = size;
pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
- &pep->tx_desc_dma, GFP_KERNEL);
+ &pep->tx_desc_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!pep->p_tx_desc_area)
goto out;
- memset((void *)pep->p_tx_desc_area, 0, pep->tx_desc_area_size);
/* Initialize the next_desc_ptr links in the Tx descriptors ring */
p_tx_desc = pep->p_tx_desc_area;
for (i = 0; i < tx_desc_num; i++) {
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 4f9937e..d5ffdc8 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3592,10 +3592,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
&ss->rx_done.bus,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (ss->rx_done.entry == NULL)
goto abort;
- memset(ss->rx_done.entry, 0, bytes);
bytes = sizeof(*ss->fw_stats);
ss->fw_stats = dma_alloc_coherent(&pdev->dev, bytes,
&ss->fw_stats_bus,
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 4bdca9e..abd5fba 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1470,11 +1470,10 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY;
rx_ring->rx_buff_pool = dma_alloc_coherent(&pdev->dev, size,
&rx_ring->rx_buff_pool_logic,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!rx_ring->rx_buff_pool)
return -ENOMEM;
- memset(rx_ring->rx_buff_pool, 0, size);
rx_ring->rx_buff_pool_size = size;
for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
@@ -1773,12 +1772,12 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
- &tx_ring->dma, GFP_KERNEL);
+ &tx_ring->dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!tx_ring->desc) {
vfree(tx_ring->buffer_info);
return -ENOMEM;
}
- memset(tx_ring->desc, 0, tx_ring->size);
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
@@ -1818,12 +1817,12 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
- &rx_ring->dma, GFP_KERNEL);
+ &rx_ring->dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!rx_ring->desc) {
vfree(rx_ring->buffer_info);
return -ENOMEM;
}
- memset(rx_ring->desc, 0, rx_ring->size);
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
for (desNo = 0; desNo < rx_ring->count; desNo++) {
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index b1cfbb7..a5f0b5d 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -441,12 +441,11 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
RX_RING_SIZE * sizeof(u64),
- &ring->buf_dma, GFP_KERNEL);
+ &ring->buf_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!ring->buffers)
goto out_ring_desc;
- memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64));
-
write_dma_reg(PAS_DMA_RXCHAN_BASEL(chno),
PAS_DMA_RXCHAN_BASEL_BRBL(ring->chan.ring_dma));
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index a0649ec..2d9c23f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -422,22 +422,20 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
- &rq_phys_addr, GFP_KERNEL);
+ &rq_phys_addr, GFP_KERNEL | __GFP_ZERO);
if (!rq_addr)
return -ENOMEM;
rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
- &rsp_phys_addr, GFP_KERNEL);
+ &rsp_phys_addr, GFP_KERNEL | __GFP_ZERO);
if (!rsp_addr) {
err = -ENOMEM;
goto out_free_rq;
}
- memset(rq_addr, 0, rq_size);
prq = rq_addr;
- memset(rsp_addr, 0, rsp_size);
prsp = rsp_addr;
prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -744,10 +742,9 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
size_t nic_size = sizeof(struct qlcnic_info_le);
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
+ &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
if (!nic_info_addr)
return -ENOMEM;
- memset(nic_info_addr, 0, nic_size);
nic_info = nic_info_addr;
@@ -795,11 +792,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
return err;
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
+ &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
if (!nic_info_addr)
return -ENOMEM;
- memset(nic_info_addr, 0, nic_size);
nic_info = nic_info_addr;
nic_info->pci_func = cpu_to_le16(nic->pci_func);
@@ -845,10 +841,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
- &pci_info_dma_t, GFP_KERNEL);
+ &pci_info_dma_t,
+ GFP_KERNEL | __GFP_ZERO);
if (!pci_info_addr)
return -ENOMEM;
- memset(pci_info_addr, 0, pci_size);
npar = pci_info_addr;
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
@@ -940,12 +936,10 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
}
stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
+ &stats_dma_t, GFP_KERNEL | __GFP_ZERO);
if (!stats_addr)
return -ENOMEM;
- memset(stats_addr, 0, stats_size);
-
arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
arg1 |= rx_tx << 15 | stats_size << 16;
@@ -993,11 +987,10 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
return -ENOMEM;
stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
+ &stats_dma_t, GFP_KERNEL | __GFP_ZERO);
if (!stats_addr)
return -ENOMEM;
- memset(stats_addr, 0, stats_size);
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
cmd.req.arg[1] = stats_size << 16;
cmd.req.arg[2] = MSD(stats_dma_t);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index f9f5df8..7b87798 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -305,11 +305,11 @@ int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
unsigned int len)
{
buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
- &buffer->dma_addr, GFP_ATOMIC);
+ &buffer->dma_addr,
+ GFP_ATOMIC | __GFP_ZERO);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
- memset(buffer->addr, 0, len);
return 0;
}
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index 79ad9c9..4bdbaad9 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -213,10 +213,11 @@ static int meth_init_tx_ring(struct meth_private *priv)
{
/* Init TX ring */
priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE,
- &priv->tx_ring_dma, GFP_ATOMIC);
+ &priv->tx_ring_dma,
+ GFP_ATOMIC | __GFP_ZERO);
if (!priv->tx_ring)
return -ENOMEM;
- memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
+
priv->tx_count = priv->tx_read = priv->tx_write = 0;
mace->eth.tx_ring_base = priv->tx_ring_dma;
/* Now init skb save area */
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index f1b91fd..fef6b59 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -352,8 +352,7 @@ spider_net_init_chain(struct spider_net_card *card,
alloc_size = chain->num_desc * sizeof(struct spider_net_hw_descr);
chain->hwring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
- &chain->dma_addr, GFP_KERNEL);
-
+ &chain->dma_addr, GFP_KERNEL);
if (!chain->hwring)
return -ENOMEM;
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 99fe3c6..3c69a04 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1308,21 +1308,16 @@ static int tsi108_open(struct net_device *dev)
data->id, dev->irq, dev->name);
}
- data->rxring = dma_alloc_coherent(NULL, rxring_size,
- &data->rxdma, GFP_KERNEL);
- if (!data->rxring) {
+ data->rxring = dma_alloc_coherent(NULL, rxring_size, &data->rxdma,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!data->rxring)
return -ENOMEM;
- } else {
- memset(data->rxring, 0, rxring_size);
- }
- data->txring = dma_alloc_coherent(NULL, txring_size,
- &data->txdma, GFP_KERNEL);
+ data->txring = dma_alloc_coherent(NULL, txring_size, &data->txdma,
+ GFP_KERNEL | __GFP_ZERO);
if (!data->txring) {
pci_free_consistent(0, rxring_size, data->rxring, data->rxdma);
return -ENOMEM;
- } else {
- memset(data->txring, 0, txring_size);
}
for (i = 0; i < TSI108_RXRING_LEN; i++) {
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index a64a6d7..4a7c60f 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -245,23 +245,21 @@ static int temac_dma_bd_init(struct net_device *ndev)
/* returns a virtual address and a physical address. */
lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- &lp->tx_bd_p, GFP_KERNEL);
+ &lp->tx_bd_p, GFP_KERNEL | __GFP_ZERO);
if (!lp->tx_bd_v)
goto out;
lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- &lp->rx_bd_p, GFP_KERNEL);
+ &lp->rx_bd_p, GFP_KERNEL | __GFP_ZERO);
if (!lp->rx_bd_v)
goto out;
- memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
for (i = 0; i < TX_BD_NUM; i++) {
lp->tx_bd_v[i].next = lp->tx_bd_p +
sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM);
}
- memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
for (i = 0; i < RX_BD_NUM; i++) {
lp->rx_bd_v[i].next = lp->rx_bd_p +
sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index c238f98..24748e8 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -204,25 +204,23 @@ static int axienet_dma_bd_init(struct net_device *ndev)
lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
sizeof(*lp->tx_bd_v) * TX_BD_NUM,
&lp->tx_bd_p,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!lp->tx_bd_v)
goto out;
lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
sizeof(*lp->rx_bd_v) * RX_BD_NUM,
&lp->rx_bd_p,
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!lp->rx_bd_v)
goto out;
- memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
for (i = 0; i < TX_BD_NUM; i++) {
lp->tx_bd_v[i].next = lp->tx_bd_p +
sizeof(*lp->tx_bd_v) *
((i + 1) % TX_BD_NUM);
}
- memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
for (i = 0; i < RX_BD_NUM; i++) {
lp->rx_bd_v[i].next = lp->rx_bd_p +
sizeof(*lp->rx_bd_v) *
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index f116e51..4c8ddc9 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -1070,11 +1070,10 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
(PI_ALIGN_K_DESC_BLK - 1);
bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
&bp->kmalloced_dma,
- GFP_ATOMIC);
+ GFP_ATOMIC | __GFP_ZERO);
if (top_v == NULL)
return DFX_K_FAILURE;
- memset(top_v, 0, alloc_size); /* zero out memory before continuing */
top_p = bp->kmalloced_dma; /* get physical address of buffer */
/*
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 9cea451..3adb43c 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -352,21 +352,19 @@ static int ali_ircc_open(int i, chipio_t *info)
/* Allocate memory if needed */
self->rx_buff.head =
dma_alloc_coherent(NULL, self->rx_buff.truesize,
- &self->rx_buff_dma, GFP_KERNEL);
+ &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->rx_buff.head == NULL) {
err = -ENOMEM;
goto err_out2;
}
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head =
dma_alloc_coherent(NULL, self->tx_buff.truesize,
- &self->tx_buff_dma, GFP_KERNEL);
+ &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->tx_buff.head == NULL) {
err = -ENOMEM;
goto err_out3;
}
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 2a4f2f1..9cf836b 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -431,22 +431,20 @@ static int __init nsc_ircc_open(chipio_t *info)
/* Allocate memory if needed */
self->rx_buff.head =
dma_alloc_coherent(NULL, self->rx_buff.truesize,
- &self->rx_buff_dma, GFP_KERNEL);
+ &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->rx_buff.head == NULL) {
err = -ENOMEM;
goto out2;
}
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head =
dma_alloc_coherent(NULL, self->tx_buff.truesize,
- &self->tx_buff_dma, GFP_KERNEL);
+ &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->tx_buff.head == NULL) {
err = -ENOMEM;
goto out3;
}
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 858de05..964b116 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -700,12 +700,12 @@ static int pxa_irda_start(struct net_device *dev)
err = -ENOMEM;
si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
- &si->dma_rx_buff_phy, GFP_KERNEL );
+ &si->dma_rx_buff_phy, GFP_KERNEL);
if (!si->dma_rx_buff)
goto err_dma_rx_buff;
si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
- &si->dma_tx_buff_phy, GFP_KERNEL );
+ &si->dma_tx_buff_phy, GFP_KERNEL);
if (!si->dma_tx_buff)
goto err_dma_tx_buff;
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 59b45c1..aa05dad 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -563,19 +563,16 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma,
self->rx_buff.head =
dma_alloc_coherent(NULL, self->rx_buff.truesize,
- &self->rx_buff_dma, GFP_KERNEL);
+ &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->rx_buff.head == NULL)
goto err_out2;
self->tx_buff.head =
dma_alloc_coherent(NULL, self->tx_buff.truesize,
- &self->tx_buff_dma, GFP_KERNEL);
+ &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->tx_buff.head == NULL)
goto err_out3;
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
-
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
self->tx_buff.data = self->tx_buff.head;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f9033c6..51f2bc3 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -364,21 +364,19 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id)
/* Allocate memory if needed */
self->rx_buff.head =
dma_alloc_coherent(&pdev->dev, self->rx_buff.truesize,
- &self->rx_buff_dma, GFP_KERNEL);
+ &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->rx_buff.head == NULL) {
err = -ENOMEM;
goto err_out2;
}
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head =
dma_alloc_coherent(&pdev->dev, self->tx_buff.truesize,
- &self->tx_buff_dma, GFP_KERNEL);
+ &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->tx_buff.head == NULL) {
err = -ENOMEM;
goto err_out3;
}
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index f5bb92f..bb8857a 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -216,22 +216,19 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
/* Allocate memory if needed */
self->rx_buff.head =
dma_alloc_coherent(NULL, self->rx_buff.truesize,
- &self->rx_buff_dma, GFP_KERNEL);
+ &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->rx_buff.head == NULL) {
err = -ENOMEM;
goto err_out1;
}
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-
self->tx_buff.head =
dma_alloc_coherent(NULL, self->tx_buff.truesize,
- &self->tx_buff_dma, GFP_KERNEL);
+ &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
if (self->tx_buff.head == NULL) {
err = -ENOMEM;
goto err_out2;
}
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 38bc5a7..f73cbb5 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -419,8 +419,6 @@ static inline
static int alloc_ringmemory(struct b43_dmaring *ring)
{
- gfp_t flags = GFP_KERNEL;
-
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
* alignment and 8K buffers for 64-bit DMA with 8K alignment.
* In practice we could use smaller buffers for the latter, but the
@@ -435,12 +433,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
ring_mem_size, &(ring->dmabase),
- flags);
- if (!ring->descbase) {
- b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
+ GFP_KERNEL | __GFP_ZERO);
+ if (!ring->descbase)
return -ENOMEM;
- }
- memset(ring->descbase, 0, ring_mem_size);
return 0;
}
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 07d7e92..faeafe2 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -334,10 +334,9 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring)
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
B43legacy_DMA_RINGMEMSIZE,
&(ring->dmabase),
- GFP_KERNEL);
+ GFP_KERNEL | __GFP_ZERO);
if (!ring->descbase)
return -ENOMEM;
- memset(ring->descbase, 0, B43legacy_DMA_RINGMEMSIZE);
return 0;
}
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 7941eb3..238f528 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -1921,8 +1921,8 @@ drop_unlock:
static inline int
il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
{
- ptr->addr =
- dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma, GFP_KERNEL);
+ ptr->addr = dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma,
+ GFP_KERNEL);
if (!ptr->addr)
return -ENOMEM;
ptr->size = size;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index bd4c188..db21871 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -2566,15 +2566,13 @@ il_rx_queue_alloc(struct il_priv *il)
INIT_LIST_HEAD(&rxq->rx_used);
/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd =
- dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
- GFP_KERNEL);
+ rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
+ GFP_KERNEL);
if (!rxq->bd)
goto err_bd;
- rxq->rb_stts =
- dma_alloc_coherent(dev, sizeof(struct il_rb_status),
- &rxq->rb_stts_dma, GFP_KERNEL);
+ rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct il_rb_status),
+ &rxq->rb_stts_dma, GFP_KERNEL);
if (!rxq->rb_stts)
goto err_rb;
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 96f2025..458e699 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -2235,9 +2235,8 @@ il_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
return -EINVAL;
}
- desc->v_addr =
- dma_alloc_coherent(&pci_dev->dev, desc->len, &desc->p_addr,
- GFP_KERNEL);
+ desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+ &desc->p_addr, GFP_KERNEL);
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index a0c8cae..696abed 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -124,12 +124,10 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
*/
addr = dma_alloc_coherent(rt2x00dev->dev,
queue->limit * queue->desc_size,
- &dma, GFP_KERNEL);
+ &dma, GFP_KERNEL | __GFP_ZERO);
if (!addr)
return -ENOMEM;
- memset(addr, 0, queue->limit * queue->desc_size);
-
/*
* Initialize all queue entries to contain valid addresses.
*/
--
1.8.1.2.459.gbcd45b4.dirty
^ permalink raw reply related
* [PATCHv3 iproute2 3/3] man: Add documentation for the bridge link operation.
From: Vlad Yasevich @ 2013-03-15 17:04 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366869-27778-4-git-send-email-vyasevic@redhat.com>
[Darn, forgot to update the patch. this one is actually updated. Appologies.
]
Bridge tool now supports setting and retrieving bridge port specific
link attributes. Document what attributes are supported and what
they mean.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
man/man8/bridge.8 | 135 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 122 insertions(+), 13 deletions(-)
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index d34e3cf..8513a5a 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -13,13 +13,35 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.IR OBJECT " := { "
-.BR fdb " | " vlan " | " monitor " }"
+.BR link " | " fdb " | " vlan " | " monitor " }"
.sp
.ti -8
.IR OPTIONS " := { "
\fB\-V\fR[\fIersion\fR] |
-\fB\-s\fR[\fItatistics\fR]
+\fB\-s\fR[\fItatistics\fR] }
+
+.ti -8
+.BR "bridge link set"
+.B dev
+.IR DEV
+.IR " [ "
+.B cost
+.IR COST " ] [ "
+.B priority
+.IR PRIO " ] [ "
+.B state
+.IR STATE "] ["
+.BR guard " { " on " | " off " } ] [ "
+.BR hairpin " { " on " | " off " } ] [ "
+.BR fastleave " { " on " | " off " } ] [ "
+.BR root_block " { " on " | " off " } ] [ "
+.BR hwmode " { " vepa " | " veb " } ] "
+
+.ti -8
+.BR "bridge link" " [ " show " ] [ "
+.B dev
+.IR DEV " ]"
.ti -8
.BR "bridge fdb" " { " add " | " del " } "
@@ -72,6 +94,10 @@ As a rule, the information is statistics or some time values.
.I OBJECT
.TP
+.B link
+- Bridge port.
+
+.TP
.B fdb
- Forwarding Database entry.
@@ -102,6 +128,100 @@ Usually it is
or, if the objects of this class cannot be listed,
.BR "help" .
+.SH bridge link - bridge port
+
+.B link
+objects correspond to the port devices of the bridge.
+
+.P
+The corresponding commands set and display port status and bridge specific
+attributes.
+
+.SS bridge link set - set bridge specific attributes on a port
+
+.TP
+.BI dev " NAME "
+interface name of the bridge port
+
+.TP
+.BI cost " COST "
+the STP path cost of the specified port.
+
+.TP
+.BI priority " PRIO "
+the STP port priority. The priority value is an unsigned 8-bit quantity
+(number between 0 and 255). This metric is used in the designated port an
+droot port selectio algorithms.
+
+.TP
+.BI state " STATE "
+the operation state of the port. This is primarily used by user space STP/RSTP
+implementation. The following is a list of valid values:
+
+.B 0
+- port is DISABLED. Make this port completely inactive.
+.sp
+
+.B 1
+- STP LISTENING state. Only valid if STP is enabled on the brige. In this
+state the port for list for STP BPDUs and drop all other traffic.
+.sp
+
+.B 2
+- STP LEARNING state. Only valid if STP is enabled on the bridge. In this
+state the port will accept traffic only for the purpose of updating MAC
+adress tables.
+.sp
+
+.B 3
+- STP FORWARDING state. Port is fully active.
+.sp
+
+.B 4
+- STP BLOCKING state. Only valid if STP is eanbled on the bridge. This state
+is used during the STP election process. In this state, port will only process
+STP BPDUs.
+.sp
+
+.TP
+.BR "guard on " or " guard off "
+Controls whether STP BPUDs will be processed by the bridge port. By default,
+the flag is turned off allowed BPDU processing. Turning this flag on will
+cause the port to stop processing STP BPDUs.
+
+.TP
+.BR "hairpin on " or " hairpin off "
+Controls whether traffic may be send back out of the port on which it was
+received. By default, this flag is turned off and the bridge will not forward
+traffic back out of the receiving port.
+
+.TP
+.BR "fastleave on " or " fastleave off "
+This flag allows the bridge to immediately stop multicast traffic on a port
+that recieves IGMP Leave message. It is only used with IGMP snooping is
+enabled on the bridge. By default the flag is off.
+
+.TP
+.BR "root_block on " or " root_block off "
+Controls whether a given port is allowed to become root port or not. Only used
+when STP is enabled on the bridge. By default the flag is off.
+
+.TP
+.BI hwmode
+Some network interface cards support HW bridge functionality and they may be
+configured in different modes. Currently support modes are:
+
+.B vepa
+- Data sent between HW ports is sent on the wire to the external
+switch.
+
+.B veb
+- bridging happens in hardware.
+
+.SS bridge link show - list bridge port configuration.
+
+This command displays the current bridge port configuration and flags.
+
.SH bridge fdb - forwarding database management
.B fdb
@@ -123,17 +243,6 @@ the Ethernet MAC address.
.BI dev " NAME"
the interface to which this address is associated.
-.TP
-.in +8
-.B local
-- the address is associated with a local interface on the system
-and is never forwarded.
-.sp
-
-.B temp
-- the address is a dynamic entry, and will be removed if not used.
-.sp
-
.B self
- the address is associated with a software fdb (default)
.sp
--
1.7.7.6
^ permalink raw reply related
* [PATCHv3 iproute2 3/3] man: Add documentation for the bridge link operation.
From: Vlad Yasevich @ 2013-03-15 17:01 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366869-27778-1-git-send-email-vyasevic@redhat.com>
Bridge tool now supports setting and retrieving bridge port specific
link attributes. Document what attributes are supported and what
they mean.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
man/man8/bridge.8 | 136 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 123 insertions(+), 13 deletions(-)
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index d34e3cf..cad93ed 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -13,13 +13,36 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.IR OBJECT " := { "
-.BR fdb " | " vlan " | " monitor " }"
+.BR link " | " fdb " | " vlan " | " monitor " }"
.sp
.ti -8
.IR OPTIONS " := { "
\fB\-V\fR[\fIersion\fR] |
-\fB\-s\fR[\fItatistics\fR]
+\fB\-s\fR[\fItatistics\fR] }
+
+.ti -8
+.BR "bridge link set"
+.B dev
+.IR DEV
+.IR " [ "
+.B cost
+.IR COST " ] [ "
+.B priority
+.IR PRIO " ] [ "
+.B state
+.IR STATE "] ["
+.BR guard " { " on " | " off " } ] [ "
+.BR hairpin " { " on " | " off " } ] [ "
+.BR fastleave " { " on " | " off " } ] [ "
+.BR root_block " { " on " | " off " } ] [ "
+.BR hwmode " { " vepa " | " veb " } ] [ "
+.BR self " ] [ " master " ] "
+
+.ti -8
+.BR "bridge link" " [ " show " ] [ "
+.B dev
+.IR DEV " ]"
.ti -8
.BR "bridge fdb" " { " add " | " del " } "
@@ -72,6 +95,10 @@ As a rule, the information is statistics or some time values.
.I OBJECT
.TP
+.B link
+- Bridge port.
+
+.TP
.B fdb
- Forwarding Database entry.
@@ -102,6 +129,100 @@ Usually it is
or, if the objects of this class cannot be listed,
.BR "help" .
+.SH bridge link - bridge port
+
+.B link
+objects correspond to the port devices of the bridge.
+
+.P
+The corresponding commands set and display port status and bridge specific
+attributes.
+
+.SS bridge link set - set bridge specific attributes on a port
+
+.TP
+.BI dev " NAME "
+interface name of the bridge port
+
+.TP
+.BI cost " COST "
+the STP path cost of the specified port.
+
+.TP
+.BI priority " PRIO "
+the STP port priority. The priority value is an unsigned 8-bit quantity
+(number between 0 and 255). This metric is used in the designated port an
+droot port selectio algorithms.
+
+.TP
+.BI state " STATE "
+the operation state of the port. This is primarily used by user space STP/RSTP
+implementation. The following is a list of valid values:
+
+.B 0
+- port is DISABLED. Make this port completely inactive.
+.sp
+
+.B 1
+- STP LISTENING state. Only valid if STP is enabled on the brige. In this
+state the port for list for STP BPDUs and drop all other traffic.
+.sp
+
+.B 2
+- STP LEARNING state. Only valid if STP is enabled on the bridge. In this
+state the port will accept traffic only for the purpose of updating MAC
+adress tables.
+.sp
+
+.B 3
+- STP FORWARDING state. Port is fully active.
+.sp
+
+.B 4
+- STP BLOCKING state. Only valid if STP is eanbled on the bridge. This state
+is used during the STP election process. In this state, port will only process
+STP BPDUs.
+.sp
+
+.TP
+.BR "guard on " or " guard off "
+Controls whether STP BPUDs will be processed by the bridge port. By default,
+the flag is turned off allowed BPDU processing. Turning this flag on will
+cause the port to stop processing STP BPDUs.
+
+.TP
+.BR "hairpin on " or " hairpin off "
+Controls whether traffic may be send back out of the port on which it was
+received. By default, this flag is turned off and the bridge will not forward
+traffic back out of the receiving port.
+
+.TP
+.BR "fastleave on " or " fastleave off "
+This flag allows the bridge to immediately stop multicast traffic on a port
+that recieves IGMP Leave message. It is only used with IGMP snooping is
+enabled on the bridge. By default the flag is off.
+
+.TP
+.BR "root_block on " or " root_block off "
+Controls whether a given port is allowed to become root port or not. Only used
+when STP is enabled on the bridge. By default the flag is off.
+
+.TP
+.BI hwmode
+Some network interface cards support HW bridge functionality and they may be
+configured in different modes. Currently support modes are:
+
+.B vepa
+- Data sent between HW ports is sent on the wire to the external
+switch.
+
+.B veb
+- bridging happens in hardware.
+
+.SS bridge link show - list bridge port configuration.
+
+This command displays the current bridge port configuration and flags.
+
.SH bridge fdb - forwarding database management
.B fdb
@@ -123,17 +244,6 @@ the Ethernet MAC address.
.BI dev " NAME"
the interface to which this address is associated.
-.TP
-.in +8
-.B local
-- the address is associated with a local interface on the system
-and is never forwarded.
-.sp
-
-.B temp
-- the address is a dynamic entry, and will be removed if not used.
-.sp
-
.B self
- the address is associated with a software fdb (default)
.sp
--
1.7.7.6
^ permalink raw reply related
* [PATCHv3 iproute2 2/3] bridge: Add support for printing bridge port attributes
From: Vlad Yasevich @ 2013-03-15 17:01 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366869-27778-1-git-send-email-vyasevic@redhat.com>
Output new nested bridge port attributes.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/link.c | 79 +++++++++++++++++++++++++++++++++++++++++++++----
include/libnetlink.h | 2 +
lib/libnetlink.c | 13 +++++++-
3 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/bridge/link.c b/bridge/link.c
index 5811ee9..6b53833 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -65,6 +65,8 @@ static const char *oper_states[] = {
"TESTING", "DORMANT", "UP"
};
+static const char *hw_mode[] = {"VEB", "VEPA"};
+
static void print_operstate(FILE *f, __u8 state)
{
if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
@@ -73,6 +75,27 @@ static void print_operstate(FILE *f, __u8 state)
fprintf(f, "state %s ", oper_states[state]);
}
+static void print_portstate(FILE *f, __u8 state)
+{
+ if (state <= BR_STATE_BLOCKING)
+ fprintf(f, "state %s ", port_states[state]);
+ else
+ fprintf(f, "state (%d) ", state);
+}
+
+static void print_onoff(FILE *f, char *flag, __u8 val)
+{
+ fprintf(f, "%s %s ", flag, val ? "on" : "off");
+}
+
+static void print_hwmode(FILE *f, __u16 mode)
+{
+ if (mode >= sizeof(hw_mode)/sizeof(hw_mode[0]))
+ fprintf(f, "hwmode %#hx ", mode);
+ else
+ fprintf(f, "hwmode %s ", hw_mode[mode]);
+}
+
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
@@ -94,7 +117,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (filter_index && filter_index != ifi->ifi_index)
return 0;
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+ parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED);
if (tb[IFLA_IFNAME] == NULL) {
fprintf(stderr, "BUG: nil ifname\n");
@@ -131,13 +154,48 @@ int print_linkinfo(const struct sockaddr_nl *who,
if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1));
if (tb[IFLA_PROTINFO]) {
- __u8 state = rta_getattr_u8(tb[IFLA_PROTINFO]);
- if (state <= BR_STATE_BLOCKING)
- fprintf(fp, "state %s", port_states[state]);
- else
- fprintf(fp, "state (%d)", state);
+ if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) {
+ struct rtattr *prtb[IFLA_BRPORT_MAX+1];
+
+ parse_rtattr_nested(prtb, IFLA_BRPORT_MAX,
+ tb[IFLA_PROTINFO]);
+
+ if (prtb[IFLA_BRPORT_STATE])
+ print_portstate(fp,
+ rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
+ if (prtb[IFLA_BRPORT_PRIORITY])
+ fprintf(fp, "priority %hu ",
+ rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY]));
+ if (prtb[IFLA_BRPORT_COST])
+ fprintf(fp, "cost %u ",
+ rta_getattr_u32(prtb[IFLA_BRPORT_COST]));
+ if (prtb[IFLA_BRPORT_MODE])
+ print_onoff(fp, "hairpin",
+ rta_getattr_u8(prtb[IFLA_BRPORT_MODE]));
+ if (prtb[IFLA_BRPORT_GUARD])
+ print_onoff(fp, "guard",
+ rta_getattr_u8(prtb[IFLA_BRPORT_GUARD]));
+ if (prtb[IFLA_BRPORT_PROTECT])
+ print_onoff(fp, "root_block",
+ rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT]));
+ if (prtb[IFLA_BRPORT_FAST_LEAVE])
+ print_onoff(fp, "fastleave",
+ rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE]));
+ } else
+ print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO]));
}
+ if (tb[IFLA_AF_SPEC]) {
+ /* This is reported by HW devices that have some bridging
+ * capabilities.
+ */
+ struct rtattr *aftb[IFLA_BRIDGE_MAX+1];
+
+ parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
+
+ if (tb[IFLA_BRIDGE_MODE])
+ print_hwmode(fp, rta_getattr_u16(tb[IFLA_BRIDGE_MODE]));
+ }
fprintf(fp, "\n");
fflush(fp);
@@ -183,6 +241,7 @@ static int brlink_modify(int argc, char **argv)
__s8 hairpin = -1;
__s8 bpdu_guard = -1;
__s8 fast_leave = -1;
+ __s8 root_block = -1;
__u32 cost = 0;
__s16 priority = -1;
__s8 state = -1;
@@ -213,6 +272,10 @@ static int brlink_modify(int argc, char **argv)
NEXT_ARG();
if (!on_off("fastleave", &fast_leave, *argv))
exit(-1);
+ } else if (strcmp(*argv, "root_block") == 0) {
+ NEXT_ARG();
+ if (!on_off("root_block", &root_block, *argv))
+ exit(-1);
} else if (strcmp(*argv, "cost")) {
NEXT_ARG();
cost = atoi(*argv);
@@ -222,7 +285,7 @@ static int brlink_modify(int argc, char **argv)
} else if (strcmp(*argv, "state")) {
NEXT_ARG();
state = atoi(*argv);
- } else if (strcmp(*argv, "mode")) {
+ } else if (strcmp(*argv, "hwmode")) {
NEXT_ARG();
flags |= BRIDGE_FLAGS_SELF;
if (strcmp(*argv, "vepa") == 0)
@@ -265,6 +328,8 @@ static int brlink_modify(int argc, char **argv)
if (fast_leave >= 0)
addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
fast_leave);
+ if (root_block >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block);
if (cost > 0)
addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 8d15ee5..ec3d657 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -65,6 +65,8 @@ extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags);
extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 67f046f..f262959 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -658,10 +658,19 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
+ return parse_rtattr_flags(tb, max, rta, len, 0);
+}
+
+int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags)
+{
+ unsigned short type;
+
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while (RTA_OK(rta, len)) {
- if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
- tb[rta->rta_type] = rta;
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
rta = RTA_NEXT(rta,len);
}
if (len)
--
1.7.7.6
^ permalink raw reply related
* [PATCHv3 iproute2 1/3] bridge: Add support for setting bridge port attributes
From: Vlad Yasevich @ 2013-03-15 17:01 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366869-27778-1-git-send-email-vyasevic@redhat.com>
Add netlink support bridge port attributes such as cost, priority, state
and flags. This also adds support for HW mode such as VEPA or VEB.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/br_common.h | 1 +
bridge/bridge.c | 3 +-
bridge/link.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 220 insertions(+), 1 deletions(-)
diff --git a/bridge/br_common.h b/bridge/br_common.h
index 8764563..12fce3e 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -10,6 +10,7 @@ extern int do_fdb(int argc, char **argv);
extern int do_mdb(int argc, char **argv);
extern int do_monitor(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
+extern int do_link(int argc, char **argv);
extern int preferred_family;
extern int show_stats;
diff --git a/bridge/bridge.c b/bridge/bridge.c
index 06b7a54..77e260f 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -27,7 +27,7 @@ static void usage(void)
{
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
-"where OBJECT := { fdb | mdb | vlan | monitor }\n"
+"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails]\n" );
exit(-1);
}
@@ -42,6 +42,7 @@ static const struct cmd {
const char *cmd;
int (*func)(int argc, char **argv);
} cmds[] = {
+ { "link", do_link },
{ "fdb", do_fdb },
{ "mdb", do_mdb },
{ "vlan", do_vlan },
diff --git a/bridge/link.c b/bridge/link.c
index edb6fbf..5811ee9 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -9,10 +9,14 @@
#include <linux/if.h>
#include <linux/if_bridge.h>
#include <string.h>
+#include <stdbool.h>
+#include "libnetlink.h"
#include "utils.h"
#include "br_common.h"
+unsigned int filter_index;
+
static const char *port_states[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
@@ -87,6 +91,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC))
return 0;
+ if (filter_index && filter_index != ifi->ifi_index)
+ return 0;
+
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
if (tb[IFLA_IFNAME] == NULL) {
@@ -136,3 +143,213 @@ int print_linkinfo(const struct sockaddr_nl *who,
fflush(fp);
return 0;
}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE ]\n");
+ fprintf(stderr, " [ guard {on | off} ]\n");
+ fprintf(stderr, " [ hairpin {on | off} ] \n");
+ fprintf(stderr, " [ fastleave {on | off} ]\n");
+ fprintf(stderr, " [ root_block {on | off} ]\n");
+ fprintf(stderr, " [ hwmode {vepa | veb} ]\n");
+ fprintf(stderr, " bridge link show [dev DEV]\n");
+ exit(-1);
+}
+
+static bool on_off(char *arg, __s8 *attr, char *val)
+{
+ if (strcmp(val, "on") == 0)
+ *attr = 1;
+ else if (strcmp(val, "off") == 0)
+ *attr = 0;
+ else {
+ fprintf(stderr,
+ "Error: argument of \"%s\" must be \"on\" or \"off\"\n",
+ arg);
+ return false;
+ }
+
+ return true;
+}
+
+static int brlink_modify(int argc, char **argv)
+{
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifm;
+ char buf[512];
+ } req;
+ char *d = NULL;
+ __s8 hairpin = -1;
+ __s8 bpdu_guard = -1;
+ __s8 fast_leave = -1;
+ __u32 cost = 0;
+ __s16 priority = -1;
+ __s8 state = -1;
+ __s16 mode = -1;
+ __u16 flags = BRIDGE_FLAGS_MASTER;
+ struct rtattr *nest;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_SETLINK;
+ req.ifm.ifi_family = PF_BRIDGE;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ d = *argv;
+ } else if (strcmp(*argv, "guard") == 0) {
+ NEXT_ARG();
+ if (!on_off("guard", &bpdu_guard, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "hairpin") == 0) {
+ NEXT_ARG();
+ if (!on_off("hairping", &hairpin, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "fastleave") == 0) {
+ NEXT_ARG();
+ if (!on_off("fastleave", &fast_leave, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "cost")) {
+ NEXT_ARG();
+ cost = atoi(*argv);
+ } else if (strcmp(*argv, "priority")) {
+ NEXT_ARG();
+ priority = atoi(*argv);
+ } else if (strcmp(*argv, "state")) {
+ NEXT_ARG();
+ state = atoi(*argv);
+ } else if (strcmp(*argv, "mode")) {
+ NEXT_ARG();
+ flags |= BRIDGE_FLAGS_SELF;
+ if (strcmp(*argv, "vepa") == 0)
+ mode = BRIDGE_MODE_VEPA;
+ else if (strcmp(*argv, "veb") == 0)
+ mode = BRIDGE_MODE_VEB;
+ else {
+ fprintf(stderr,
+ "Mode argument must be \"vepa\" or "
+ "\"veb\".\n");
+ exit(-1);
+ }
+ } else {
+ usage();
+ }
+ argc--; argv++;
+ }
+ if (d == NULL) {
+ fprintf(stderr, "Device is a required argument.\n");
+ exit(-1);
+ }
+
+
+ req.ifm.ifi_index = ll_name_to_index(d);
+ if (req.ifm.ifi_index == 0) {
+ fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
+ exit(-1);
+ }
+
+ /* Nested PROTINFO attribute. Contains: port flags, cost, priority and
+ * state.
+ */
+ nest = addattr_nest(&req.n, sizeof(req),
+ IFLA_PROTINFO | NLA_F_NESTED);
+ /* Flags first */
+ if (bpdu_guard >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard);
+ if (hairpin >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin);
+ if (fast_leave >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
+ fast_leave);
+
+ if (cost > 0)
+ addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
+
+ if (priority >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority);
+
+ if (state >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state);
+
+ addattr_nest_end(&req.n, nest);
+
+ /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that
+ * designates master or self operation as well as 'vepa' or 'veb'
+ * operation modes. These are only valid in 'self' mode on some
+ * devices so far. Thus we only need to include the flags attribute
+ * if we are setting the hw mode.
+ */
+ if (mode >= 0) {
+ nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
+
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
+
+ if (mode >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode);
+
+ addattr_nest_end(&req.n, nest);
+ }
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+ exit(2);
+
+ return 0;
+}
+
+static int brlink_show(int argc, char **argv)
+{
+ char *filter_dev = NULL;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ if (filter_dev)
+ duparg("dev", *argv);
+ filter_dev = *argv;
+ }
+ argc--; argv++;
+ }
+
+ if (filter_dev) {
+ if ((filter_index = ll_name_to_index(filter_dev)) == 0) {
+ fprintf(stderr, "Cannot find device \"%s\"\n",
+ filter_dev);
+ return -1;
+ }
+ }
+
+ if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
+ perror("Cannon send dump request");
+ exit(1);
+ }
+
+ if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ exit(1);
+ }
+ return 0;
+}
+
+int do_link(int argc, char **argv)
+{
+ ll_init_map(&rth);
+ if (argc > 0) {
+ if (matches(*argv, "set") == 0 ||
+ matches(*argv, "change") == 0)
+ return brlink_modify(argc-1, argv+1);
+ if (matches(*argv, "show") == 0 ||
+ matches(*argv, "lst") == 0 ||
+ matches(*argv, "list") == 0)
+ return brlink_show(argc-1, argv+1);
+ if (matches(*argv, "help") == 0)
+ usage();
+ } else
+ return brlink_show(0, NULL);
+
+ fprintf(stderr, "Command \"%s\" is unknown, try \"bridge link help\".\n", *argv);
+ exit(-1);
+}
--
1.7.7.6
^ permalink raw reply related
* [PATCHv3 iproute2 0/3] Add support for bridge port link information
From: Vlad Yasevich @ 2013-03-15 17:01 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
Bridge ports provide unique link information about the properties and flags of
the port. This patch set allows bridge utility to configure and disaplay
this information.
Please take a look at the man page text and let me know if you have anything
to add.
Since v2:
- Remove master and self flags from brind link man page. They were removed
from the patch and made implicit since the only self command we support is
hwmode right now.
Since v1:
- Change the link output to match link command line options as suggested by
Stephen.
- Add man page text.
- Add root_block attribute.
Vlad Yasevich (3):
bridge: Add support for setting bridge port attributes
bridge: Add support for printing bridge port attributes
man: Add documentation for the bridge link operation.
bridge/br_common.h | 1 +
bridge/bridge.c | 3 +-
bridge/link.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++-
include/libnetlink.h | 2 +
lib/libnetlink.c | 13 ++-
man/man8/bridge.8 | 136 +++++++++++++++++++++---
6 files changed, 427 insertions(+), 22 deletions(-)
--
1.7.7.6
^ permalink raw reply
* [PATCH 4/9] netpoll: use DEFINE_STATIC_SRCU() to define netpoll_srcu
From: Lai Jiangshan @ 2013-03-15 16:50 UTC (permalink / raw)
To: Paul E. McKenney, Andrew Morton, linux-kernel
Cc: Lai Jiangshan, David S. Miller, Cong Wang, Neil Horman,
Eric Dumazet, Jiri Pirko, netdev
In-Reply-To: <1363366257-4886-1-git-send-email-laijs@cn.fujitsu.com>
DEFINE_STATIC_SRCU() defines srcu struct and do init at build time.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
net/core/netpoll.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index fa32899..a3a17ae 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -47,7 +47,7 @@ static struct sk_buff_head skb_pool;
static atomic_t trapped;
-static struct srcu_struct netpoll_srcu;
+DEFINE_STATIC_SRCU(netpoll_srcu);
#define USEC_PER_POLL 50
#define NETPOLL_RX_ENABLED 1
@@ -1212,7 +1212,6 @@ EXPORT_SYMBOL(netpoll_setup);
static int __init netpoll_init(void)
{
skb_queue_head_init(&skb_pool);
- init_srcu_struct(&netpoll_srcu);
return 0;
}
core_initcall(netpoll_init);
--
1.7.4.4
^ permalink raw reply related
* [PATCHv2 iproute2 3/3] man: Add documentation for the bridge link operation.
From: Vlad Yasevich @ 2013-03-15 16:46 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366001-27622-1-git-send-email-vyasevic@redhat.com>
Bridge tool now supports setting and retrieving bridge port specific
link attributes. Document what attributes are supported and what
they mean.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
man/man8/bridge.8 | 136 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 123 insertions(+), 13 deletions(-)
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index d34e3cf..cad93ed 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -13,13 +13,36 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.IR OBJECT " := { "
-.BR fdb " | " vlan " | " monitor " }"
+.BR link " | " fdb " | " vlan " | " monitor " }"
.sp
.ti -8
.IR OPTIONS " := { "
\fB\-V\fR[\fIersion\fR] |
-\fB\-s\fR[\fItatistics\fR]
+\fB\-s\fR[\fItatistics\fR] }
+
+.ti -8
+.BR "bridge link set"
+.B dev
+.IR DEV
+.IR " [ "
+.B cost
+.IR COST " ] [ "
+.B priority
+.IR PRIO " ] [ "
+.B state
+.IR STATE "] ["
+.BR guard " { " on " | " off " } ] [ "
+.BR hairpin " { " on " | " off " } ] [ "
+.BR fastleave " { " on " | " off " } ] [ "
+.BR root_block " { " on " | " off " } ] [ "
+.BR hwmode " { " vepa " | " veb " } ] [ "
+.BR self " ] [ " master " ] "
+
+.ti -8
+.BR "bridge link" " [ " show " ] [ "
+.B dev
+.IR DEV " ]"
.ti -8
.BR "bridge fdb" " { " add " | " del " } "
@@ -72,6 +95,10 @@ As a rule, the information is statistics or some time values.
.I OBJECT
.TP
+.B link
+- Bridge port.
+
+.TP
.B fdb
- Forwarding Database entry.
@@ -102,6 +129,100 @@ Usually it is
or, if the objects of this class cannot be listed,
.BR "help" .
+.SH bridge link - bridge port
+
+.B link
+objects correspond to the port devices of the bridge.
+
+.P
+The corresponding commands set and display port status and bridge specific
+attributes.
+
+.SS bridge link set - set bridge specific attributes on a port
+
+.TP
+.BI dev " NAME "
+interface name of the bridge port
+
+.TP
+.BI cost " COST "
+the STP path cost of the specified port.
+
+.TP
+.BI priority " PRIO "
+the STP port priority. The priority value is an unsigned 8-bit quantity
+(number between 0 and 255). This metric is used in the designated port an
+droot port selectio algorithms.
+
+.TP
+.BI state " STATE "
+the operation state of the port. This is primarily used by user space STP/RSTP
+implementation. The following is a list of valid values:
+
+.B 0
+- port is DISABLED. Make this port completely inactive.
+.sp
+
+.B 1
+- STP LISTENING state. Only valid if STP is enabled on the brige. In this
+state the port for list for STP BPDUs and drop all other traffic.
+.sp
+
+.B 2
+- STP LEARNING state. Only valid if STP is enabled on the bridge. In this
+state the port will accept traffic only for the purpose of updating MAC
+adress tables.
+.sp
+
+.B 3
+- STP FORWARDING state. Port is fully active.
+.sp
+
+.B 4
+- STP BLOCKING state. Only valid if STP is eanbled on the bridge. This state
+is used during the STP election process. In this state, port will only process
+STP BPDUs.
+.sp
+
+.TP
+.BR "guard on " or " guard off "
+Controls whether STP BPUDs will be processed by the bridge port. By default,
+the flag is turned off allowed BPDU processing. Turning this flag on will
+cause the port to stop processing STP BPDUs.
+
+.TP
+.BR "hairpin on " or " hairpin off "
+Controls whether traffic may be send back out of the port on which it was
+received. By default, this flag is turned off and the bridge will not forward
+traffic back out of the receiving port.
+
+.TP
+.BR "fastleave on " or " fastleave off "
+This flag allows the bridge to immediately stop multicast traffic on a port
+that recieves IGMP Leave message. It is only used with IGMP snooping is
+enabled on the bridge. By default the flag is off.
+
+.TP
+.BR "root_block on " or " root_block off "
+Controls whether a given port is allowed to become root port or not. Only used
+when STP is enabled on the bridge. By default the flag is off.
+
+.TP
+.BI hwmode
+Some network interface cards support HW bridge functionality and they may be
+configured in different modes. Currently support modes are:
+
+.B vepa
+- Data sent between HW ports is sent on the wire to the external
+switch.
+
+.B veb
+- bridging happens in hardware.
+
+.SS bridge link show - list bridge port configuration.
+
+This command displays the current bridge port configuration and flags.
+
.SH bridge fdb - forwarding database management
.B fdb
@@ -123,17 +244,6 @@ the Ethernet MAC address.
.BI dev " NAME"
the interface to which this address is associated.
-.TP
-.in +8
-.B local
-- the address is associated with a local interface on the system
-and is never forwarded.
-.sp
-
-.B temp
-- the address is a dynamic entry, and will be removed if not used.
-.sp
-
.B self
- the address is associated with a software fdb (default)
.sp
--
1.7.7.6
^ permalink raw reply related
* [PATCHv2 iproute2 1/3] bridge: Add support for setting bridge port attributes
From: Vlad Yasevich @ 2013-03-15 16:46 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366001-27622-1-git-send-email-vyasevic@redhat.com>
Add netlink support bridge port attributes such as cost, priority, state
and flags. This also adds support for HW mode such as VEPA or VEB.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/br_common.h | 1 +
bridge/bridge.c | 3 +-
bridge/link.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 220 insertions(+), 1 deletions(-)
diff --git a/bridge/br_common.h b/bridge/br_common.h
index 8764563..12fce3e 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -10,6 +10,7 @@ extern int do_fdb(int argc, char **argv);
extern int do_mdb(int argc, char **argv);
extern int do_monitor(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
+extern int do_link(int argc, char **argv);
extern int preferred_family;
extern int show_stats;
diff --git a/bridge/bridge.c b/bridge/bridge.c
index 06b7a54..77e260f 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -27,7 +27,7 @@ static void usage(void)
{
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
-"where OBJECT := { fdb | mdb | vlan | monitor }\n"
+"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails]\n" );
exit(-1);
}
@@ -42,6 +42,7 @@ static const struct cmd {
const char *cmd;
int (*func)(int argc, char **argv);
} cmds[] = {
+ { "link", do_link },
{ "fdb", do_fdb },
{ "mdb", do_mdb },
{ "vlan", do_vlan },
diff --git a/bridge/link.c b/bridge/link.c
index edb6fbf..5811ee9 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -9,10 +9,14 @@
#include <linux/if.h>
#include <linux/if_bridge.h>
#include <string.h>
+#include <stdbool.h>
+#include "libnetlink.h"
#include "utils.h"
#include "br_common.h"
+unsigned int filter_index;
+
static const char *port_states[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
@@ -87,6 +91,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC))
return 0;
+ if (filter_index && filter_index != ifi->ifi_index)
+ return 0;
+
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
if (tb[IFLA_IFNAME] == NULL) {
@@ -136,3 +143,213 @@ int print_linkinfo(const struct sockaddr_nl *who,
fflush(fp);
return 0;
}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE ]\n");
+ fprintf(stderr, " [ guard {on | off} ]\n");
+ fprintf(stderr, " [ hairpin {on | off} ] \n");
+ fprintf(stderr, " [ fastleave {on | off} ]\n");
+ fprintf(stderr, " [ root_block {on | off} ]\n");
+ fprintf(stderr, " [ hwmode {vepa | veb} ]\n");
+ fprintf(stderr, " bridge link show [dev DEV]\n");
+ exit(-1);
+}
+
+static bool on_off(char *arg, __s8 *attr, char *val)
+{
+ if (strcmp(val, "on") == 0)
+ *attr = 1;
+ else if (strcmp(val, "off") == 0)
+ *attr = 0;
+ else {
+ fprintf(stderr,
+ "Error: argument of \"%s\" must be \"on\" or \"off\"\n",
+ arg);
+ return false;
+ }
+
+ return true;
+}
+
+static int brlink_modify(int argc, char **argv)
+{
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifm;
+ char buf[512];
+ } req;
+ char *d = NULL;
+ __s8 hairpin = -1;
+ __s8 bpdu_guard = -1;
+ __s8 fast_leave = -1;
+ __u32 cost = 0;
+ __s16 priority = -1;
+ __s8 state = -1;
+ __s16 mode = -1;
+ __u16 flags = BRIDGE_FLAGS_MASTER;
+ struct rtattr *nest;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_SETLINK;
+ req.ifm.ifi_family = PF_BRIDGE;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ d = *argv;
+ } else if (strcmp(*argv, "guard") == 0) {
+ NEXT_ARG();
+ if (!on_off("guard", &bpdu_guard, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "hairpin") == 0) {
+ NEXT_ARG();
+ if (!on_off("hairping", &hairpin, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "fastleave") == 0) {
+ NEXT_ARG();
+ if (!on_off("fastleave", &fast_leave, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "cost")) {
+ NEXT_ARG();
+ cost = atoi(*argv);
+ } else if (strcmp(*argv, "priority")) {
+ NEXT_ARG();
+ priority = atoi(*argv);
+ } else if (strcmp(*argv, "state")) {
+ NEXT_ARG();
+ state = atoi(*argv);
+ } else if (strcmp(*argv, "mode")) {
+ NEXT_ARG();
+ flags |= BRIDGE_FLAGS_SELF;
+ if (strcmp(*argv, "vepa") == 0)
+ mode = BRIDGE_MODE_VEPA;
+ else if (strcmp(*argv, "veb") == 0)
+ mode = BRIDGE_MODE_VEB;
+ else {
+ fprintf(stderr,
+ "Mode argument must be \"vepa\" or "
+ "\"veb\".\n");
+ exit(-1);
+ }
+ } else {
+ usage();
+ }
+ argc--; argv++;
+ }
+ if (d == NULL) {
+ fprintf(stderr, "Device is a required argument.\n");
+ exit(-1);
+ }
+
+
+ req.ifm.ifi_index = ll_name_to_index(d);
+ if (req.ifm.ifi_index == 0) {
+ fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
+ exit(-1);
+ }
+
+ /* Nested PROTINFO attribute. Contains: port flags, cost, priority and
+ * state.
+ */
+ nest = addattr_nest(&req.n, sizeof(req),
+ IFLA_PROTINFO | NLA_F_NESTED);
+ /* Flags first */
+ if (bpdu_guard >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard);
+ if (hairpin >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin);
+ if (fast_leave >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
+ fast_leave);
+
+ if (cost > 0)
+ addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
+
+ if (priority >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority);
+
+ if (state >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state);
+
+ addattr_nest_end(&req.n, nest);
+
+ /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that
+ * designates master or self operation as well as 'vepa' or 'veb'
+ * operation modes. These are only valid in 'self' mode on some
+ * devices so far. Thus we only need to include the flags attribute
+ * if we are setting the hw mode.
+ */
+ if (mode >= 0) {
+ nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
+
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
+
+ if (mode >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode);
+
+ addattr_nest_end(&req.n, nest);
+ }
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+ exit(2);
+
+ return 0;
+}
+
+static int brlink_show(int argc, char **argv)
+{
+ char *filter_dev = NULL;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ if (filter_dev)
+ duparg("dev", *argv);
+ filter_dev = *argv;
+ }
+ argc--; argv++;
+ }
+
+ if (filter_dev) {
+ if ((filter_index = ll_name_to_index(filter_dev)) == 0) {
+ fprintf(stderr, "Cannot find device \"%s\"\n",
+ filter_dev);
+ return -1;
+ }
+ }
+
+ if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
+ perror("Cannon send dump request");
+ exit(1);
+ }
+
+ if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ exit(1);
+ }
+ return 0;
+}
+
+int do_link(int argc, char **argv)
+{
+ ll_init_map(&rth);
+ if (argc > 0) {
+ if (matches(*argv, "set") == 0 ||
+ matches(*argv, "change") == 0)
+ return brlink_modify(argc-1, argv+1);
+ if (matches(*argv, "show") == 0 ||
+ matches(*argv, "lst") == 0 ||
+ matches(*argv, "list") == 0)
+ return brlink_show(argc-1, argv+1);
+ if (matches(*argv, "help") == 0)
+ usage();
+ } else
+ return brlink_show(0, NULL);
+
+ fprintf(stderr, "Command \"%s\" is unknown, try \"bridge link help\".\n", *argv);
+ exit(-1);
+}
--
1.7.7.6
^ permalink raw reply related
* [PATCHv2 iproute2 2/3] bridge: Add support for printing bridge port attributes
From: Vlad Yasevich @ 2013-03-15 16:46 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
In-Reply-To: <1363366001-27622-1-git-send-email-vyasevic@redhat.com>
Output new nested bridge port attributes.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/link.c | 79 +++++++++++++++++++++++++++++++++++++++++++++----
include/libnetlink.h | 2 +
lib/libnetlink.c | 13 +++++++-
3 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/bridge/link.c b/bridge/link.c
index 5811ee9..6b53833 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -65,6 +65,8 @@ static const char *oper_states[] = {
"TESTING", "DORMANT", "UP"
};
+static const char *hw_mode[] = {"VEB", "VEPA"};
+
static void print_operstate(FILE *f, __u8 state)
{
if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
@@ -73,6 +75,27 @@ static void print_operstate(FILE *f, __u8 state)
fprintf(f, "state %s ", oper_states[state]);
}
+static void print_portstate(FILE *f, __u8 state)
+{
+ if (state <= BR_STATE_BLOCKING)
+ fprintf(f, "state %s ", port_states[state]);
+ else
+ fprintf(f, "state (%d) ", state);
+}
+
+static void print_onoff(FILE *f, char *flag, __u8 val)
+{
+ fprintf(f, "%s %s ", flag, val ? "on" : "off");
+}
+
+static void print_hwmode(FILE *f, __u16 mode)
+{
+ if (mode >= sizeof(hw_mode)/sizeof(hw_mode[0]))
+ fprintf(f, "hwmode %#hx ", mode);
+ else
+ fprintf(f, "hwmode %s ", hw_mode[mode]);
+}
+
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
@@ -94,7 +117,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (filter_index && filter_index != ifi->ifi_index)
return 0;
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+ parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED);
if (tb[IFLA_IFNAME] == NULL) {
fprintf(stderr, "BUG: nil ifname\n");
@@ -131,13 +154,48 @@ int print_linkinfo(const struct sockaddr_nl *who,
if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1));
if (tb[IFLA_PROTINFO]) {
- __u8 state = rta_getattr_u8(tb[IFLA_PROTINFO]);
- if (state <= BR_STATE_BLOCKING)
- fprintf(fp, "state %s", port_states[state]);
- else
- fprintf(fp, "state (%d)", state);
+ if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) {
+ struct rtattr *prtb[IFLA_BRPORT_MAX+1];
+
+ parse_rtattr_nested(prtb, IFLA_BRPORT_MAX,
+ tb[IFLA_PROTINFO]);
+
+ if (prtb[IFLA_BRPORT_STATE])
+ print_portstate(fp,
+ rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
+ if (prtb[IFLA_BRPORT_PRIORITY])
+ fprintf(fp, "priority %hu ",
+ rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY]));
+ if (prtb[IFLA_BRPORT_COST])
+ fprintf(fp, "cost %u ",
+ rta_getattr_u32(prtb[IFLA_BRPORT_COST]));
+ if (prtb[IFLA_BRPORT_MODE])
+ print_onoff(fp, "hairpin",
+ rta_getattr_u8(prtb[IFLA_BRPORT_MODE]));
+ if (prtb[IFLA_BRPORT_GUARD])
+ print_onoff(fp, "guard",
+ rta_getattr_u8(prtb[IFLA_BRPORT_GUARD]));
+ if (prtb[IFLA_BRPORT_PROTECT])
+ print_onoff(fp, "root_block",
+ rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT]));
+ if (prtb[IFLA_BRPORT_FAST_LEAVE])
+ print_onoff(fp, "fastleave",
+ rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE]));
+ } else
+ print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO]));
}
+ if (tb[IFLA_AF_SPEC]) {
+ /* This is reported by HW devices that have some bridging
+ * capabilities.
+ */
+ struct rtattr *aftb[IFLA_BRIDGE_MAX+1];
+
+ parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
+
+ if (tb[IFLA_BRIDGE_MODE])
+ print_hwmode(fp, rta_getattr_u16(tb[IFLA_BRIDGE_MODE]));
+ }
fprintf(fp, "\n");
fflush(fp);
@@ -183,6 +241,7 @@ static int brlink_modify(int argc, char **argv)
__s8 hairpin = -1;
__s8 bpdu_guard = -1;
__s8 fast_leave = -1;
+ __s8 root_block = -1;
__u32 cost = 0;
__s16 priority = -1;
__s8 state = -1;
@@ -213,6 +272,10 @@ static int brlink_modify(int argc, char **argv)
NEXT_ARG();
if (!on_off("fastleave", &fast_leave, *argv))
exit(-1);
+ } else if (strcmp(*argv, "root_block") == 0) {
+ NEXT_ARG();
+ if (!on_off("root_block", &root_block, *argv))
+ exit(-1);
} else if (strcmp(*argv, "cost")) {
NEXT_ARG();
cost = atoi(*argv);
@@ -222,7 +285,7 @@ static int brlink_modify(int argc, char **argv)
} else if (strcmp(*argv, "state")) {
NEXT_ARG();
state = atoi(*argv);
- } else if (strcmp(*argv, "mode")) {
+ } else if (strcmp(*argv, "hwmode")) {
NEXT_ARG();
flags |= BRIDGE_FLAGS_SELF;
if (strcmp(*argv, "vepa") == 0)
@@ -265,6 +328,8 @@ static int brlink_modify(int argc, char **argv)
if (fast_leave >= 0)
addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
fast_leave);
+ if (root_block >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block);
if (cost > 0)
addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 8d15ee5..ec3d657 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -65,6 +65,8 @@ extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags);
extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 67f046f..f262959 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -658,10 +658,19 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
+ return parse_rtattr_flags(tb, max, rta, len, 0);
+}
+
+int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags)
+{
+ unsigned short type;
+
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while (RTA_OK(rta, len)) {
- if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
- tb[rta->rta_type] = rta;
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
rta = RTA_NEXT(rta,len);
}
if (len)
--
1.7.7.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox