* Re: Re: [PATCH-SR9700] Merge USB 1.1 Ethernet Adapter SR9700 DeviceDriver into the Linux Kernel
From: liujunliang_ljl @ 2013-08-21 10:07 UTC (permalink / raw)
To: Joe Perches, Francois Romieu
Cc: gregkh, sunhecheng, linux-usb, netdev, linux-kernel
In-Reply-To: <1377032302.2016.75.camel@joe-AO722>
Dear Joe :
Thanks a lot and I have been fixed all the problems mentioned above. please check the following patch and thanks again.
[PATCH] :
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 287cc62..a94b196 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -272,6 +272,14 @@ config USB_NET_DM9601
This option adds support for Davicom DM9601 based USB 1.1
10/100 Ethernet adapters.
+config USB_NET_SR9700
+ tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
+ depends on USB_USBNET
+ select CRC32
+ help
+ This option adds support for CoreChip-sz SR9700 based USB 1.1
+ 10/100 Ethernet adapters.
+
config USB_NET_SMSC75XX
tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
depends on USB_USBNET
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index 9ab5c9d..bba87a2 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
+obj-$(CONFIG_USB_NET_SR9700) += sr9700.o
obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o
obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
new file mode 100644
index 0000000..9c8f167
--- /dev/null
+++ b/drivers/net/usb/sr9700.c
@@ -0,0 +1,536 @@
+/*
+ * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices
+ *
+ * Author : liujl <liujunliang_ljl@163.com>
+ *
+ * Based on dm9601.c
+ *
+ * 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/module.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+
+#include "sr9700.h"
+
+static int sr_read(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+ int err;
+
+ err = usbnet_read_cmd(dev, SR_RD_REGS, SR_REQ_RD_REG,
+ 0, reg, data, length);
+ if ((err != length) && (err >= 0))
+ err = -EINVAL;
+ return err;
+}
+
+static int sr_write(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+ int err;
+
+ err = usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ 0, reg, data, length);
+ if ((err >= 0) && (err < length))
+ err = -EINVAL;
+ return err;
+}
+
+static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
+{
+ return sr_read(dev, reg, 1, value);
+}
+
+static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
+{
+ return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ value, reg, NULL, 0);
+}
+
+static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+ usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ 0, reg, data, length);
+}
+
+static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+{
+ usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ value, reg, NULL, 0);
+}
+
+static int sr_share_read_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
+{
+ int ret, i;
+
+ mutex_lock(&dev->phy_mutex);
+
+ sr_write_reg(dev, EPAR, phy ? (reg | 0x40) : reg);
+ sr_write_reg(dev, EPCR, phy ? 0xc : 0x4);
+
+ for (i = 0; i < SR_SHARE_TIMEOUT; i++) {
+ u8 tmp = 0;
+
+ udelay(1);
+ ret = sr_read_reg(dev, EPCR, &tmp);
+ if (ret < 0)
+ goto out_unlock;
+
+ /* ready */
+ if ((tmp & EPCR_ERRE) == 0)
+ break;
+ }
+
+ if (i >= SR_SHARE_TIMEOUT) {
+ netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ sr_write_reg(dev, EPCR, 0x0);
+ ret = sr_read(dev, EPDR, 2, value);
+
+ netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
+ phy, reg, *value, ret);
+
+ out_unlock:
+ mutex_unlock(&dev->phy_mutex);
+ return ret;
+}
+
+static int sr_share_write_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
+{
+ int ret, i;
+
+ mutex_lock(&dev->phy_mutex);
+
+ ret = sr_write(dev, EPDR, 2, &value);
+ if (ret < 0)
+ goto out_unlock;
+
+ sr_write_reg(dev, EPAR, phy ? (reg | 0x40) : reg);
+ sr_write_reg(dev, EPCR, phy ? 0x1a : 0x12);
+
+ for (i = 0; i < SR_SHARE_TIMEOUT; i++) {
+ u8 tmp = 0;
+
+ udelay(1);
+ ret = sr_read_reg(dev, EPCR, &tmp);
+ if (ret < 0)
+ goto out_unlock;
+
+ /* ready */
+ if ((tmp & EPCR_ERRE) == 0)
+ break;
+ }
+
+ if (i >= SR_SHARE_TIMEOUT) {
+ netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ sr_write_reg(dev, EPCR, 0x0);
+
+out_unlock:
+ mutex_unlock(&dev->phy_mutex);
+ return ret;
+}
+
+static int sr_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
+{
+ return sr_share_read_word(dev, 0, offset, value);
+}
+
+static int sr9700_get_eeprom_len(struct net_device *dev)
+{
+ return SR_EEPROM_LEN;
+}
+
+static int sr9700_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct usbnet *dev = netdev_priv(net);
+ __le16 *ebuf = (__le16 *) data;
+ int ret = 0;
+ int i;
+
+ /* access is 16bit */
+ if ((eeprom->offset % 2) || (eeprom->len % 2))
+ return -EINVAL;
+
+ for (i = 0; i < eeprom->len / 2; i++)
+ ret = sr_read_eeprom_word(dev, eeprom->offset / 2 + i, &ebuf[i]);
+
+ return ret;
+}
+
+static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ __le16 res;
+ int rc = 0;
+
+ if (phy_id) {
+ netdev_dbg(dev->net, "Only internal phy supported\n");
+ return 0;
+ }
+
+ /* Access NSR_LINKST bit for link status instead of MII_BMSR */
+ if (loc == MII_BMSR) {
+ u8 value;
+
+ sr_read_reg(dev, NSR, &value);
+ if (value & NSR_LINKST)
+ rc = 1;
+ }
+ sr_share_read_word(dev, 1, loc, &res);
+ if (rc == 1)
+ return le16_to_cpu(res) | BMSR_LSTATUS;
+ else
+ return le16_to_cpu(res) & ~BMSR_LSTATUS;
+
+ netdev_dbg(dev->net,
+ "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
+ phy_id, loc, le16_to_cpu(res));
+
+ return le16_to_cpu(res);
+}
+
+static void sr_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ __le16 res = cpu_to_le16(val);
+
+ if (phy_id) {
+ netdev_dbg(dev->net, "Only internal phy supported\n");
+ return;
+ }
+
+ netdev_dbg(dev->net, "sr_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
+ phy_id, loc, val);
+
+ sr_share_write_word(dev, 1, loc, res);
+}
+
+static u32 sr9700_get_link(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int rc = 0;
+ u8 value = 0;
+
+ /* Get the Link Status directly */
+ sr_read_reg(dev, NSR, &value);
+ if (value & NSR_LINKST)
+ rc = 1;
+
+ return rc;
+}
+
+static int sr9700_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static const struct ethtool_ops sr9700_ethtool_ops = {
+ .get_drvinfo = usbnet_get_drvinfo,
+ .get_link = sr9700_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_eeprom_len = sr9700_get_eeprom_len,
+ .get_eeprom = sr9700_get_eeprom,
+ .get_settings = usbnet_get_settings,
+ .set_settings = usbnet_set_settings,
+ .nway_reset = usbnet_nway_reset,
+};
+
+static void sr9700_set_multicast(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ /* We use the 20 byte dev->data for our 8 byte filter buffer
+ * to avoid allocating memory that is tricky to free later
+ */
+ u8 *hashes = (u8 *) &dev->data;
+ /* rx_ctl setting : enable, disable_long, disable_crc */
+ u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG;
+
+ memset(hashes, 0x00, SR_MCAST_SIZE);
+ hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG; /* broadcast address */
+
+ if (net->flags & IFF_PROMISC) {
+ rx_ctl |= RCR_PRMSC;
+ } else if (net->flags & IFF_ALLMULTI ||
+ netdev_mc_count(net) > SR_MCAST_MAX) {
+ rx_ctl |= RCR_RUNT;
+ } else if (!netdev_mc_empty(net)) {
+ struct netdev_hw_addr *ha;
+ netdev_for_each_mc_addr(ha, net) {
+ u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
+ hashes[crc >> 3] |= 1 << (crc & 0x7);
+ }
+ }
+
+ sr_write_async(dev, MAR, SR_MCAST_SIZE, hashes);
+ sr_write_reg_async(dev, RCR, rx_ctl);
+}
+
+static int sr9700_set_mac_address(struct net_device *net, void *p)
+{
+ struct sockaddr *addr = p;
+ struct usbnet *dev = netdev_priv(net);
+
+ if (!is_valid_ether_addr(addr->sa_data)) {
+ netdev_err(net, "not setting invalid mac address %pM\n",
+ addr->sa_data);
+ return -EINVAL;
+ }
+
+ memcpy(net->dev_addr, addr->sa_data, net->addr_len);
+ sr_write_async(dev, PAR, 6, dev->net->dev_addr);
+
+ return 0;
+}
+
+static const struct net_device_ops sr9700_netdev_ops = {
+ .ndo_open = usbnet_open,
+ .ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_change_mtu = usbnet_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = sr9700_ioctl,
+ .ndo_set_rx_mode = sr9700_set_multicast,
+ .ndo_set_mac_address = sr9700_set_mac_address,
+};
+
+static int sr9700_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+
+ ret = usbnet_get_endpoints(dev, intf);
+ if (ret)
+ goto out;
+
+ dev->net->netdev_ops = &sr9700_netdev_ops;
+ dev->net->ethtool_ops = &sr9700_ethtool_ops;
+ dev->net->hard_header_len += SR_TX_OVERHEAD;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+ dev->rx_urb_size = 3072; /* bulkin buffer is preferably not less than 3K */
+
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = sr_mdio_read;
+ dev->mii.mdio_write = sr_mdio_write;
+ dev->mii.phy_id_mask = 0x1f;
+ dev->mii.reg_num_mask = 0x1f;
+
+ /* reset the sr9700 */
+ sr_write_reg(dev, NCR, 1);
+ udelay(20);
+
+ /* read MAC
+ * After Chip Power on, the Chip will reload the MAC from EEPROM automatically to PAR
+ * In case there is no EEPROM externally, a default MAC address is stored in PAR for making chip work properly
+ */
+ if (sr_read(dev, PAR, ETH_ALEN, dev->net->dev_addr) < 0) {
+ netdev_err(dev->net, "Error reading MAC address\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* power up and reset phy */
+ sr_write_reg(dev, PRR, 1);
+ mdelay(20); /* at least 10ms, here 20ms for safe */
+ sr_write_reg(dev, PRR, 0);
+ udelay(2 * 1000); /* at least 1ms, here 2ms for reading right register */
+
+ /* receive broadcast packets */
+ sr9700_set_multicast(dev->net);
+
+ sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ mii_nway_restart(&dev->mii);
+
+out:
+ return ret;
+}
+
+static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ int len;
+ struct sk_buff *sr_skb;
+
+ /* format:
+ b0: rx status
+ b1: packet length (incl crc) low
+ b2: packet length (incl crc) high
+ b3..n-4: packet data
+ bn-3..bn: ethernet crc
+ */
+
+ if (unlikely(skb->len < SR_RX_OVERHEAD)) {
+ netdev_err(dev->net, "unexpected tiny rx frame\n");
+ return 0;
+ }
+
+ /* Each packet contains multiple skbs */
+ while (skb->len > SR_RX_OVERHEAD) {
+ if (skb->data[0] != 0x40)
+ return 0;
+
+ /* ignore the CRC length */
+ len = (skb->data[1] | (skb->data[2] << 8)) - 4;
+
+ if (len > ETH_FRAME_LEN)
+ return 0;
+
+ /* the last skb of current packet */
+ if (skb->len == (len + SR_RX_OVERHEAD)) {
+ skb_pull(skb, 3);
+ skb->len = len;
+ skb->tail = skb->data + len;
+ skb->truesize = len + sizeof(struct sk_buff);
+ return 2;
+ }
+
+ /* skb_clone is used for address align */
+ sr_skb = skb_clone(skb, GFP_ATOMIC);
+ if (sr_skb) {
+ sr_skb->len = len;
+ sr_skb->data = skb->data + 3;
+ sr_skb->tail = skb->data + len;
+ sr_skb->truesize = len + sizeof(struct sk_buff);
+ usbnet_skb_return(dev, sr_skb);
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, len + SR_RX_OVERHEAD);
+ };
+
+ return 0;
+}
+
+static struct sk_buff *sr9700_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int len;
+
+ /* format:
+ b0: packet length low
+ b1: packet length high
+ b3..n: packet data
+ */
+
+ len = skb->len;
+
+ if (skb_headroom(skb) < SR_TX_OVERHEAD) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ __skb_push(skb, SR_TX_OVERHEAD);
+
+ /* usbnet adds padding if length is a multiple of packet size
+ * if so, adjust length value in header
+ */
+ if ((skb->len % dev->maxpacket) == 0)
+ len++;
+
+ skb->data[0] = len;
+ skb->data[1] = len >> 8;
+
+ return skb;
+}
+
+static void sr9700_status(struct usbnet *dev, struct urb *urb)
+{
+ int link;
+ u8 *buf;
+
+ /* format:
+ b0: net status
+ b1: tx status 1
+ b2: tx status 2
+ b3: rx status
+ b4: rx overflow
+ b5: rx count
+ b6: tx count
+ b7: gpr
+ */
+
+ if (urb->actual_length < 8)
+ return;
+
+ buf = urb->transfer_buffer;
+
+ link = !!(buf[0] & 0x40);
+ if (netif_carrier_ok(dev->net) != link) {
+ usbnet_link_change(dev, link, 1);
+ netdev_dbg(dev->net, "Link Status is: %d\n", link);
+ }
+}
+
+static int sr9700_link_reset(struct usbnet *dev)
+{
+ struct ethtool_cmd ecmd;
+
+ mii_check_media(&dev->mii, 1, 1);
+ mii_ethtool_gset(&dev->mii, &ecmd);
+
+ netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n",
+ ecmd.speed, ecmd.duplex);
+
+ return 0;
+}
+
+static const struct driver_info sr9700_driver_info = {
+ .description = "CoreChip SR9700 USB Ethernet",
+ .flags = FLAG_ETHER,
+ .bind = sr9700_bind,
+ .rx_fixup = sr9700_rx_fixup,
+ .tx_fixup = sr9700_tx_fixup,
+ .status = sr9700_status,
+ .link_reset = sr9700_link_reset,
+ .reset = sr9700_link_reset,
+};
+
+static const struct usb_device_id products[] = {
+ {
+ USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */
+ .driver_info = (unsigned long)&sr9700_driver_info,
+ },
+ {}, /* END */
+};
+
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver sr9700_usb_driver = {
+ .name = "sr9700",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(sr9700_usb_driver);
+
+MODULE_AUTHOR("liujl <liujunliang_ljl@163.com>");
+MODULE_DESCRIPTION("SR9700 one chip USB 1.1 USB to Ethernet device from http://www.corechip-sz.com/");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/sr9700.h b/drivers/net/usb/sr9700.h
new file mode 100644
index 0000000..f1968ae
--- /dev/null
+++ b/drivers/net/usb/sr9700.h
@@ -0,0 +1,172 @@
+/*
+ * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices
+ *
+ * Author : liujl <liujunliang_ljl@163.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _SR9700_H
+#define _SR9700_H
+
+/* sr9700 spec. register table on Linux platform */
+
+/* Network Control Reg */
+#define NCR 0x00
+#define NCR_RST (1 << 0)
+#define NCR_LBK (3 << 1)
+#define NCR_FDX (1 << 3)
+#define NCR_WAKEEN (1 << 6)
+/* Network Status Reg */
+#define NSR 0x01
+#define NSR_RXRDY (1 << 0)
+#define NSR_RXOV (1 << 1)
+#define NSR_TX1END (1 << 2)
+#define NSR_TX2END (1 << 3)
+#define NSR_TXFULL (1 << 4)
+#define NSR_WAKEST (1 << 5)
+#define NSR_LINKST (1 << 6)
+#define NSR_SPEED (1 << 7)
+/* Tx Control Reg */
+#define TCR 0x02
+#define TCR_CRC_DIS (1 << 1)
+#define TCR_PAD_DIS (1 << 2)
+#define TCR_LC_CARE (1 << 3)
+#define TCR_CRS_CARE (1 << 4)
+#define TCR_EXCECM (1 << 5)
+#define TCR_LF_EN (1 << 6)
+/* Tx Status Reg for Packet Index 1 */
+#define TSR1 0x03
+#define TSR1_EC (1 << 2)
+#define TSR1_COL (1 << 3)
+#define TSR1_LC (1 << 4)
+#define TSR1_NC (1 << 5)
+#define TSR1_LOC (1 << 6)
+#define TSR1_TLF (1 << 7)
+/* Tx Status Reg for Packet Index 2 */
+#define TSR2 0x04
+#define TSR2_EC (1 << 2)
+#define TSR2_COL (1 << 3)
+#define TSR2_LC (1 << 4)
+#define TSR2_NC (1 << 5)
+#define TSR2_LOC (1 << 6)
+#define TSR2_TLF (1 << 7)
+/* Rx Control Reg*/
+#define RCR 0x05
+#define RCR_RXEN (1 << 0)
+#define RCR_PRMSC (1 << 1)
+#define RCR_RUNT (1 << 2)
+#define RCR_ALL (1 << 3)
+#define RCR_DIS_CRC (1 << 4)
+#define RCR_DIS_LONG (1 << 5)
+/* Rx Status Reg */
+#define RSR 0x06
+#define RSR_AE (1 << 2)
+#define RSR_MF (1 << 6)
+#define RSR_RF (1 << 7)
+/* Rx Overflow Counter Reg */
+#define ROCR 0x07
+#define ROCR_ROC (0x7F << 0)
+#define ROCR_RXFU (1 << 7)
+/* Back Pressure Threshold Reg */
+#define BPTR 0x08
+#define BPTR_JPT (0x0F << 0)
+#define BPTR_BPHW (0x0F << 4)
+/* Flow Control Threshold Reg */
+#define FCTR 0x09
+#define FCTR_LWOT (0x0F << 0)
+#define FCTR_HWOT (0x0F << 4)
+/* rx/tx Flow Control Reg */
+#define FCR 0x0A
+#define FCR_FLCE (1 << 0)
+#define FCR_BKPA (1 << 4)
+#define FCR_TXPEN (1 << 5)
+#define FCR_TXPF (1 << 6)
+#define FCR_TXP0 (1 << 7)
+/* Eeprom & Phy Control Reg */
+#define EPCR 0x0B
+#define EPCR_ERRE (1 << 0)
+#define EPCR_ERPRW (1 << 1)
+#define EPCR_ERPRR (1 << 2)
+#define EPCR_EPOS (1 << 3)
+#define EPCR_WEP (1 << 4)
+/* Eeprom & Phy Address Reg */
+#define EPAR 0x0C
+#define EPAR_EROA (0x3F << 0)
+#define EPAR_PHY_ADR (0x03 << 6)
+/* Eeprom & Phy Data Reg */
+#define EPDR 0x0D /* 0x0D ~ 0x0E for Data Reg Low & High */
+/* Wakeup Control Reg */
+#define WCR 0x0F
+#define WCR_MAGICST (1 << 0)
+#define WCR_LINKST (1 << 2)
+#define WCR_MAGICEN (1 << 3)
+#define WCR_LINKEN (1 << 5)
+/* Physical Address Reg */
+#define PAR 0x10 /* 0x10 ~ 0x15 6 bytes for PAR */
+/* Multicast Address Reg */
+#define MAR 0x16 /* 0x16 ~ 0x1D 8 bytes for MAR */
+/* 0x1e unused */
+/* Phy Reset Reg */
+#define PRR 0x1F
+#define PRR_PHY_RST (1 << 0)
+/* Tx sdram Write Pointer Address Low */
+#define TWPAL 0x20
+/* Tx sdram Write Pointer Address High */
+#define TWPAH 0x21
+/* Tx sdram Read Pointer Address Low */
+#define TRPAL 0x22
+/* Tx sdram Read Pointer Address High */
+#define TRPAH 0x23
+/* Rx sdram Write Pointer Address Low */
+#define RWPAL 0x24
+/* Rx sdram Write Pointer Address High */
+#define RWPAH 0x25
+/* Rx sdram Read Pointer Address Low */
+#define RRPAL 0x26
+/* Rx sdram Read Pointer Address High */
+#define RRPAH 0x27
+/* Vendor ID register */
+#define VID 0x28 /* 0x28 ~ 0x29 2 bytes for VID */
+/* Product ID register */
+#define PID 0x2A /* 0x2A ~ 0x2B 2 bytes for PID */
+/* CHIP Revision register */
+#define CHIPR 0x2C
+/* 0x2D --> 0xEF unused */
+/* USB Device Address */
+#define USBDA 0xF0
+#define USBDA_USBFA (0x7F << 0)
+/* RX packet Counter Reg */
+#define RXC 0xF1
+/* Tx packet Counter & USB Status Reg */
+#define TXC_USBS 0xF2
+#define TXC_USBS_TXC0 (1 << 0)
+#define TXC_USBS_TXC1 (1 << 1)
+#define TXC_USBS_TXC2 (1 << 2)
+#define TXC_USBS_EP1RDY (1 << 5)
+#define TXC_USBS_SUSFLAG (1 << 6)
+#define TXC_USBS_RXFAULT (1 << 7)
+/* USB Control register */
+#define USBC 0xF4
+#define USBC_EP3NAK (1 << 4)
+#define USBC_EP3ACK (1 << 5)
+
+/* Register access commands and flags */
+#define SR_RD_REGS 0x00
+#define SR_WR_REGS 0x01
+#define SR_WR_REG 0x03
+#define SR_REQ_RD_REG (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+#define SR_REQ_WR_REG (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+
+/* parameters */
+#define SR_SHARE_TIMEOUT 1000
+#define SR_EEPROM_LEN 256
+#define SR_MCAST_SIZE 8
+#define SR_MCAST_ADDR_FLAG 0x80
+#define SR_MCAST_MAX 64
+#define SR_TX_OVERHEAD 2 /* 2bytes header */
+#define SR_RX_OVERHEAD 7 /* 3bytes header + 4crc tail */
+
+#endif /* _SR9700_H */
2013-08-21
liujunliang_ljl
发件人: Joe Perches
发送时间: 2013-08-21 04:58:27
收件人: Francois Romieu
抄送: liujunliang_ljl; gregkh; sunhecheng; linux-usb; netdev; linux-kernel
主题: Re: [PATCH-SR9700] Merge USB 1.1 Ethernet Adapter SR9700 DeviceDriver into the Linux Kernel
On Tue, 2013-08-20 at 22:46 +0200, Francois Romieu wrote:
> liujunliang_ljl <liujunliang_ljl@163.com> :
> > + if (i >= SR_SHARE_TIMEOUT) {
> > + netdev_err(dev->net, "%s read timed out!", phy ? "phy" : "eeprom");
netdev_<level>, like almost all other printk
messages needs a terminating "\n" newline to
avoid any possible message interleaving by other
printks.
> > + if (!is_valid_ether_addr(addr->sa_data)) {
> > + dev_err(&net->dev, "not setting invalid mac address %pM\n",
> > + addr->sa_data);
>
> dev_err(&net->dev, "not setting invalid mac address %pM\n",
> addr->sa_data);
prefer netdev_<level> to dev_<level> where possible.
^ permalink raw reply related
* [PATCH 0/2] net: can: use platform_set_drvdata()
From: Libo Chen @ 2013-08-21 10:14 UTC (permalink / raw)
To: wg, mkl; +Cc: davem, linux-can, lizefan, netdev, linux-kernel, libo.chen
Use the wrapper functions for getting and setting the driver data using
platform_device instead of using dev_set_drvdata() with &pdev->dev,
so we can directly pass a struct platform_device.
Libo Chen (2):
net: can: at91_can: use platform_set_drvdata()
net: can: flexcan: use platform_set_drvdata()
drivers/net/can/at91_can.c | 2 +-
drivers/net/can/flexcan.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
^ permalink raw reply
* [PATCH 1/2] net: can: at91_can: use platform_set_drvdata()
From: Libo Chen @ 2013-08-21 10:15 UTC (permalink / raw)
To: wg, mkl; +Cc: davem, linux-can, netdev, linux-kernel, lizefan, libo.chen
Use the wrapper functions for getting and setting the driver data using
platform_device instead of using dev_set_drvdata() with &pdev->dev,
so we can directly pass a struct platform_device.
Signed-off-by: Libo Chen <libo.chen@huawei.com>
---
drivers/net/can/at91_can.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index dbbe97a..3b1ff61 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -1355,7 +1355,7 @@ static int at91_can_probe(struct platform_device *pdev)
if (at91_is_sam9263(priv))
dev->sysfs_groups[0] = &at91_sysfs_attr_group;
- dev_set_drvdata(&pdev->dev, dev);
+ platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
err = register_candev(dev);
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] net: can: flexcan: use platform_set_drvdata()
From: Libo Chen @ 2013-08-21 10:15 UTC (permalink / raw)
To: wg, mkl; +Cc: linux-can, davem, netdev, linux-kernel, lizefan, libo.chen
Use the wrapper functions for getting and setting the driver data using
platform_device instead of using dev_set_drvdata() with &pdev->dev,
so we can directly pass a struct platform_device.
Signed-off-by: Libo Chen <libo.chen@huawei.com>
---
drivers/net/can/flexcan.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 7b0be09..9978de7 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1087,7 +1087,7 @@ static int flexcan_probe(struct platform_device *pdev)
netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
- dev_set_drvdata(&pdev->dev, dev);
+ platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
err = register_flexcandev(dev);
--
1.7.1
^ permalink raw reply related
* [PATCH] net: irda: pxaficp_ir: use platform_set_drvdata()
From: Libo Chen @ 2013-08-21 10:15 UTC (permalink / raw)
To: samuel, davem; +Cc: netdev, linux-kernel, lizefan, libo.chen
Use the wrapper functions for getting and setting the driver data using
platform_device instead of using deva_set_drvdata() with &pdev->dev,
so we can directly pass a struct platform_device.
Signed-off-by: Libo Chen <libo.chen@huawei.com>
---
drivers/net/irda/pxaficp_ir.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 964b116..3eeaaf8 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -915,7 +915,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
err = register_netdev(dev);
if (err == 0)
- dev_set_drvdata(&pdev->dev, dev);
+ platform_set_drvdata(pdev, dev);
if (err) {
if (si->pdata->shutdown)
--
1.7.1
^ permalink raw reply related
* [PATCH] net: phy: mdio-octeon: use platform_set_drvdata()
From: Libo Chen @ 2013-08-21 10:15 UTC (permalink / raw)
To: davem, grant.likely, rob.herring
Cc: david.daney, wfp5p, gregkh, sachin.kamat, netdev, linux-kernel,
lizefan, libo.chen
Use the wrapper functions for getting and setting the driver data using
platform_device instead of using dev_set_drvdata() with &pdev->dev,
so we can directly pass a struct platform_device.
Signed-off-by: Libo Chen <libo.chen@huawei.com>
---
drivers/net/phy/mdio-octeon.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index b51fa1f..7f18f80 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -222,7 +222,7 @@ static int octeon_mdiobus_probe(struct platform_device *pdev)
bus->mii_bus->read = octeon_mdiobus_read;
bus->mii_bus->write = octeon_mdiobus_write;
- dev_set_drvdata(&pdev->dev, bus);
+ platform_set_drvdata(pdev, bus);
err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
if (err)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 2/2] net: can: flexcan: use platform_set_drvdata()
From: Marc Kleine-Budde @ 2013-08-21 10:17 UTC (permalink / raw)
To: Libo Chen; +Cc: wg, linux-can, davem, netdev, linux-kernel, lizefan
In-Reply-To: <1377080108-33780-1-git-send-email-libo.chen@huawei.com>
[-- Attachment #1: Type: text/plain, Size: 596 bytes --]
On 08/21/2013 12:15 PM, Libo Chen wrote:
> Use the wrapper functions for getting and setting the driver data using
> platform_device instead of using dev_set_drvdata() with &pdev->dev,
> so we can directly pass a struct platform_device.
>
> Signed-off-by: Libo Chen <libo.chen@huawei.com>
tnx, applied.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] net: can: at91_can: use platform_set_drvdata()
From: Marc Kleine-Budde @ 2013-08-21 10:16 UTC (permalink / raw)
To: Libo Chen; +Cc: wg, davem, linux-can, netdev, linux-kernel, lizefan
In-Reply-To: <1377080103-33872-1-git-send-email-libo.chen@huawei.com>
[-- Attachment #1: Type: text/plain, Size: 596 bytes --]
On 08/21/2013 12:15 PM, Libo Chen wrote:
> Use the wrapper functions for getting and setting the driver data using
> platform_device instead of using dev_set_drvdata() with &pdev->dev,
> so we can directly pass a struct platform_device.
>
> Signed-off-by: Libo Chen <libo.chen@huawei.com>
tnx, applied.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply
* [PATCH] be2net: fix disabling TX in be_close()
From: Sathya Perla @ 2013-08-21 10:22 UTC (permalink / raw)
To: netdev
commit fba875591 disabled TX in be_close() to protect be_xmit() from
touching freed up queues in the AER recovery flow.
But, TX must be disabled *before* cleaning up TX completions in the
close() path, not after. This allows be_tx_compl_clean() to free up
all TX-req skbs that were notified to the HW.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 181edb5..4559c35 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2563,8 +2563,8 @@ static int be_close(struct net_device *netdev)
/* Wait for all pending tx completions to arrive so that
* all tx skbs are freed.
*/
- be_tx_compl_clean(adapter);
netif_tx_disable(netdev);
+ be_tx_compl_clean(adapter);
be_rx_qs_destroy(adapter);
--
1.8.3.4
^ permalink raw reply related
* Re: [PATCH net-next] ip6_tunnel: ensure to always have a link local address
From: Nicolas Dichtel @ 2013-08-21 10:25 UTC (permalink / raw)
To: Bjørn Mork; +Cc: David Miller, netdev, yoshfuji
In-Reply-To: <87haej76wz.fsf@nemi.mork.no>
Le 21/08/2013 11:02, Bjørn Mork a écrit :
> Nicolas Dichtel <nicolas.dichtel@6wind.com> writes:
>> Le 21/08/2013 08:48, David Miller a écrit :
>>
>>> Applied, but this brings up an issue I keep noticing.
>>>
>>> We talk about eth_random_addr() and "uniqueness" together all the
>>> time, but the former never implies the latter.
>>>
>>> And we're going to run into situations where any conflicts generated
>>> by this random address generater will cause reall failures.
>>>
>>> Therefore we'll have to create a system to prevent them. Probably
>>> using some simple table that keeps track of the addresses we've
>>> generated.
>>>
>> Ok, I will look at this.
>
> Are eth_random_addr() collisions really any different than interfaces
> having the same address for other reasons?
I would tend to say yes, it's different.
It's easy for an administrator to fix a configuration for a physical interface,
because it's statically configured and there is a limited number of interfaces.
For virtual interfaces, they can be dynamically created and destroyed by daemons
and we can have a lot of interfaces. Hence it could be hard to fix them. Trying
to avoid these errors at kernel level could be useful.
I've start to write a patch, and to test it I've just run a simple test which
generate 1 000 000 of random addresses. I've run it several times (maybe not
enough ;-)) and I never get a duplicated address...
^ permalink raw reply
* [PATCH net-next 0/4] tun: Some bits required for tun's checkpoint-restore (v2)
From: Pavel Emelyanov @ 2013-08-21 10:31 UTC (permalink / raw)
To: David Miller, Linux Netdev List
Hi,
After taking a closer look on tun checkpoint-restore I've found several
issues with the tun's API that make it impossible to dump and restore
the state of tun device and attached tun-files.
The proposed API changes are all about extending the existing ioctl-based
stuff. Patches fit today's net-next.
This v2 has David's comments about patch #1 fixed. All the rest is the same.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
^ permalink raw reply
* [PATCH 1/4] tun: Add ability to create tun device with given index
From: Pavel Emelyanov @ 2013-08-21 10:31 UTC (permalink / raw)
To: David Miller, Linux Netdev List
In-Reply-To: <521496EF.8090909@parallels.com>
Tun devices cannot be created with ifidex user wants, but it's
required by checkpoint-restore project.
Long time ago such ability was implemented for rtnl_ops-based
interface for creating links (9c7dafbf net: Allow to create links
with given ifindex), but the only API for creating and managing
tuntap devices is ioctl-based and is evolving with adding new ones
(cde8b15f tuntap: add ioctl to attach or detach a file form tuntap
device).
Following that trend, here's how a new ioctl that sets the ifindex
for device, that _will_ be created by TUNSETIFF ioctl looks like.
So those who want a tuntap device with the ifindex N, should open
the tun device, call ioctl(fd, TUNSETIFINDEX, &N), then call TUNSETIFF.
If the index N is busy, then the register_netdev will find this out
and the ioctl would be failed with -EBUSY.
If setifindex is not called, then it will be generated as before.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
drivers/net/tun.c | 21 ++++++++++++++++++++-
include/uapi/linux/if_tun.h | 1 +
2 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7ed13cc..4b65fbc 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -138,7 +138,10 @@ struct tun_file {
struct fasync_struct *fasync;
/* only used for fasnyc */
unsigned int flags;
- u16 queue_index;
+ union {
+ u16 queue_index;
+ unsigned int ifindex;
+ };
struct list_head next;
struct tun_struct *detached;
};
@@ -1601,6 +1604,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
dev_net_set(dev, net);
dev->rtnl_link_ops = &tun_link_ops;
+ dev->ifindex = tfile->ifindex;
tun = netdev_priv(dev);
tun->dev = dev;
@@ -1817,6 +1821,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
kgid_t group;
int sndbuf;
int vnet_hdr_sz;
+ unsigned int ifindex;
int ret;
if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
@@ -1851,6 +1856,19 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
ret = -EFAULT;
goto unlock;
}
+ if (cmd == TUNSETIFINDEX) {
+ ret = -EPERM;
+ if (tun)
+ goto unlock;
+
+ ret = -EFAULT;
+ if (copy_from_user(&ifindex, argp, sizeof(ifindex)))
+ goto unlock;
+
+ ret = 0;
+ tfile->ifindex = ifindex;
+ goto unlock;
+ }
ret = -EBADFD;
if (!tun)
@@ -2099,6 +2117,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
rcu_assign_pointer(tfile->tun, NULL);
tfile->net = get_net(current->nsproxy->net_ns);
tfile->flags = 0;
+ tfile->ifindex = 0;
rcu_assign_pointer(tfile->socket.wq, &tfile->wq);
init_waitqueue_head(&tfile->wq.wait);
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 1870ee2..c58d023 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -56,6 +56,7 @@
#define TUNGETVNETHDRSZ _IOR('T', 215, int)
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
#define TUNSETQUEUE _IOW('T', 217, int)
+#define TUNSETIFINDEX _IOW('T', 218, unsigned int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
--
1.7.6.5
^ permalink raw reply related
* [PATCH 2/4] tun: Report whether the queue is attached or not
From: Pavel Emelyanov @ 2013-08-21 10:32 UTC (permalink / raw)
To: David Miller, Linux Netdev List
In-Reply-To: <521496EF.8090909@parallels.com>
Multiqueue tun devices allow to attach and detach from its queues
while keeping the interface itself set on file.
Knowing this is critical for the checkpoint part of criu project.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
drivers/net/tun.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4b65fbc..db43a24 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1881,6 +1881,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
case TUNGETIFF:
tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
+ if (tfile->detached)
+ ifr.ifr_flags |= IFF_DETACH_QUEUE;
+
if (copy_to_user(argp, &ifr, ifreq_len))
ret = -EFAULT;
break;
--
1.7.6.5
^ permalink raw reply related
* [PATCH 3/4] tun: Allow to skip filter on attach
From: Pavel Emelyanov @ 2013-08-21 10:32 UTC (permalink / raw)
To: David Miller, Linux Netdev List
In-Reply-To: <521496EF.8090909@parallels.com>
There's a small problem with sk-filters on tun devices. Consider
an application doing this sequence of steps:
fd = open("/dev/net/tun");
ioctl(fd, TUNSETIFF, { .ifr_name = "tun0" });
ioctl(fd, TUNATTACHFILTER, &my_filter);
ioctl(fd, TUNSETPERSIST, 1);
close(fd);
At that point the tun0 will remain in the system and will keep in
mind that there should be a socket filter at address '&my_filter'.
If after that we do
fd = open("/dev/net/tun");
ioctl(fd, TUNSETIFF, { .ifr_name = "tun0" });
we most likely receive the -EFAULT error, since tun_attach() would
try to connect the filter back. But (!) if we provide a filter at
address &my_filter, then tun0 will be created and the "new" filter
would be attached, but application may not know about that.
This may create certain problems to anyone using tun-s, but it's
critical problem for c/r -- if we meet a persistent tun device
with a filter in mind, we will not be able to attach to it to dump
its state (flags, owner, address, vnethdr size, etc.).
The proposal is to allow to attach to tun device (with TUNSETIFF)
w/o attaching the filter to the tun-file's socket. After this
attach app may e.g clean the device by dropping the filter, it
doesn't want to have one, or (in case of c/r) get information
about the device with tun ioctls.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
drivers/net/tun.c | 12 +++++++-----
include/uapi/linux/if_tun.h | 1 +
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index db43a24..6acbdbc 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -501,7 +501,7 @@ static void tun_detach_all(struct net_device *dev)
module_put(THIS_MODULE);
}
-static int tun_attach(struct tun_struct *tun, struct file *file)
+static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filter)
{
struct tun_file *tfile = file->private_data;
int err;
@@ -526,7 +526,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
err = 0;
/* Re-attach the filter to presist device */
- if (tun->filter_attached == true) {
+ if (!skip_filter && (tun->filter_attached == true)) {
err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
if (!err)
goto out;
@@ -1557,7 +1557,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
if (err < 0)
return err;
- err = tun_attach(tun, file);
+ err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER);
if (err < 0)
return err;
@@ -1631,7 +1631,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
dev->vlan_features = dev->features;
INIT_LIST_HEAD(&tun->disabled);
- err = tun_attach(tun, file);
+ err = tun_attach(tun, file, false);
if (err < 0)
goto err_free_dev;
@@ -1795,7 +1795,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
ret = security_tun_dev_attach_queue(tun->security);
if (ret < 0)
goto unlock;
- ret = tun_attach(tun, file);
+ ret = tun_attach(tun, file, false);
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
tun = rtnl_dereference(tfile->tun);
if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached)
@@ -1883,6 +1883,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
if (tfile->detached)
ifr.ifr_flags |= IFF_DETACH_QUEUE;
+ if (!tfile->socket.sk->sk_filter)
+ ifr.ifr_flags |= IFF_NOFILTER;
if (copy_to_user(argp, &ifr, ifreq_len))
ret = -EFAULT;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index c58d023..cc127b2 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -71,6 +71,7 @@
#define IFF_DETACH_QUEUE 0x0400
/* read-only flag */
#define IFF_PERSIST 0x0800
+#define IFF_NOFILTER 0x1000
/* Socket options */
#define TUN_TX_TIMESTAMP 1
--
1.7.6.5
^ permalink raw reply related
* [PATCH 4/4] tun: Get skfilter layout
From: Pavel Emelyanov @ 2013-08-21 10:32 UTC (permalink / raw)
To: David Miller, Linux Netdev List
In-Reply-To: <521496EF.8090909@parallels.com>
The only thing we may have from tun device is the fprog, whic contains
the number of filter elements and a pointer to (user-space) memory
where the elements are. The program itself may not be available if the
device is persistent and detached.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
drivers/net/tun.c | 10 ++++++++++
include/uapi/linux/if_tun.h | 1 +
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 6acbdbc..60a1e93 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2042,6 +2042,16 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
tun_detach_filter(tun, tun->numqueues);
break;
+ case TUNGETFILTER:
+ ret = -EINVAL;
+ if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
+ break;
+ ret = -EFAULT;
+ if (copy_to_user(argp, &tun->fprog, sizeof(tun->fprog)))
+ break;
+ ret = 0;
+ break;
+
default:
ret = -EINVAL;
break;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index cc127b2..e9502dd 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -57,6 +57,7 @@
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
#define TUNSETQUEUE _IOW('T', 217, int)
#define TUNSETIFINDEX _IOW('T', 218, unsigned int)
+#define TUNGETFILTER _IOR('T', 219, struct sock_fprog)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
--
1.7.6.5
^ permalink raw reply related
* [PATCH RFC net-next] net: epoll support for busy poll
From: Eliezer Tamir @ 2013-08-21 10:39 UTC (permalink / raw)
To: David Miller
Cc: linux-kernel, netdev, e1000-devel, Eilon Greenstein, Amir Vadai,
Eric Dumazet, Willem de Bruijn, Eliezer Tamir
Add busy poll support to epoll.
Background:
The persistent nature of epoll allows us to have a long lasting context
that we use to keep track of which device queues we expect traffic
to come on for the sockets monitored by an epoll file.
Design:
We tried to make epoll changes as small as possible and to keep
networking structures out of eventpoll.c.
All of the epoll changes have nop placeholders for when busy poll
is not defined.
Instead of remembering the napi_id for all the sockets in an epoll,
we only track the first socket we see with any unique napi_id.
The rational for this is that while there may be many thousands of
sockets tracked by a single epoll, we expect to only see a handful
of unique napi_ids in most cases.
A list of "unique" sockets is linked to struct epoll.
Struct busy_poll_id_index serves as the element of this list.
In sk_mark_napi_id() we notice and record the following events:
1. the napid_id of an sk changes
2. the socket receives data through napi poll
in epoll_poll_callback() and ep_table_queue_proc() if these
events happened, we check if we need to update the list.
Locking:
ep->busy_list is protected by ep->lock, with irqs disabled.
busy_poll indices use RCU.
sk_ll_state uses bitpos.
Performance:
using sockperf, Intel X520 NICs,
Supermicro 6026TT-BTF systems with E5-2690 Xeon CPUs
100 UDP sockets avg. latency 5.756 (std-dev 0.510)
1k UDP sockets avg. latency 5.780 (std-dev 0.536)
10k UDP sockets avg. latency 6.269 (std-dev 0.611)
Open issues:
warn_busy_list_empty() happens under load with memcached.
Should we add some hysteresis so the queue list does not change too fast?
As usual suggestions about naming, where to put things and overall design
are most welcome.
Credit:
Eliel Louzoun and Matthew Wilcox: parts of the event handling algorithm.
Willem de Brujin: advice on style, where to put things, RCU.
Special thanks for finding bugs in earlier versions: Julie Cummings.
Signed-off-by: Eliezer Tamir <eliezer.tamir@linux.intel.com>
---
fs/eventpoll.c | 131 +++++++++++++++++++++++++++++
include/linux/poll.h | 2
include/net/busy_poll.h | 216 +++++++++++++++++++++++++++++++++++++++++++++--
include/net/sock.h | 1
4 files changed, 341 insertions(+), 9 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9ad17b15..f432599 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -42,6 +42,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/compat.h>
+#include <net/busy_poll.h>
/*
* LOCKING:
@@ -215,6 +216,9 @@ struct eventpoll {
/* used to optimize loop detection check */
int visited;
struct list_head visited_list_link;
+
+ /* list of busy poll indices with active unique busy-poll ids */
+ struct busy_list busy_list;
};
/* Wait structure used by the poll hooks */
@@ -233,6 +237,10 @@ struct eppoll_entry {
/* The wait queue head that linked the "wait" wait queue item */
wait_queue_head_t *whead;
+
+ /* Is this file in the busy wait list for our waiter */
+ struct busy_state busy;
+
};
/* Wrapper struct used by poll queueing */
@@ -375,6 +383,103 @@ static inline int ep_events_available(struct eventpoll *ep)
return !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR;
}
+#ifdef CONFIG_NET_RX_BUSY_POLL
+/*
+ * if busy polling is on and the file for this pwq is a socket,
+ * return a pointer to struct socket
+ */
+static inline struct socket *ep_sock_from_pwq(struct eppoll_entry *pwq)
+{
+ struct file *file = pwq->base->ffd.file;
+ struct inode *inode = file_inode(file);
+
+ if (!net_busy_loop_on())
+ return NULL;
+
+ if (!S_ISSOCK(inode->i_mode))
+ return NULL;
+
+ return file->private_data;
+}
+
+/*
+ * check if a socket might need to be added or removed from busy poll list
+ * must be called with ep->lock taken, irqs disabled
+ */
+static inline void eppoll_check_busy_poll(struct eventpoll *ep,
+ struct eppoll_entry *pwq)
+{
+ struct socket *sock = ep_sock_from_pwq(pwq);
+
+ if (!sock)
+ return;
+
+ busy_poll_update_socket(sock, &ep->busy_list, &pwq->busy.listed);
+}
+
+/*
+ * attempt to delete on removal even if !net_busy_loop_on because it may have
+ * been turned off while we have sockets on the list
+ */
+static inline void eppoll_del_busy_poll(struct eventpoll *ep,
+ struct eppoll_entry *pwq)
+{
+ struct socket *sock = pwq->busy.listed ? ep_sock_from_pwq(pwq) : NULL;
+ unsigned long flags;
+
+ if (sock) {
+ spin_lock_irqsave(&ep->lock, flags);
+ busy_poll_delete_socket(&ep->busy_list, sock);
+ pwq->busy.listed = false;
+ spin_unlock_irqrestore(&ep->lock, flags);
+ }
+}
+
+/*
+ * called from ep_poll() when there is nothing for the user
+ * and busy polling is on
+ */
+static inline void epoll_busy_loop(struct eventpoll *ep, unsigned long end)
+{
+ struct busy_poll_id_index *idx;
+
+ rcu_read_lock_bh();
+
+ while (!busy_loop_timeout(end) && !need_resched()) {
+ list_for_each_entry_rcu(idx, &ep->busy_list.head, list) {
+ if (napi_id_busy_loop(idx->napi_id) &&
+ ep_events_available(ep))
+ goto out;
+ }
+ }
+out:
+ rcu_read_unlock_bh();
+}
+
+#else /* CONFIG_NET_RX_BUSY_POLL */
+
+static inline struct socket *ep_sock_from_pwq(struct eppoll_entry *pwq)
+{
+ return NULL;
+}
+
+static inline void eppoll_check_busy_poll(struct eventpoll *ep,
+ struct eppoll_entry *pwq)
+{
+}
+
+static inline void eppoll_del_busy_poll(struct eventpoll *ep,
+ struct eppoll_entry *pwq)
+{
+}
+
+static inline void epoll_busy_loop(struct eventpoll *ep, unsigned long end)
+{
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+
+
/**
* ep_call_nested - Perform a bound (possibly) nested call, by checking
* that the recursion limit is not exceeded, and that
@@ -536,6 +641,7 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
list_del(&pwq->llink);
ep_remove_wait_queue(pwq);
+ eppoll_del_busy_poll(ep, pwq);
kmem_cache_free(pwq_cache, pwq);
}
}
@@ -755,6 +861,10 @@ static void ep_free(struct eventpoll *ep)
epi = rb_entry(rbp, struct epitem, rbn);
ep_remove(ep, epi);
}
+
+ /* at this stage ep->ll_list should be empty */
+ warn_busy_list_empty(&ep->busy_list);
+
mutex_unlock(&ep->mtx);
mutex_unlock(&epmutex);
@@ -920,6 +1030,7 @@ static int ep_alloc(struct eventpoll **pep)
init_waitqueue_head(&ep->wq);
init_waitqueue_head(&ep->poll_wait);
INIT_LIST_HEAD(&ep->rdllist);
+ init_busy_list(&ep->busy_list);
ep->rbr = RB_ROOT;
ep->ovflist = EP_UNACTIVE_PTR;
ep->user = user;
@@ -987,6 +1098,8 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
spin_lock_irqsave(&ep->lock, flags);
+ eppoll_check_busy_poll(ep, ep_pwq_from_wait(wait));
+
/*
* If the event mask does not contain any poll(2) event, we consider the
* descriptor to be disabled. This condition is likely the effect of the
@@ -1066,9 +1179,11 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
pwq->base = epi;
+ init_busy_state(&pwq->busy);
add_wait_queue(whead, &pwq->wait);
list_add_tail(&pwq->llink, &epi->pwqlist);
epi->nwait++;
+ eppoll_check_busy_poll(epi->ep, pwq);
} else {
/* We have to signal that an error occurred */
epi->nwait = -1;
@@ -1559,6 +1674,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
long slack = 0;
wait_queue_t wait;
ktime_t expires, *to = NULL;
+ unsigned long busy_loop_end = 0;
if (timeout > 0) {
struct timespec end_time = ep_set_mstimeout(timeout);
@@ -1577,6 +1693,21 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
}
fetch_events:
+
+ /*
+ * Busy poll if globally on and supporting sockets found && no events,
+ * busy loop will return if need_resched or ep_events_available.
+ *
+ * we must do our busy polling with irqs enabled
+ */
+
+ if (epoll_can_busy_loop(&ep->busy_list) && !ep_events_available(ep)) {
+ if (!busy_loop_end)
+ busy_loop_end = busy_loop_end_time();
+
+ epoll_busy_loop(ep, busy_loop_end);
+ }
+
spin_lock_irqsave(&ep->lock, flags);
if (!ep_events_available(ep)) {
diff --git a/include/linux/poll.h b/include/linux/poll.h
index c08386f..8de6133 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -69,7 +69,7 @@ static inline unsigned long poll_requested_events(const poll_table *p)
static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
{
pt->_qproc = qproc;
- pt->_key = ~0UL; /* all events enabled */
+ pt->_key = ~(unsigned long) POLL_BUSY_LOOP;
}
struct poll_table_entry {
diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h
index 8a358a2..048de8c 100644
--- a/include/net/busy_poll.h
+++ b/include/net/busy_poll.h
@@ -37,6 +37,12 @@ extern unsigned int sysctl_net_busy_poll __read_mostly;
#define LL_FLUSH_FAILED -1
#define LL_FLUSH_BUSY -2
+enum {
+ SK_LL_STATE_EVICT, /* napi id changed or became invalid */
+ SK_LL_STATE_MISS, /* date came through napi poll */
+ SK_LL_STATE_MISS_2, /* data came through napi poll twice in a row */
+};
+
static inline bool net_busy_loop_on(void)
{
return sysctl_net_busy_poll;
@@ -89,6 +95,24 @@ static inline bool busy_loop_timeout(unsigned long end_time)
return time_after(now, end_time);
}
+/* must be called with rcu_read_lock_bh
+ * ops->ndo_ll_poll must not be null
+ */
+static inline bool __napi_busy_loop(const struct net_device_ops *ops,
+ struct napi_struct *napi)
+{
+ int rc = ops->ndo_busy_poll(napi);
+
+ if (rc > 0) {
+ /* local bh are disabled so it is ok to use _BH */
+ NET_ADD_STATS_BH(dev_net(napi->dev),
+ LINUX_MIB_BUSYPOLLRXPACKETS, rc);
+ return true;
+ }
+
+ return false;
+}
+
/* when used in sock_poll() nonblock is known at compile time to be true
* so the loop and end_time will be optimized out
*/
@@ -114,16 +138,11 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock)
goto out;
do {
- rc = ops->ndo_busy_poll(napi);
+ rc = __napi_busy_loop(ops, napi);
if (rc == LL_FLUSH_FAILED)
break; /* permanent failure */
- if (rc > 0)
- /* local bh are disabled so it is ok to use _BH */
- NET_ADD_STATS_BH(sock_net(sk),
- LINUX_MIB_BUSYPOLLRXPACKETS, rc);
-
} while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
!need_resched() && !busy_loop_timeout(end_time));
@@ -133,6 +152,18 @@ out:
return rc;
}
+/* must be called with rcu_read_lock_bh */
+static inline bool napi_id_busy_loop(unsigned int id)
+{
+ struct napi_struct *napi = napi_by_id(id);
+ const struct net_device_ops *ops = napi->dev->netdev_ops;
+
+ if (!napi || !ops->ndo_busy_poll)
+ return false;
+
+ return __napi_busy_loop(ops, napi);
+}
+
/* used in the NIC receive handler to mark the skb */
static inline void skb_mark_napi_id(struct sk_buff *skb,
struct napi_struct *napi)
@@ -140,13 +171,154 @@ static inline void skb_mark_napi_id(struct sk_buff *skb,
skb->napi_id = napi->napi_id;
}
-/* used in the protocol hanlder to propagate the napi_id to the socket */
+/* Used in the protocol handler to propagate the napi_id to the socket.
+ * If the id changes or if we came from napi, record this for epoll.
+ */
static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
{
- sk->sk_napi_id = skb->napi_id;
+ if (unlikely(sk->sk_napi_id != skb->napi_id)) {
+
+ sk->sk_napi_id = skb->napi_id;
+ set_bit(SK_LL_STATE_EVICT, &sk->sk_ll_state);
+
+ /* if the new id is valid, also try to re-insert */
+ if (sk->sk_napi_id)
+ set_bit(SK_LL_STATE_MISS_2, &sk->sk_ll_state);
+
+ /* Lazy detect when the queue needs updating:
+ * we only suspect something needs an update,
+ * if we get here twice in a row in softirq or irq context.
+ * credit: Eliel Louzoun
+ */
+ } else if (unlikely(sk->sk_napi_id && (in_serving_softirq() ||
+ in_irq()))) {
+ if (test_and_set_bit(SK_LL_STATE_MISS, &sk->sk_ll_state))
+ set_bit(SK_LL_STATE_MISS_2, &sk->sk_ll_state);
+ } else {
+ clear_bit(SK_LL_STATE_MISS, &sk->sk_ll_state);
+ clear_bit(SK_LL_STATE_MISS_2, &sk->sk_ll_state);
+ }
+
+}
+
+/* epoll support */
+
+/* The list will typically have 0-2 elements,
+ * so there is no point of doing anything fancier than a simple linked list
+*/
+
+/* used for epoll support */
+struct busy_poll_id_index {
+ struct list_head list;
+ struct rcu_head free_rcu;
+ unsigned int napi_id;
+ struct sock *sk;
+};
+
+/* used in struct eventpoll */
+struct busy_list {
+ struct list_head head;
+};
+
+/* used in eppoll_entry */
+struct busy_state {
+ bool listed;
+};
+
+static inline void init_busy_list(struct busy_list *list)
+{
+ INIT_LIST_HEAD(&list->head);
+}
+
+static inline void warn_busy_list_empty(struct busy_list *list)
+{
+ WARN_ONCE(!list_empty(&list->head),
+ "ep busy poll list not empty on free\n");
+}
+
+static inline void init_busy_state(struct busy_state *state)
+{
+ state->listed = false;
+}
+
+static inline bool epoll_can_busy_loop(struct busy_list *list)
+{
+ return net_busy_loop_on() && !list_empty(&list->head);
+}
+
+/* must be called with the lock protecting list held */
+static inline bool busy_poll_insert_socket(struct busy_list *list,
+ struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ unsigned int id = sk->sk_napi_id;
+ struct busy_poll_id_index *idx;
+
+
+ /* make sure this id is not in the list */
+ list_for_each_entry(idx, &list->head, list)
+ if (idx->napi_id == id)
+ return false;
+
+ idx = kmalloc(sizeof(struct busy_poll_id_index), GFP_ATOMIC);
+
+ if (!idx)
+ return false;
+
+ idx->napi_id = id;
+ idx->sk = sk;
+ list_add_tail(&idx->list, &list->head);
+
+ return true;
+}
+
+/* must be called with the lock protecting list held */
+static inline bool busy_poll_delete_socket(struct busy_list *list,
+ struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ unsigned int id = sk->sk_napi_id;
+ struct busy_poll_id_index *idx;
+
+ list_for_each_entry(idx, &list->head, list)
+ if (idx->sk == sk) {
+ list_del_rcu(&idx->list);
+ kfree_rcu(idx, free_rcu);
+ return true;
+ }
+
+ /* should never reach here */
+ WARN_ONCE(true, "busy_poll_delete_id %x not on list\n", id);
+ return false;
+}
+
+/* must be called with the lock protecting list held */
+static inline void busy_poll_update_socket(struct socket *sock,
+ struct busy_list *list,
+ bool *listed)
+{
+ struct sock *sk = sock->sk;
+ unsigned long *state = &sk->sk_ll_state;
+
+ /* should almost always be false */
+ if (unlikely(*state)) {
+
+ bool evict = test_and_clear_bit(SK_LL_STATE_EVICT, state);
+ bool insert = test_and_clear_bit(SK_LL_STATE_MISS_2, state);
+
+ if (*listed && evict)
+ *listed = !busy_poll_delete_socket(list, sock);
+
+ if (!*listed && insert) {
+ clear_bit(SK_LL_STATE_MISS, state);
+ *listed = busy_poll_insert_socket(list, sock);
+ }
+
+ }
}
#else /* CONFIG_NET_RX_BUSY_POLL */
+
static inline unsigned long net_busy_loop_on(void)
{
return 0;
@@ -162,6 +334,11 @@ static inline bool sk_can_busy_loop(struct sock *sk)
return false;
}
+static inline bool napi_id_busy_loop(unsigned int id)
+{
+ return false;
+}
+
static inline void skb_mark_napi_id(struct sk_buff *skb,
struct napi_struct *napi)
{
@@ -181,5 +358,28 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock)
return false;
}
+struct busy_poll_id_index { };
+
+struct busy_list { };
+
+struct busy_state { };
+
+static inline void init_busy_list(struct busy_list *list)
+{
+}
+
+static inline void warn_busy_list_empty(struct busy_list *list)
+{
+}
+
+static inline void init_busy_state(struct busy_state *state)
+{
+}
+
+static inline bool epoll_can_busy_loop(struct busy_list *list)
+{
+ return false;
+}
+
#endif /* CONFIG_NET_RX_BUSY_POLL */
#endif /* _LINUX_NET_BUSY_POLL_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index e4bbcbf..0537109 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -330,6 +330,7 @@ struct sock {
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int sk_napi_id;
unsigned int sk_ll_usec;
+ unsigned long sk_ll_state;
#endif
atomic_t sk_drops;
int sk_rcvbuf;
^ permalink raw reply related
* Re: [PATCH] netns: unix: only allow to find out unix socket in same net namespace
From: Eric W. Biederman @ 2013-08-21 10:42 UTC (permalink / raw)
To: Gao feng
Cc: systemd-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
libvir-list-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA, Linux Containers,
lxc-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <52146AC2.5070409-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org> writes:
> right now I only take note of the unix socket /run/systemd/private,
> but there may have many similar unix sockets, they can exist in any
> path. the strange problems will still happen.
It could just as easily have been a fifo in the filesystem, and the
result would have been the same.
The network namespace are all about communicating between network
namespaces and that is what was allowed here.
If you don't want a socket or a fifo or any other file to be used by a
container don't give it access to it. It really is that simple.
Eric
^ permalink raw reply
* Re: [RFC PATCH 1/3] of: provide a binding for the 'fixed-link' property
From: Christian Gmeiner @ 2013-08-21 10:55 UTC (permalink / raw)
To: Sascha Hauer
Cc: Thomas Petazzoni, Lior Amsalem, netdev, devicetree-discuss,
Rob Herring, Florian Fainelli, Grant Likely, David S. Miller,
linux-arm-kernel
In-Reply-To: <20130812083746.GM26614@pengutronix.de>
--
Christian Gmeiner, MSc
2013/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
> On Mon, Aug 12, 2013 at 10:16:49AM +0200, Thomas Petazzoni wrote:
>> Dear Sascha Hauer,
>>
>> On Mon, 12 Aug 2013 08:38:06 +0200, Sascha Hauer wrote:
>>
>> > > This patch adds:
>> > >
>> > > * A documentation for the Device Tree property "fixed-link".
>> > >
>> > > * A of_phy_register_fixed_link() OF helper, which provided an OF node
>> > > that contains a "fixed-link" property, registers the corresponding
>> > > fixed PHY.
>> > >
>> > > * Removes the warning on the of_phy_connect_fixed_link() that says
>> > > new drivers should not use it, since Grant Likely indicated that
>> > > this "fixed-link" property is indeed the way to go.
>> > >
>> >
>> > Any progress with this series?
>>
>> I am not sure there really was a consensus yet on what the DT binding
>> looks like. As soon as there is a consensus, I'm definitely willing to
>> make progress on this series.
>>
>> > We have more and more boards here with exactly the same problem as
>> > Thomas has. For reasons stated below I don't like this binding, but
>> > still it would solve my problem.
>>
>> Ok.
>>
>> > > +Example:
>> > > +
>> > > +ethernet@0 {
>> > > + ...
>> > > + fixed-link = <1 1 1000 0 0>;
>> > > + ...
>> > > +};
>> >
>> > I must say I don't like this binding at all for two reasons.
>>
>> As I explained, this binding was chosen for this RFC for two reasons:
>>
>> * It's the binding used on PowerPC platforms to represent fixed links.
>> * It allows to encode all the informations into a single property,
>> which avoids the need for a separate DT node for a "fake PHY", which
>> isn't a representation of the hardware.
>
> The fake phy is avoided by making the other side of the link what it
> really is: An ethernet switch. I'm currently not aware of a situation
> where a fixed link is needed and the other side is not a switch. And I
> can't think of a situation in which the other side of the other side of
> the fixed link really is pure 'virtual', I mean there always must be
> something connected, right?
>
>>
>> > First the positional arguments make it impossible to add optional
>> > arguments to the link.
>> >
>> > Second the other side of the link is most likely a switch. Once this
>> > switch has its own node in the devicetree it seems like having a phandle
>> > to the switch here would be better.
>>
>> So, in other words, what you're suggesting is something like:
>>
>> ethernet@0 {
>> reg = <...>;
>> interrupt = <...>;
>> phy = <&phy0>;
>> phy0: phy@0 {
>> fixed-link;
>> speed = <1000>;
>> full-duplex;
>> ...
>> };
>> };
>
> Yes, this looks good. ePAPR suggests naming the phy property
> "phy-handle" instead of just "phy", but that's just details. In case the
> phy really is a switch the phandle could just point to a i2c device instead
> of the ethernet node.
>
I have here a I.MX6 based board where I have the same issue that the
MAC is directly
connected to a switch. The switch has 5 phys (5 port 100mbt switch)
but the phy5 is not
physically connected to my FEC MAC as my hw guy has chosen to do it without it.
In general it is not a bad idea and I got networking working in u-boot
quite easily.
http://patchwork.ozlabs.org/patch/266558/
Now I am interested in a solution and I think that a fixed-phy is the wrong way.
I like the fixed-link solution more as it models the real world
better. In my example I
do not have any phy, but I have a fixed-link.
&fec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet_1>;
fixed-link = <0 1 100 0 0>;
status = "okay";
};
--
Christian Gmeiner, MSc
^ permalink raw reply
* Re: [PATCH V3] ipv6: handle Redirect ICMP Message with no Redirected Header option
From: Hannes Frederic Sowa @ 2013-08-21 11:17 UTC (permalink / raw)
To: Duan Jiong; +Cc: davem, netdev
In-Reply-To: <521468C4.5020700@cn.fujitsu.com>
On Wed, Aug 21, 2013 at 03:14:12PM +0800, Duan Jiong wrote:
> From: Duan Jiong <duanj.fnst@cn.fujitsu.com>
>
> rfc 4861 says the Redirected Header option is optional, so
> the kernel should not drop the Redirect Message that has no
> Redirected Header option. In this patch, the function
> ip6_redirect_no_header() is introduced to deal with that
> condition.
>
> Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
Sorry for being so picky about local socket delivery before. You were right
all along.
I just tested and reviewed this patch and everything is fine:
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Just out of curiosity, can you tell because of which devices you did
this patch?
Thanks,
Hannes
^ permalink raw reply
* Re: [RFC PATCH 1/3] of: provide a binding for the 'fixed-link' property
From: Florian Fainelli @ 2013-08-21 11:25 UTC (permalink / raw)
To: Christian Gmeiner
Cc: Sascha Hauer, Thomas Petazzoni, Lior Amsalem, netdev,
devicetree-discuss@lists.ozlabs.org, Rob Herring, Grant Likely,
David S. Miller, linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAH9NwWewcDE57g8qgy4aeOeQpfE_RA8hT+cQ9U2_gOFEWKAUDQ@mail.gmail.com>
2013/8/21 Christian Gmeiner <christian.gmeiner@gmail.com>:
> --
> Christian Gmeiner, MSc
>
>
> 2013/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
>> On Mon, Aug 12, 2013 at 10:16:49AM +0200, Thomas Petazzoni wrote:
>>> Dear Sascha Hauer,
>>>
>>> On Mon, 12 Aug 2013 08:38:06 +0200, Sascha Hauer wrote:
>>>
>>> > > This patch adds:
>>> > >
>>> > > * A documentation for the Device Tree property "fixed-link".
>>> > >
>>> > > * A of_phy_register_fixed_link() OF helper, which provided an OF node
>>> > > that contains a "fixed-link" property, registers the corresponding
>>> > > fixed PHY.
>>> > >
>>> > > * Removes the warning on the of_phy_connect_fixed_link() that says
>>> > > new drivers should not use it, since Grant Likely indicated that
>>> > > this "fixed-link" property is indeed the way to go.
>>> > >
>>> >
>>> > Any progress with this series?
>>>
>>> I am not sure there really was a consensus yet on what the DT binding
>>> looks like. As soon as there is a consensus, I'm definitely willing to
>>> make progress on this series.
>>>
>>> > We have more and more boards here with exactly the same problem as
>>> > Thomas has. For reasons stated below I don't like this binding, but
>>> > still it would solve my problem.
>>>
>>> Ok.
>>>
>>> > > +Example:
>>> > > +
>>> > > +ethernet@0 {
>>> > > + ...
>>> > > + fixed-link = <1 1 1000 0 0>;
>>> > > + ...
>>> > > +};
>>> >
>>> > I must say I don't like this binding at all for two reasons.
>>>
>>> As I explained, this binding was chosen for this RFC for two reasons:
>>>
>>> * It's the binding used on PowerPC platforms to represent fixed links.
>>> * It allows to encode all the informations into a single property,
>>> which avoids the need for a separate DT node for a "fake PHY", which
>>> isn't a representation of the hardware.
>>
>> The fake phy is avoided by making the other side of the link what it
>> really is: An ethernet switch. I'm currently not aware of a situation
>> where a fixed link is needed and the other side is not a switch. And I
>> can't think of a situation in which the other side of the other side of
>> the fixed link really is pure 'virtual', I mean there always must be
>> something connected, right?
>>
>>>
>>> > First the positional arguments make it impossible to add optional
>>> > arguments to the link.
>>> >
>>> > Second the other side of the link is most likely a switch. Once this
>>> > switch has its own node in the devicetree it seems like having a phandle
>>> > to the switch here would be better.
>>>
>>> So, in other words, what you're suggesting is something like:
>>>
>>> ethernet@0 {
>>> reg = <...>;
>>> interrupt = <...>;
>>> phy = <&phy0>;
>>> phy0: phy@0 {
>>> fixed-link;
>>> speed = <1000>;
>>> full-duplex;
>>> ...
>>> };
>>> };
>>
>> Yes, this looks good. ePAPR suggests naming the phy property
>> "phy-handle" instead of just "phy", but that's just details. In case the
>> phy really is a switch the phandle could just point to a i2c device instead
>> of the ethernet node.
>>
>
> I have here a I.MX6 based board where I have the same issue that the
> MAC is directly
> connected to a switch. The switch has 5 phys (5 port 100mbt switch)
> but the phy5 is not
> physically connected to my FEC MAC as my hw guy has chosen to do it without it.
> In general it is not a bad idea and I got networking working in u-boot
> quite easily.
This is completely debatable and left to your own use case here.
>
> http://patchwork.ozlabs.org/patch/266558/
>
> Now I am interested in a solution and I think that a fixed-phy is the wrong way.
> I like the fixed-link solution more as it models the real world
> better. In my example I
> do not have any phy, but I have a fixed-link.
>
> &fec {
> pinctrl-names = "default";
> pinctrl-0 = <&pinctrl_enet_1>;
> fixed-link = <0 1 100 0 0>;
> status = "okay";
> };
As was already raised before, this representation has a couple of issues:
- not easily extendable
- not self-explanatory
- it transpires some internal OS concepts such as id/address to the binding
On the other side I prefer the other representation for all of the
opposite reasons above and it actually represents some kind of a PHY
device which is not discoverable via usual means such as MDIO, but
which still needs to be known by the Ethernet MAC to work correctly.
To move forward, we really need a better argumentation than "I do not like it".
--
Florian
^ permalink raw reply
* Re: Re: [PATCH-SR9700] Merge USB 1.1 Ethernet Adapter SR9700 DeviceDriver into the Linux Kernel
From: Joe Perches @ 2013-08-21 11:34 UTC (permalink / raw)
To: liujunliang_ljl
Cc: Francois Romieu, gregkh, sunhecheng, linux-usb, netdev,
linux-kernel
In-Reply-To: <201308211807295009698@163.com>
On Wed, 2013-08-21 at 18:07 +0800, liujunliang_ljl wrote:
> Thanks a lot and I have been fixed all the problems mentioned above. please check the following patch and thanks again.
Just trivial comments below:
> diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
[]
> +static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
> +{
> + usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
> + value, reg, NULL, 0);
> +}
> +
> +static int sr_share_read_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
> +{
[]
> + netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
> + phy, reg, *value, ret);
You have a lot of code that uses inconsistent
indentation. Code in drivers/net and drivers/usb/net
generally prefers to use alignment to parenthesis for
multi-line statements
The first could use
usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
value, reg, NULL, 0);
and the second
netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
phy, reg, *value, ret);
Maximal use of 8 space indentation tabs followed by
minimal spaces.
There are many of these above.
> +static int sr9700_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, u8 *data)
[]
> + for (i = 0; i < eeprom->len / 2; i++)
> + ret = sr_read_eeprom_word(dev, eeprom->offset / 2 + i, &ebuf[i]);
One too many tabs for the second line, a few of these...
[]
> +static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
[]
> + if (rc == 1)
> + return le16_to_cpu(res) | BMSR_LSTATUS;
> + else
> + return le16_to_cpu(res) & ~BMSR_LSTATUS;
The code below the returns here is unreachable.
> +
> + netdev_dbg(dev->net,
> + "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
> + phy_id, loc, le16_to_cpu(res));
> +
> + return le16_to_cpu(res);
> +}
You might try to use scripts/checkpatch.pl --strict if you
care about these. It should flag most of these coding
style inconsistencies.
^ permalink raw reply
* Re: [PATCH net-next] ip6_tunnel: ensure to always have a link local address
From: Bjørn Mork @ 2013-08-21 11:37 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: David Miller, netdev, yoshfuji
In-Reply-To: <5214958F.1080907@6wind.com>
Nicolas Dichtel <nicolas.dichtel@6wind.com> writes:
> Le 21/08/2013 11:02, Bjørn Mork a écrit :
>> Nicolas Dichtel <nicolas.dichtel@6wind.com> writes:
>>> Le 21/08/2013 08:48, David Miller a écrit :
>>>
>>>> Applied, but this brings up an issue I keep noticing.
>>>>
>>>> We talk about eth_random_addr() and "uniqueness" together all the
>>>> time, but the former never implies the latter.
>>>>
>>>> And we're going to run into situations where any conflicts generated
>>>> by this random address generater will cause reall failures.
>>>>
>>>> Therefore we'll have to create a system to prevent them. Probably
>>>> using some simple table that keeps track of the addresses we've
>>>> generated.
>>>>
>>> Ok, I will look at this.
>>
>> Are eth_random_addr() collisions really any different than interfaces
>> having the same address for other reasons?
> I would tend to say yes, it's different.
> It's easy for an administrator to fix a configuration for a physical
> interface, because it's statically configured and there is a limited
> number of interfaces.
>
> For virtual interfaces, they can be dynamically created and destroyed
> by daemons and we can have a lot of interfaces. Hence it could be hard
> to fix them.
If they are created by daemons then it should be up to the daemons to
fix them. Or?
> Trying to avoid these errors at kernel level could be useful.
I strongly believe in fixing configuration issues in userspace if at all
possible. You are setting a new policy every time you implement an
automatic fix or workaround. It is so much better to keep that out of
the kernel, or the next question you will face is "How do I change this
policy? I want the addresses to be assigned by function Y"
I see no reason why the daemon creating these interfaces can't also
fixup any collisions. Or maybe better: If your daemon create millions
of interfaces, and cares about unique addresses, then it should
implement it's own address management.
> I've start to write a patch, and to test it I've just run a simple
> test which generate 1 000 000 of random addresses. I've run it several
> times (maybe not enough ;-)) and I never get a duplicated address...
Well, there are only 2^46 combinations so you are guaranteed to hit a
collision if you just generate 70 368 744 177 665 random addresses :-)
Bjørn
^ permalink raw reply
* Re: [RFC PATCH 1/3] of: provide a binding for the 'fixed-link' property
From: Florian Fainelli @ 2013-08-21 11:46 UTC (permalink / raw)
To: Sascha Hauer
Cc: Thomas Petazzoni, Grant Likely, Rob Herring, David S. Miller,
Lior Amsalem, netdev, devicetree-discuss@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20130812083746.GM26614@pengutronix.de>
2013/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
> On Mon, Aug 12, 2013 at 10:16:49AM +0200, Thomas Petazzoni wrote:
>> Dear Sascha Hauer,
>>
>> On Mon, 12 Aug 2013 08:38:06 +0200, Sascha Hauer wrote:
>>
>> > > This patch adds:
>> > >
>> > > * A documentation for the Device Tree property "fixed-link".
>> > >
>> > > * A of_phy_register_fixed_link() OF helper, which provided an OF node
>> > > that contains a "fixed-link" property, registers the corresponding
>> > > fixed PHY.
>> > >
>> > > * Removes the warning on the of_phy_connect_fixed_link() that says
>> > > new drivers should not use it, since Grant Likely indicated that
>> > > this "fixed-link" property is indeed the way to go.
>> > >
>> >
>> > Any progress with this series?
>>
>> I am not sure there really was a consensus yet on what the DT binding
>> looks like. As soon as there is a consensus, I'm definitely willing to
>> make progress on this series.
>>
>> > We have more and more boards here with exactly the same problem as
>> > Thomas has. For reasons stated below I don't like this binding, but
>> > still it would solve my problem.
>>
>> Ok.
>>
>> > > +Example:
>> > > +
>> > > +ethernet@0 {
>> > > + ...
>> > > + fixed-link = <1 1 1000 0 0>;
>> > > + ...
>> > > +};
>> >
>> > I must say I don't like this binding at all for two reasons.
>>
>> As I explained, this binding was chosen for this RFC for two reasons:
>>
>> * It's the binding used on PowerPC platforms to represent fixed links.
>> * It allows to encode all the informations into a single property,
>> which avoids the need for a separate DT node for a "fake PHY", which
>> isn't a representation of the hardware.
>
> The fake phy is avoided by making the other side of the link what it
> really is: An ethernet switch. I'm currently not aware of a situation
> where a fixed link is needed and the other side is not a switch.
There is such hardware out there, some platforms have a MoCA PHY which
is responsible for the signaling/control path while the data-path can
be connected to a slightly modified Ethernet MAC.
> And I
> can't think of a situation in which the other side of the other side of
> the fixed link really is pure 'virtual', I mean there always must be
> something connected, right?
I agree, there is something on the other end in every case.
>
>>
>> > First the positional arguments make it impossible to add optional
>> > arguments to the link.
>> >
>> > Second the other side of the link is most likely a switch. Once this
>> > switch has its own node in the devicetree it seems like having a phandle
>> > to the switch here would be better.
>>
>> So, in other words, what you're suggesting is something like:
>>
>> ethernet@0 {
>> reg = <...>;
>> interrupt = <...>;
>> phy = <&phy0>;
>> phy0: phy@0 {
>> fixed-link;
>> speed = <1000>;
>> full-duplex;
>> ...
>> };
>> };
>
> Yes, this looks good. ePAPR suggests naming the phy property
> "phy-handle" instead of just "phy", but that's just details. In case the
> phy really is a switch the phandle could just point to a i2c device instead
> of the ethernet node.
I do like this representation better than the existing fixed-link property.
--
Florian
^ permalink raw reply
* Re: ADSL/ATM linklayer tc shaping regression fix commits for stable
From: Jesper Dangaard Brouer @ 2013-08-21 12:03 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: stable, netdev, linux-kernel, bufferbloat-list, David Miller,
Eric Dumazet, Dave Taht
In-Reply-To: <20130820151650.GA18016@kroah.com>
On Tue, 20 Aug 2013 08:16:50 -0700
Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> On Tue, Aug 20, 2013 at 01:26:29PM +0200, Jesper Dangaard Brouer wrote:
[...]
> If there are issues with 3.10, that's a different story.
>
> > Refactor improvements (v3.11-rc1):
> > commit 130d3d68b52 (net_sched: psched_ratecfg_precompute() improvements)
Needed because it fixes the accuracy of the rate calc.
> > The linklayer ATM/ADSL fix, reached 3.11-rc6:
> > commit 8a8e3d84b17 (net_sched: restore "linklayer atm" handling)
Needed because we broke userspace interface.
> David sends me the networking patches for the stable tree, and if he
> thinks these are applicable, then I'll take them.
DaveM, please? What do you want me to do, submit this req/patches somehow?
(Can see that is not currently on your stable queue via:
http://patchwork.ozlabs.org/bundle/davem/stable/?state=*)
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH net-next] ip6_tunnel: ensure to always have a link local address
From: Nicolas Dichtel @ 2013-08-21 12:11 UTC (permalink / raw)
To: Bjørn Mork; +Cc: David Miller, netdev, yoshfuji
In-Reply-To: <8761uz6zra.fsf@nemi.mork.no>
Le 21/08/2013 13:37, Bjørn Mork a écrit :
> Nicolas Dichtel <nicolas.dichtel@6wind.com> writes:
>
>> Le 21/08/2013 11:02, Bjørn Mork a écrit :
>>> Nicolas Dichtel <nicolas.dichtel@6wind.com> writes:
>>>> Le 21/08/2013 08:48, David Miller a écrit :
>>>>
>>>>> Applied, but this brings up an issue I keep noticing.
>>>>>
>>>>> We talk about eth_random_addr() and "uniqueness" together all the
>>>>> time, but the former never implies the latter.
>>>>>
>>>>> And we're going to run into situations where any conflicts generated
>>>>> by this random address generater will cause reall failures.
>>>>>
>>>>> Therefore we'll have to create a system to prevent them. Probably
>>>>> using some simple table that keeps track of the addresses we've
>>>>> generated.
>>>>>
>>>> Ok, I will look at this.
>>>
>>> Are eth_random_addr() collisions really any different than interfaces
>>> having the same address for other reasons?
>> I would tend to say yes, it's different.
>> It's easy for an administrator to fix a configuration for a physical
>> interface, because it's statically configured and there is a limited
>> number of interfaces.
>>
>> For virtual interfaces, they can be dynamically created and destroyed
>> by daemons and we can have a lot of interfaces. Hence it could be hard
>> to fix them.
>
> If they are created by daemons then it should be up to the daemons to
> fix them. Or?
>
>> Trying to avoid these errors at kernel level could be useful.
>
> I strongly believe in fixing configuration issues in userspace if at all
> possible. You are setting a new policy every time you implement an
> automatic fix or workaround. It is so much better to keep that out of
> the kernel, or the next question you will face is "How do I change this
> policy? I want the addresses to be assigned by function Y"
>
> I see no reason why the daemon creating these interfaces can't also
> fixup any collisions. Or maybe better: If your daemon create millions
> of interfaces, and cares about unique addresses, then it should
> implement it's own address management.
Ok ok, you convince me ;-)
I will wait David feedback.
>
>> I've start to write a patch, and to test it I've just run a simple
>> test which generate 1 000 000 of random addresses. I've run it several
>> times (maybe not enough ;-)) and I never get a duplicated address...
>
> Well, there are only 2^46 combinations so you are guaranteed to hit a
> collision if you just generate 70 368 744 177 665 random addresses :-)
Yes, it was just to say that the function which generate these addresses has a
"good" entropy ;-)
^ permalink raw reply
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