* Re: dhclient, checksum and tap
From: Michael S. Tsirkin @ 2010-06-26 21:14 UTC (permalink / raw)
To: David Miller; +Cc: herbert.xu, netdev
In-Reply-To: <20100625.112152.241921019.davem@davemloft.net>
On Fri, Jun 25, 2010 at 11:21:52AM -0700, David Miller wrote:
> From: "Michael S. Tsirkin" <mst@redhat.com>
> Date: Fri, 25 Jun 2010 18:10:08 +0300
>
> > I've been looking at the issue of checksum on
> > dhcp packets: to recap, 8dc4194474159660d7f37c495e3fc3f10d0db8cc
> > added a way for af_packet sockets to get the packet status.
> > Unfortunately not all dhcp clients caught up with
> > this development, so they are still broken
> > when both server and client run on the same host,
> > e.g. with bridge+tap.
> >
> > And of course virtualization adds another way to run
> > old dhcp clients, so userspace virtio net in qemu has
> > a hack to detect DHCP and fill in the checksum.
> > I guess we could add this in vhost, as well.
> >
> > However, one wonders whether the tap driver is a better place
> > for this work-around, that would help all users.
> > Any objections against putting such code in tap?
>
> We added the af_packet status as the migration path to deal with
> this issue in the cleanest manner possible. Putting a new hack
> into the TAP driver works contrary to that goal.
Hmm, problem is, using the af_packets status requires
userspace changes, and so does not help old clients.
And for virt, clients might be running old kernels without this support.
qemu has a hack to make old guests running within qemu work.
I guess I can copy that hack into vhost - a bit ugly as I don't have
access to the original skb there, so I will have to duplcate some logic,
but doable. Is this what you suggest? OTOH if we had the workaround in
tap, this could replace hacks in both vhost and qemu.
--
MST
^ permalink raw reply
* [PATCH 1/2] caif: Kconfig and Makefile fixes
From: sjur.brandeland @ 2010-06-26 21:31 UTC (permalink / raw)
To: davem
Cc: sjurbr, netdev, marcel, daniel.martensson, linus.walleij,
Sjur Braendeland
In-Reply-To: <20100625.211223.232914661.davem@davemloft.net>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Use "depends on" instead of "if" in Kconfig files.
Fixed CAIF debug flag, and removed unnecessary clean-* options.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
David Miller wrote:
>Surrounding a config options with "if XXX" protection is not the
>proper way to protect config options. Simply add a proper "Depends"
>specification to it.
Thanks Dave,
I've updated the existing Kconfig files with "depends on" instead of "if".
drivers/net/caif/Kconfig | 5 +----
drivers/net/caif/Makefile | 10 ++--------
net/caif/Kconfig | 7 ++-----
net/caif/Makefile | 14 ++------------
4 files changed, 7 insertions(+), 29 deletions(-)
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 0b28e01..6f33ee4 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -2,16 +2,13 @@
# CAIF physical drivers
#
-if CAIF
-
comment "CAIF transport drivers"
config CAIF_TTY
tristate "CAIF TTY transport driver"
+ depends on CAIF
default n
---help---
The CAIF TTY transport driver is a Line Discipline (ldisc)
identified as N_CAIF. When this ldisc is opened from user space
it will redirect the TTY's traffic into the CAIF stack.
-
-endif # CAIF
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 52b6d1f..e6d3ca0 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -1,12 +1,6 @@
-ifeq ($(CONFIG_CAIF_DEBUG),1)
-CAIF_DBG_FLAGS := -DDEBUG
+ifeq ($(CONFIG_CAIF_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
endif
-KBUILD_EXTRA_SYMBOLS=net/caif/Module.symvers
-
-ccflags-y := $(CAIF_FLAGS) $(CAIF_DBG_FLAGS)
-clean-dirs:= .tmp_versions
-clean-files:= Module.symvers modules.order *.cmd *~ \
-
# Serial interface
obj-$(CONFIG_CAIF_TTY) += caif_serial.o
diff --git a/net/caif/Kconfig b/net/caif/Kconfig
index ed65178..529750d 100644
--- a/net/caif/Kconfig
+++ b/net/caif/Kconfig
@@ -21,19 +21,18 @@ menuconfig CAIF
See Documentation/networking/caif for a further explanation on how to
use and configure CAIF.
-if CAIF
-
config CAIF_DEBUG
bool "Enable Debug"
+ depends on CAIF
default n
--- help ---
Enable the inclusion of debug code in the CAIF stack.
Be aware that doing this will impact performance.
If unsure say N.
-
config CAIF_NETDEV
tristate "CAIF GPRS Network device"
+ depends on CAIF
default CAIF
---help---
Say Y if you will be using a CAIF based GPRS network device.
@@ -41,5 +40,3 @@ config CAIF_NETDEV
If you select to build it as a built-in then the main CAIF device must
also be a built-in.
If unsure say Y.
-
-endif
diff --git a/net/caif/Makefile b/net/caif/Makefile
index 34852af..f87481f 100644
--- a/net/caif/Makefile
+++ b/net/caif/Makefile
@@ -1,23 +1,13 @@
-ifeq ($(CONFIG_CAIF_DEBUG),1)
-CAIF_DBG_FLAGS := -DDEBUG
+ifeq ($(CONFIG_CAIF_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
endif
-ccflags-y := $(CAIF_FLAGS) $(CAIF_DBG_FLAGS)
-
caif-objs := caif_dev.o \
cfcnfg.o cfmuxl.o cfctrl.o \
cffrml.o cfveil.o cfdbgl.o\
cfserl.o cfdgml.o \
cfrfml.o cfvidl.o cfutill.o \
cfsrvl.o cfpkt_skbuff.o caif_config_util.o
-clean-dirs:= .tmp_versions
-
-clean-files:= \
- Module.symvers \
- modules.order \
- *.cmd \
- *.o \
- *~
obj-$(CONFIG_CAIF) += caif.o
obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o
--
1.6.3.3
^ permalink raw reply related
* [PATCH v4 2/2] caif-driver: Add CAIF-SPI Protocol driver.
From: sjur.brandeland @ 2010-06-26 21:31 UTC (permalink / raw)
To: davem
Cc: sjurbr, netdev, marcel, daniel.martensson, linus.walleij,
Sjur Braendeland
In-Reply-To: <1277587889-17314-1-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
This patch introduces the CAIF SPI Protocol Driver for
CAIF Link Layer.
This driver implements a platform driver to accommodate for a
platform specific SPI device. A general platform driver is not
possible as there are no SPI Slave side Kernel API defined.
A sample CAIF SPI Platform device can be found in
.../Documentation/networking/caif/spi_porting.txt
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
== CHANGES since v1 of CAIF-SPI Protocol driver:
o Using "depends on" instead of "if" in Kconfig files.
o Changed uint8_t to u8 et. al.
o Using netif_rx_ni instead of netif_rx from workqueue.
o Removed CONFIG_* defines from Makefile.
Documentation/networking/caif/spi_porting.txt | 208 ++++++
drivers/net/caif/Kconfig | 20 +
drivers/net/caif/Makefile | 4 +
drivers/net/caif/caif_spi.c | 847 +++++++++++++++++++++++++
drivers/net/caif/caif_spi_slave.c | 252 ++++++++
include/net/caif/caif_spi.h | 153 +++++
6 files changed, 1484 insertions(+), 0 deletions(-)
create mode 100644 Documentation/networking/caif/spi_porting.txt
create mode 100644 drivers/net/caif/caif_spi.c
create mode 100644 drivers/net/caif/caif_spi_slave.c
create mode 100644 include/net/caif/caif_spi.h
diff --git a/Documentation/networking/caif/spi_porting.txt b/Documentation/networking/caif/spi_porting.txt
new file mode 100644
index 0000000..61d7c92
--- /dev/null
+++ b/Documentation/networking/caif/spi_porting.txt
@@ -0,0 +1,208 @@
+- CAIF SPI porting -
+
+- CAIF SPI basics:
+
+Running CAIF over SPI needs some extra setup, owing to the nature of SPI.
+Two extra GPIOs have been added in order to negotiate the transfers
+ between the master and the slave. The minimum requirement for running
+CAIF over SPI is a SPI slave chip and two GPIOs (more details below).
+Please note that running as a slave implies that you need to keep up
+with the master clock. An overrun or underrun event is fatal.
+
+- CAIF SPI framework:
+
+To make porting as easy as possible, the CAIF SPI has been divided in
+two parts. The first part (called the interface part) deals with all
+generic functionality such as length framing, SPI frame negotiation
+and SPI frame delivery and transmission. The other part is the CAIF
+SPI slave device part, which is the module that you have to write if
+you want to run SPI CAIF on a new hardware. This part takes care of
+the physical hardware, both with regard to SPI and to GPIOs.
+
+- Implementing a CAIF SPI device:
+
+ - Functionality provided by the CAIF SPI slave device:
+
+ In order to implement a SPI device you will, as a minimum,
+ need to implement the following
+ functions:
+
+ int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev):
+
+ This function is called by the CAIF SPI interface to give
+ you a chance to set up your hardware to be ready to receive
+ a stream of data from the master. The xfer structure contains
+ both physical and logical adresses, as well as the total length
+ of the transfer in both directions.The dev parameter can be used
+ to map to different CAIF SPI slave devices.
+
+ void (*sig_xfer) (bool xfer, struct cfspi_dev *dev):
+
+ This function is called by the CAIF SPI interface when the output
+ (SPI_INT) GPIO needs to change state. The boolean value of the xfer
+ variable indicates whether the GPIO should be asserted (HIGH) or
+ deasserted (LOW). The dev parameter can be used to map to different CAIF
+ SPI slave devices.
+
+ - Functionality provided by the CAIF SPI interface:
+
+ void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
+
+ This function is called by the CAIF SPI slave device in order to
+ signal a change of state of the input GPIO (SS) to the interface.
+ Only active edges are mandatory to be reported.
+ This function can be called from IRQ context (recommended in order
+ not to introduce latency). The ifc parameter should be the pointer
+ returned from the platform probe function in the SPI device structure.
+
+ void (*xfer_done_cb) (struct cfspi_ifc *ifc);
+
+ This function is called by the CAIF SPI slave device in order to
+ report that a transfer is completed. This function should only be
+ called once both the transmission and the reception are completed.
+ This function can be called from IRQ context (recommended in order
+ not to introduce latency). The ifc parameter should be the pointer
+ returned from the platform probe function in the SPI device structure.
+
+ - Connecting the bits and pieces:
+
+ - Filling in the SPI slave device structure:
+
+ Connect the necessary callback functions.
+ Indicate clock speed (used to calculate toggle delays).
+ Chose a suitable name (helps debugging if you use several CAIF
+ SPI slave devices).
+ Assign your private data (can be used to map to your structure).
+
+ - Filling in the SPI slave platform device structure:
+ Add name of driver to connect to ("cfspi_sspi").
+ Assign the SPI slave device structure as platform data.
+
+- Padding:
+
+In order to optimize throughput, a number of SPI padding options are provided.
+Padding can be enabled independently for uplink and downlink transfers.
+Padding can be enabled for the head, the tail and for the total frame size.
+The padding needs to be correctly configured on both sides of the link.
+The padding can be changed via module parameters in cfspi_sspi.c or via
+the sysfs directory of the cfspi_sspi driver (before device registration).
+
+- CAIF SPI device template:
+
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
+ * License terms: GNU General Public License (GPL), version 2.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <net/caif/caif_spi.h>
+
+MODULE_LICENSE("GPL");
+
+struct sspi_struct {
+ struct cfspi_dev sdev;
+ struct cfspi_xfer *xfer;
+};
+
+static struct sspi_struct slave;
+static struct platform_device slave_device;
+
+static irqreturn_t sspi_irq(int irq, void *arg)
+{
+ /* You only need to trigger on an edge to the active state of the
+ * SS signal. Once a edge is detected, the ss_cb() function should be
+ * called with the parameter assert set to true. It is OK
+ * (and even advised) to call the ss_cb() function in IRQ context in
+ * order not to add any delay. */
+
+ return IRQ_HANDLED;
+}
+
+static void sspi_complete(void *context)
+{
+ /* Normally the DMA or the SPI framework will call you back
+ * in something similar to this. The only thing you need to
+ * do is to call the xfer_done_cb() function, providing the pointer
+ * to the CAIF SPI interface. It is OK to call this function
+ * from IRQ context. */
+}
+
+static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev)
+{
+ /* Store transfer info. For a normal implementation you should
+ * set up your DMA here and make sure that you are ready to
+ * receive the data from the master SPI. */
+
+ struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
+
+ sspi->xfer = xfer;
+
+ return 0;
+}
+
+void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
+{
+ /* If xfer is true then you should assert the SPI_INT to indicate to
+ * the master that you are ready to recieve the data from the master
+ * SPI. If xfer is false then you should de-assert SPI_INT to indicate
+ * that the transfer is done.
+ */
+
+ struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
+}
+
+static void sspi_release(struct device *dev)
+{
+ /*
+ * Here you should release your SPI device resources.
+ */
+}
+
+static int __init sspi_init(void)
+{
+ /* Here you should initialize your SPI device by providing the
+ * necessary functions, clock speed, name and private data. Once
+ * done, you can register your device with the
+ * platform_device_register() function. This function will return
+ * with the CAIF SPI interface initialized. This is probably also
+ * the place where you should set up your GPIOs, interrupts and SPI
+ * resources. */
+
+ int res = 0;
+
+ /* Initialize slave device. */
+ slave.sdev.init_xfer = sspi_init_xfer;
+ slave.sdev.sig_xfer = sspi_sig_xfer;
+ slave.sdev.clk_mhz = 13;
+ slave.sdev.priv = &slave;
+ slave.sdev.name = "spi_sspi";
+ slave_device.dev.release = sspi_release;
+
+ /* Initialize platform device. */
+ slave_device.name = "cfspi_sspi";
+ slave_device.dev.platform_data = &slave.sdev;
+
+ /* Register platform device. */
+ res = platform_device_register(&slave_device);
+ if (res) {
+ printk(KERN_WARNING "sspi_init: failed to register dev.\n");
+ return -ENODEV;
+ }
+
+ return res;
+}
+
+static void __exit sspi_exit(void)
+{
+ platform_device_del(&slave_device);
+}
+
+module_init(sspi_init);
+module_exit(sspi_exit);
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 6f33ee4..cfbe675 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -12,3 +12,23 @@ config CAIF_TTY
The CAIF TTY transport driver is a Line Discipline (ldisc)
identified as N_CAIF. When this ldisc is opened from user space
it will redirect the TTY's traffic into the CAIF stack.
+
+config CAIF_SPI_SLAVE
+ tristate "CAIF SPI transport driver for slave interface"
+ depends on CAIF
+ default n
+ ---help---
+ The CAIF Link layer SPI Protocol driver for Slave SPI interface.
+ This driver implements a platform driver to accommodate for a
+ platform specific SPI device. A sample CAIF SPI Platform device is
+ provided in Documentation/networking/caif/spi_porting.txt
+
+config CAIF_SPI_SYNC
+ bool "Next command and length in start of frame"
+ depends on CAIF_SPI_SLAVE
+ default n
+ ---help---
+ Putting the next command and length in the start of the frame can
+ help to synchronize to the next transfer in case of over or under-runs.
+ This option also needs to be enabled on the modem.
+
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index e6d3ca0..3a11d61 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -4,3 +4,7 @@ endif
# Serial interface
obj-$(CONFIG_CAIF_TTY) += caif_serial.o
+
+# SPI slave physical interfaces module
+cfspi_slave-objs := caif_spi.o caif_spi_slave.o
+obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
new file mode 100644
index 0000000..03049e8
--- /dev/null
+++ b/drivers/net/caif/caif_spi.c
@@ -0,0 +1,847 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <linux/if_arp.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_spi.h>
+
+#ifndef CONFIG_CAIF_SPI_SYNC
+#define FLAVOR "Flavour: Vanilla.\n"
+#else
+#define FLAVOR "Flavour: Master CMD&LEN at start.\n"
+#endif /* CONFIG_CAIF_SPI_SYNC */
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>");
+MODULE_DESCRIPTION("CAIF SPI driver");
+
+static int spi_loop;
+module_param(spi_loop, bool, S_IRUGO);
+MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode.");
+
+/* SPI frame alignment. */
+module_param(spi_frm_align, int, S_IRUGO);
+MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment.");
+
+/* SPI padding options. */
+module_param(spi_up_head_align, int, S_IRUGO);
+MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment.");
+
+module_param(spi_up_tail_align, int, S_IRUGO);
+MODULE_PARM_DESC(spi_up_tail_align, "SPI uplink tail alignment.");
+
+module_param(spi_down_head_align, int, S_IRUGO);
+MODULE_PARM_DESC(spi_down_head_align, "SPI downlink head alignment.");
+
+module_param(spi_down_tail_align, int, S_IRUGO);
+MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment.");
+
+#ifdef CONFIG_ARM
+#define BYTE_HEX_FMT "%02X"
+#else
+#define BYTE_HEX_FMT "%02hhX"
+#endif
+
+#define SPI_MAX_PAYLOAD_SIZE 4096
+/*
+ * Threshold values for the SPI packet queue. Flowcontrol will be asserted
+ * when the number of packets exceeds HIGH_WATER_MARK. It will not be
+ * deasserted before the number of packets drops below LOW_WATER_MARK.
+ */
+#define LOW_WATER_MARK 100
+#define HIGH_WATER_MARK (LOW_WATER_MARK*5)
+
+#ifdef CONFIG_UML
+
+/*
+ * We sometimes use UML for debugging, but it cannot handle
+ * dma_alloc_coherent so we have to wrap it.
+ */
+static inline void *dma_alloc(dma_addr_t *daddr)
+{
+ return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL);
+}
+
+static inline void dma_free(void *cpu_addr, dma_addr_t handle)
+{
+ kfree(cpu_addr);
+}
+
+#else
+
+static inline void *dma_alloc(dma_addr_t *daddr)
+{
+ return dma_alloc_coherent(NULL, SPI_DMA_BUF_LEN, daddr,
+ GFP_KERNEL);
+}
+
+static inline void dma_free(void *cpu_addr, dma_addr_t handle)
+{
+ dma_free_coherent(NULL, SPI_DMA_BUF_LEN, cpu_addr, handle);
+}
+#endif /* CONFIG_UML */
+
+#ifdef CONFIG_DEBUG_FS
+
+#define DEBUGFS_BUF_SIZE 4096
+
+static struct dentry *dbgfs_root;
+
+static inline void driver_debugfs_create(void)
+{
+ dbgfs_root = debugfs_create_dir(cfspi_spi_driver.driver.name, NULL);
+}
+
+static inline void driver_debugfs_remove(void)
+{
+ debugfs_remove(dbgfs_root);
+}
+
+static inline void dev_debugfs_rem(struct cfspi *cfspi)
+{
+ debugfs_remove(cfspi->dbgfs_frame);
+ debugfs_remove(cfspi->dbgfs_state);
+ debugfs_remove(cfspi->dbgfs_dir);
+}
+
+static int dbgfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int len = 0;
+ ssize_t size;
+ struct cfspi *cfspi = (struct cfspi *)file->private_data;
+
+ buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return 0;
+
+ /* Print out debug information. */
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "CAIF SPI debug information:\n");
+
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), FLAVOR);
+
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "STATE: %d\n", cfspi->dbg_state);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Previous CMD: 0x%x\n", cfspi->pcmd);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Current CMD: 0x%x\n", cfspi->cmd);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Previous TX len: %d\n", cfspi->tx_ppck_len);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Previous RX len: %d\n", cfspi->rx_ppck_len);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Current TX len: %d\n", cfspi->tx_cpck_len);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Current RX len: %d\n", cfspi->rx_cpck_len);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Next TX len: %d\n", cfspi->tx_npck_len);
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Next RX len: %d\n", cfspi->rx_npck_len);
+
+ size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return size;
+}
+
+static ssize_t print_frame(char *buf, size_t size, char *frm,
+ size_t count, size_t cut)
+{
+ int len = 0;
+ int i;
+ for (i = 0; i < count; i++) {
+ len += snprintf((buf + len), (size - len),
+ "[0x" BYTE_HEX_FMT "]",
+ frm[i]);
+ if ((i == cut) && (count > (cut * 2))) {
+ /* Fast forward. */
+ i = count - cut;
+ len += snprintf((buf + len), (size - len),
+ "--- %u bytes skipped ---\n",
+ (int)(count - (cut * 2)));
+ }
+
+ if ((!(i % 10)) && i) {
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "\n");
+ }
+ }
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), "\n");
+ return len;
+}
+
+static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int len = 0;
+ ssize_t size;
+ struct cfspi *cfspi;
+
+ cfspi = (struct cfspi *)file->private_data;
+ buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return 0;
+
+ /* Print out debug information. */
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Current frame:\n");
+
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Tx data (Len: %d):\n", cfspi->tx_cpck_len);
+
+ len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
+ cfspi->xfer.va_tx,
+ (cfspi->tx_cpck_len + SPI_CMD_SZ), 100);
+
+ len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
+ "Rx data (Len: %d):\n", cfspi->rx_cpck_len);
+
+ len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
+ cfspi->xfer.va_rx,
+ (cfspi->rx_cpck_len + SPI_CMD_SZ), 100);
+
+ size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return size;
+}
+
+static const struct file_operations dbgfs_state_fops = {
+ .open = dbgfs_open,
+ .read = dbgfs_state,
+ .owner = THIS_MODULE
+};
+
+static const struct file_operations dbgfs_frame_fops = {
+ .open = dbgfs_open,
+ .read = dbgfs_frame,
+ .owner = THIS_MODULE
+};
+
+static inline void dev_debugfs_add(struct cfspi *cfspi)
+{
+ cfspi->dbgfs_dir = debugfs_create_dir(cfspi->pdev->name, dbgfs_root);
+ cfspi->dbgfs_state = debugfs_create_file("state", S_IRUGO,
+ cfspi->dbgfs_dir, cfspi,
+ &dbgfs_state_fops);
+ cfspi->dbgfs_frame = debugfs_create_file("frame", S_IRUGO,
+ cfspi->dbgfs_dir, cfspi,
+ &dbgfs_frame_fops);
+}
+
+inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
+{
+ cfspi->dbg_state = state;
+};
+#else
+
+static inline void driver_debugfs_create(void)
+{
+}
+
+static inline void driver_debugfs_remove(void)
+{
+}
+
+static inline void dev_debugfs_add(struct cfspi *cfspi)
+{
+}
+
+static inline void dev_debugfs_rem(struct cfspi *cfspi)
+{
+}
+
+inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static LIST_HEAD(cfspi_list);
+static spinlock_t cfspi_list_lock;
+
+/* SPI uplink head alignment. */
+static ssize_t show_up_head_align(struct device_driver *driver, char *buf)
+{
+ return sprintf(buf, "%d\n", spi_up_head_align);
+}
+
+static DRIVER_ATTR(up_head_align, S_IRUSR, show_up_head_align, NULL);
+
+/* SPI uplink tail alignment. */
+static ssize_t show_up_tail_align(struct device_driver *driver, char *buf)
+{
+ return sprintf(buf, "%d\n", spi_up_tail_align);
+}
+
+static DRIVER_ATTR(up_tail_align, S_IRUSR, show_up_tail_align, NULL);
+
+/* SPI downlink head alignment. */
+static ssize_t show_down_head_align(struct device_driver *driver, char *buf)
+{
+ return sprintf(buf, "%d\n", spi_down_head_align);
+}
+
+static DRIVER_ATTR(down_head_align, S_IRUSR, show_down_head_align, NULL);
+
+/* SPI downlink tail alignment. */
+static ssize_t show_down_tail_align(struct device_driver *driver, char *buf)
+{
+ return sprintf(buf, "%d\n", spi_down_tail_align);
+}
+
+static DRIVER_ATTR(down_tail_align, S_IRUSR, show_down_tail_align, NULL);
+
+/* SPI frame alignment. */
+static ssize_t show_frame_align(struct device_driver *driver, char *buf)
+{
+ return sprintf(buf, "%d\n", spi_frm_align);
+}
+
+static DRIVER_ATTR(frame_align, S_IRUSR, show_frame_align, NULL);
+
+int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len)
+{
+ u8 *dst = buf;
+ caif_assert(buf);
+
+ do {
+ struct sk_buff *skb;
+ struct caif_payload_info *info;
+ int spad = 0;
+ int epad;
+
+ skb = skb_dequeue(&cfspi->chead);
+ if (!skb)
+ break;
+
+ /*
+ * Calculate length of frame including SPI padding.
+ * The payload position is found in the control buffer.
+ */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ /*
+ * Compute head offset i.e. number of bytes to add to
+ * get the start of the payload aligned.
+ */
+ if (spi_up_head_align) {
+ spad = 1 + ((info->hdr_len + 1) & spi_up_head_align);
+ *dst = (u8)(spad - 1);
+ dst += spad;
+ }
+
+ /* Copy in CAIF frame. */
+ skb_copy_bits(skb, 0, dst, skb->len);
+ dst += skb->len;
+ cfspi->ndev->stats.tx_packets++;
+ cfspi->ndev->stats.tx_bytes += skb->len;
+
+ /*
+ * Compute tail offset i.e. number of bytes to add to
+ * get the complete CAIF frame aligned.
+ */
+ epad = (skb->len + spad) & spi_up_tail_align;
+ dst += epad;
+
+ dev_kfree_skb(skb);
+
+ } while ((dst - buf) < len);
+
+ return dst - buf;
+}
+
+int cfspi_xmitlen(struct cfspi *cfspi)
+{
+ struct sk_buff *skb = NULL;
+ int frm_len = 0;
+ int pkts = 0;
+
+ /*
+ * Decommit previously commited frames.
+ * skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead)
+ */
+ while (skb_peek(&cfspi->chead)) {
+ skb = skb_dequeue_tail(&cfspi->chead);
+ skb_queue_head(&cfspi->qhead, skb);
+ }
+
+ do {
+ struct caif_payload_info *info = NULL;
+ int spad = 0;
+ int epad = 0;
+
+ skb = skb_dequeue(&cfspi->qhead);
+ if (!skb)
+ break;
+
+ /*
+ * Calculate length of frame including SPI padding.
+ * The payload position is found in the control buffer.
+ */
+ info = (struct caif_payload_info *)&skb->cb;
+
+ /*
+ * Compute head offset i.e. number of bytes to add to
+ * get the start of the payload aligned.
+ */
+ if (spi_up_head_align)
+ spad = 1 + ((info->hdr_len + 1) & spi_up_head_align);
+
+ /*
+ * Compute tail offset i.e. number of bytes to add to
+ * get the complete CAIF frame aligned.
+ */
+ epad = (skb->len + spad) & spi_up_tail_align;
+
+ if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) {
+ skb_queue_tail(&cfspi->chead, skb);
+ pkts++;
+ frm_len += skb->len + spad + epad;
+ } else {
+ /* Put back packet. */
+ skb_queue_head(&cfspi->qhead, skb);
+ }
+ } while (pkts <= CAIF_MAX_SPI_PKTS);
+
+ /*
+ * Send flow on if previously sent flow off
+ * and now go below the low water mark
+ */
+ if (cfspi->flow_off_sent && cfspi->qhead.qlen < cfspi->qd_low_mark &&
+ cfspi->cfdev.flowctrl) {
+ cfspi->flow_off_sent = 0;
+ cfspi->cfdev.flowctrl(cfspi->ndev, 1);
+ }
+
+ return frm_len;
+}
+
+static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc)
+{
+ struct cfspi *cfspi = (struct cfspi *)ifc->priv;
+
+ if (!in_interrupt())
+ spin_lock(&cfspi->lock);
+ if (assert) {
+ set_bit(SPI_SS_ON, &cfspi->state);
+ set_bit(SPI_XFER, &cfspi->state);
+ } else {
+ set_bit(SPI_SS_OFF, &cfspi->state);
+ }
+ if (!in_interrupt())
+ spin_unlock(&cfspi->lock);
+
+ /* Wake up the xfer thread. */
+ wake_up_interruptible(&cfspi->wait);
+}
+
+static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc)
+{
+ struct cfspi *cfspi = (struct cfspi *)ifc->priv;
+
+ /* Transfer done, complete work queue */
+ complete(&cfspi->comp);
+}
+
+static int cfspi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct cfspi *cfspi = NULL;
+ unsigned long flags;
+ if (!dev)
+ return -EINVAL;
+
+ cfspi = netdev_priv(dev);
+
+ skb_queue_tail(&cfspi->qhead, skb);
+
+ spin_lock_irqsave(&cfspi->lock, flags);
+ if (!test_and_set_bit(SPI_XFER, &cfspi->state)) {
+ /* Wake up xfer thread. */
+ wake_up_interruptible(&cfspi->wait);
+ }
+ spin_unlock_irqrestore(&cfspi->lock, flags);
+
+ /* Send flow off if number of bytes is above high water mark */
+ if (!cfspi->flow_off_sent &&
+ cfspi->qhead.qlen > cfspi->qd_high_mark &&
+ cfspi->cfdev.flowctrl) {
+ cfspi->flow_off_sent = 1;
+ cfspi->cfdev.flowctrl(cfspi->ndev, 0);
+ }
+
+ return 0;
+}
+
+int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len)
+{
+ u8 *src = buf;
+
+ caif_assert(buf != NULL);
+
+ do {
+ int res;
+ struct sk_buff *skb = NULL;
+ int spad = 0;
+ int epad = 0;
+ u8 *dst = NULL;
+ int pkt_len = 0;
+
+ /*
+ * Compute head offset i.e. number of bytes added to
+ * get the start of the payload aligned.
+ */
+ if (spi_down_head_align) {
+ spad = 1 + *src;
+ src += spad;
+ }
+
+ /* Read length of CAIF frame (little endian). */
+ pkt_len = *src;
+ pkt_len |= ((*(src+1)) << 8) & 0xFF00;
+ pkt_len += 2; /* Add FCS fields. */
+
+ /* Get a suitable caif packet and copy in data. */
+
+ skb = netdev_alloc_skb(cfspi->ndev, pkt_len + 1);
+ caif_assert(skb != NULL);
+
+ dst = skb_put(skb, pkt_len);
+ memcpy(dst, src, pkt_len);
+ src += pkt_len;
+
+ skb->protocol = htons(ETH_P_CAIF);
+ skb_reset_mac_header(skb);
+ skb->dev = cfspi->ndev;
+
+ /*
+ * Push received packet up the stack.
+ */
+ if (!spi_loop)
+ res = netif_rx_ni(skb);
+ else
+ res = cfspi_xmit(skb, cfspi->ndev);
+
+ if (!res) {
+ cfspi->ndev->stats.rx_packets++;
+ cfspi->ndev->stats.rx_bytes += pkt_len;
+ } else
+ cfspi->ndev->stats.rx_dropped++;
+
+ /*
+ * Compute tail offset i.e. number of bytes added to
+ * get the complete CAIF frame aligned.
+ */
+ epad = (pkt_len + spad) & spi_down_tail_align;
+ src += epad;
+ } while ((src - buf) < len);
+
+ return src - buf;
+}
+
+static int cfspi_open(struct net_device *dev)
+{
+ netif_wake_queue(dev);
+ return 0;
+}
+
+static int cfspi_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ return 0;
+}
+static const struct net_device_ops cfspi_ops = {
+ .ndo_open = cfspi_open,
+ .ndo_stop = cfspi_close,
+ .ndo_start_xmit = cfspi_xmit
+};
+
+static void cfspi_setup(struct net_device *dev)
+{
+ struct cfspi *cfspi = netdev_priv(dev);
+ dev->features = 0;
+ dev->netdev_ops = &cfspi_ops;
+ dev->type = ARPHRD_CAIF;
+ dev->flags = IFF_NOARP | IFF_POINTOPOINT;
+ dev->tx_queue_len = 0;
+ dev->mtu = SPI_MAX_PAYLOAD_SIZE;
+ dev->destructor = free_netdev;
+ skb_queue_head_init(&cfspi->qhead);
+ skb_queue_head_init(&cfspi->chead);
+ cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
+ cfspi->cfdev.use_frag = false;
+ cfspi->cfdev.use_stx = false;
+ cfspi->cfdev.use_fcs = false;
+ cfspi->ndev = dev;
+}
+
+int cfspi_spi_probe(struct platform_device *pdev)
+{
+ struct cfspi *cfspi = NULL;
+ struct net_device *ndev;
+ struct cfspi_dev *dev;
+ int res;
+ dev = (struct cfspi_dev *)pdev->dev.platform_data;
+
+ ndev = alloc_netdev(sizeof(struct cfspi),
+ "cfspi%d", cfspi_setup);
+ if (!dev)
+ return -ENODEV;
+
+ cfspi = netdev_priv(ndev);
+ netif_stop_queue(ndev);
+ cfspi->ndev = ndev;
+ cfspi->pdev = pdev;
+
+ /* Set flow info */
+ cfspi->flow_off_sent = 0;
+ cfspi->qd_low_mark = LOW_WATER_MARK;
+ cfspi->qd_high_mark = HIGH_WATER_MARK;
+
+ /* Assign the SPI device. */
+ cfspi->dev = dev;
+ /* Assign the device ifc to this SPI interface. */
+ dev->ifc = &cfspi->ifc;
+
+ /* Allocate DMA buffers. */
+ cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
+ if (!cfspi->xfer.va_tx) {
+ printk(KERN_WARNING
+ "CFSPI: failed to allocate dma TX buffer.\n");
+ res = -ENODEV;
+ goto err_dma_alloc_tx;
+ }
+
+ cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
+
+ if (!cfspi->xfer.va_rx) {
+ printk(KERN_WARNING
+ "CFSPI: failed to allocate dma TX buffer.\n");
+ res = -ENODEV;
+ goto err_dma_alloc_rx;
+ }
+
+ /* Initialize the work queue. */
+ INIT_WORK(&cfspi->work, cfspi_xfer);
+
+ /* Initialize spin locks. */
+ spin_lock_init(&cfspi->lock);
+
+ /* Initialize flow control state. */
+ cfspi->flow_stop = false;
+
+ /* Initialize wait queue. */
+ init_waitqueue_head(&cfspi->wait);
+
+ /* Create work thread. */
+ cfspi->wq = create_singlethread_workqueue(dev->name);
+ if (!cfspi->wq) {
+ printk(KERN_WARNING "CFSPI: failed to create work queue.\n");
+ res = -ENODEV;
+ goto err_create_wq;
+ }
+
+ /* Initialize work queue. */
+ init_completion(&cfspi->comp);
+
+ /* Create debugfs entries. */
+ dev_debugfs_add(cfspi);
+
+ /* Set up the ifc. */
+ cfspi->ifc.ss_cb = cfspi_ss_cb;
+ cfspi->ifc.xfer_done_cb = cfspi_xfer_done_cb;
+ cfspi->ifc.priv = cfspi;
+
+ /* Add CAIF SPI device to list. */
+ spin_lock(&cfspi_list_lock);
+ list_add_tail(&cfspi->list, &cfspi_list);
+ spin_unlock(&cfspi_list_lock);
+
+ /* Schedule the work queue. */
+ queue_work(cfspi->wq, &cfspi->work);
+
+ /* Register network device. */
+ res = register_netdev(ndev);
+ if (res) {
+ printk(KERN_ERR "CFSPI: Reg. error: %d.\n", res);
+ goto err_net_reg;
+ }
+ return res;
+
+ err_net_reg:
+ dev_debugfs_rem(cfspi);
+ set_bit(SPI_TERMINATE, &cfspi->state);
+ wake_up_interruptible(&cfspi->wait);
+ destroy_workqueue(cfspi->wq);
+ err_create_wq:
+ dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
+ err_dma_alloc_rx:
+ dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
+ err_dma_alloc_tx:
+ free_netdev(ndev);
+
+ return res;
+}
+
+int cfspi_spi_remove(struct platform_device *pdev)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfspi *cfspi = NULL;
+ struct cfspi_dev *dev;
+
+ dev = (struct cfspi_dev *)pdev->dev.platform_data;
+ spin_lock(&cfspi_list_lock);
+ list_for_each_safe(list_node, n, &cfspi_list) {
+ cfspi = list_entry(list_node, struct cfspi, list);
+ /* Find the corresponding device. */
+ if (cfspi->dev == dev) {
+ /* Remove from list. */
+ list_del(list_node);
+ /* Free DMA buffers. */
+ dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
+ dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
+ set_bit(SPI_TERMINATE, &cfspi->state);
+ wake_up_interruptible(&cfspi->wait);
+ destroy_workqueue(cfspi->wq);
+ /* Destroy debugfs directory and files. */
+ dev_debugfs_rem(cfspi);
+ unregister_netdev(cfspi->ndev);
+ spin_unlock(&cfspi_list_lock);
+ return 0;
+ }
+ }
+ spin_unlock(&cfspi_list_lock);
+ return -ENODEV;
+}
+
+static void __exit cfspi_exit_module(void)
+{
+ struct list_head *list_node;
+ struct list_head *n;
+ struct cfspi *cfspi = NULL;
+
+ list_for_each_safe(list_node, n, &cfspi_list) {
+ cfspi = list_entry(list_node, struct cfspi, list);
+ platform_device_unregister(cfspi->pdev);
+ }
+
+ /* Destroy sysfs files. */
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_head_align);
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_tail_align);
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_head_align);
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_tail_align);
+ driver_remove_file(&cfspi_spi_driver.driver, &driver_attr_frame_align);
+ /* Unregister platform driver. */
+ platform_driver_unregister(&cfspi_spi_driver);
+ /* Destroy debugfs root directory. */
+ driver_debugfs_remove();
+}
+
+static int __init cfspi_init_module(void)
+{
+ int result;
+
+ /* Initialize spin lock. */
+ spin_lock_init(&cfspi_list_lock);
+
+ /* Register platform driver. */
+ result = platform_driver_register(&cfspi_spi_driver);
+ if (result) {
+ printk(KERN_ERR "Could not register platform SPI driver.\n");
+ goto err_dev_register;
+ }
+
+ /* Create sysfs files. */
+ result =
+ driver_create_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_head_align);
+ if (result) {
+ printk(KERN_ERR "Sysfs creation failed 1.\n");
+ goto err_create_up_head_align;
+ }
+
+ result =
+ driver_create_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_tail_align);
+ if (result) {
+ printk(KERN_ERR "Sysfs creation failed 2.\n");
+ goto err_create_up_tail_align;
+ }
+
+ result =
+ driver_create_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_head_align);
+ if (result) {
+ printk(KERN_ERR "Sysfs creation failed 3.\n");
+ goto err_create_down_head_align;
+ }
+
+ result =
+ driver_create_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_tail_align);
+ if (result) {
+ printk(KERN_ERR "Sysfs creation failed 4.\n");
+ goto err_create_down_tail_align;
+ }
+
+ result =
+ driver_create_file(&cfspi_spi_driver.driver,
+ &driver_attr_frame_align);
+ if (result) {
+ printk(KERN_ERR "Sysfs creation failed 5.\n");
+ goto err_create_frame_align;
+ }
+ driver_debugfs_create();
+ return result;
+
+ err_create_frame_align:
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_tail_align);
+ err_create_down_tail_align:
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_down_head_align);
+ err_create_down_head_align:
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_tail_align);
+ err_create_up_tail_align:
+ driver_remove_file(&cfspi_spi_driver.driver,
+ &driver_attr_up_head_align);
+ err_create_up_head_align:
+ err_dev_register:
+ return result;
+}
+
+module_init(cfspi_init_module);
+module_exit(cfspi_exit_module);
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
new file mode 100644
index 0000000..077ccf8
--- /dev/null
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/semaphore.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <net/caif/caif_spi.h>
+
+#ifndef CONFIG_CAIF_SPI_SYNC
+#define SPI_DATA_POS SPI_CMD_SZ
+static inline int forward_to_spi_cmd(struct cfspi *cfspi)
+{
+ return cfspi->rx_cpck_len;
+}
+#else
+#define SPI_DATA_POS 0
+static inline int forward_to_spi_cmd(struct cfspi *cfspi)
+{
+ return 0;
+}
+#endif
+
+int spi_frm_align = 2;
+int spi_up_head_align = 1;
+int spi_up_tail_align;
+int spi_down_head_align = 3;
+int spi_down_tail_align = 1;
+
+#ifdef CONFIG_DEBUG_FS
+static inline void debugfs_store_prev(struct cfspi *cfspi)
+{
+ /* Store previous command for debugging reasons.*/
+ cfspi->pcmd = cfspi->cmd;
+ /* Store previous transfer. */
+ cfspi->tx_ppck_len = cfspi->tx_cpck_len;
+ cfspi->rx_ppck_len = cfspi->rx_cpck_len;
+}
+#else
+static inline void debugfs_store_prev(struct cfspi *cfspi)
+{
+}
+#endif
+
+void cfspi_xfer(struct work_struct *work)
+{
+ struct cfspi *cfspi;
+ u8 *ptr = NULL;
+ unsigned long flags;
+ int ret;
+ cfspi = container_of(work, struct cfspi, work);
+
+ /* Initialize state. */
+ cfspi->cmd = SPI_CMD_EOT;
+
+ for (;;) {
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING);
+
+ /* Wait for master talk or transmit event. */
+ wait_event_interruptible(cfspi->wait,
+ test_bit(SPI_XFER, &cfspi->state) ||
+ test_bit(SPI_TERMINATE, &cfspi->state));
+
+ if (test_bit(SPI_TERMINATE, &cfspi->state))
+ return;
+
+#if CFSPI_DBG_PREFILL
+ /* Prefill buffers for easier debugging. */
+ memset(cfspi->xfer.va_tx, 0xFF, SPI_DMA_BUF_LEN);
+ memset(cfspi->xfer.va_rx, 0xFF, SPI_DMA_BUF_LEN);
+#endif /* CFSPI_DBG_PREFILL */
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE);
+
+ /* Check whether we have a committed frame. */
+ if (cfspi->tx_cpck_len) {
+ int len;
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);
+
+ /* Copy commited SPI frames after the SPI indication. */
+ ptr = (u8 *) cfspi->xfer.va_tx;
+ ptr += SPI_IND_SZ;
+ len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
+ WARN_ON(len != cfspi->tx_cpck_len);
+ }
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT);
+
+ /* Get length of next frame to commit. */
+ cfspi->tx_npck_len = cfspi_xmitlen(cfspi);
+
+ WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN);
+
+ /*
+ * Add indication and length at the beginning of the frame,
+ * using little endian.
+ */
+ ptr = (u8 *) cfspi->xfer.va_tx;
+ *ptr++ = SPI_CMD_IND;
+ *ptr++ = (SPI_CMD_IND & 0xFF00) >> 8;
+ *ptr++ = cfspi->tx_npck_len & 0x00FF;
+ *ptr++ = (cfspi->tx_npck_len & 0xFF00) >> 8;
+
+ /* Calculate length of DMAs. */
+ cfspi->xfer.tx_dma_len = cfspi->tx_cpck_len + SPI_IND_SZ;
+ cfspi->xfer.rx_dma_len = cfspi->rx_cpck_len + SPI_CMD_SZ;
+
+ /* Add SPI TX frame alignment padding, if necessary. */
+ if (cfspi->tx_cpck_len &&
+ (cfspi->xfer.tx_dma_len % spi_frm_align)) {
+
+ cfspi->xfer.tx_dma_len += spi_frm_align -
+ (cfspi->xfer.tx_dma_len % spi_frm_align);
+ }
+
+ /* Add SPI RX frame alignment padding, if necessary. */
+ if (cfspi->rx_cpck_len &&
+ (cfspi->xfer.rx_dma_len % spi_frm_align)) {
+
+ cfspi->xfer.rx_dma_len += spi_frm_align -
+ (cfspi->xfer.rx_dma_len % spi_frm_align);
+ }
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER);
+
+ /* Start transfer. */
+ ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev);
+ WARN_ON(ret);
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE);
+
+ /*
+ * TODO: We might be able to make an assumption if this is the
+ * first loop. Make sure that minimum toggle time is respected.
+ */
+ udelay(MIN_TRANSITION_TIME_USEC);
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);
+
+ /* Signal that we are ready to recieve data. */
+ cfspi->dev->sig_xfer(true, cfspi->dev);
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);
+
+ /* Wait for transfer completion. */
+ wait_for_completion(&cfspi->comp);
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE);
+
+ if (cfspi->cmd == SPI_CMD_EOT) {
+ /*
+ * Clear the master talk bit. A xfer is always at
+ * least two bursts.
+ */
+ clear_bit(SPI_SS_ON, &cfspi->state);
+ }
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE);
+
+ /* Make sure that the minimum toggle time is respected. */
+ if (SPI_XFER_TIME_USEC(cfspi->xfer.tx_dma_len,
+ cfspi->dev->clk_mhz) <
+ MIN_TRANSITION_TIME_USEC) {
+
+ udelay(MIN_TRANSITION_TIME_USEC -
+ SPI_XFER_TIME_USEC
+ (cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz));
+ }
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE);
+
+ /* De-assert transfer signal. */
+ cfspi->dev->sig_xfer(false, cfspi->dev);
+
+ /* Check whether we received a CAIF packet. */
+ if (cfspi->rx_cpck_len) {
+ int len;
+
+ cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT);
+
+ /* Parse SPI frame. */
+ ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS));
+
+ len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len);
+ WARN_ON(len != cfspi->rx_cpck_len);
+ }
+
+ /* Check the next SPI command and length. */
+ ptr = (u8 *) cfspi->xfer.va_rx;
+
+ ptr += forward_to_spi_cmd(cfspi);
+
+ cfspi->cmd = *ptr++;
+ cfspi->cmd |= ((*ptr++) << 8) & 0xFF00;
+ cfspi->rx_npck_len = *ptr++;
+ cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00;
+
+ WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN);
+ WARN_ON(cfspi->cmd > SPI_CMD_EOT);
+
+ debugfs_store_prev(cfspi);
+
+ /* Check whether the master issued an EOT command. */
+ if (cfspi->cmd == SPI_CMD_EOT) {
+ /* Reset state. */
+ cfspi->tx_cpck_len = 0;
+ cfspi->rx_cpck_len = 0;
+ } else {
+ /* Update state. */
+ cfspi->tx_cpck_len = cfspi->tx_npck_len;
+ cfspi->rx_cpck_len = cfspi->rx_npck_len;
+ }
+
+ /*
+ * Check whether we need to clear the xfer bit.
+ * Spin lock needed for packet insertion.
+ * Test and clear of different bits
+ * are not supported.
+ */
+ spin_lock_irqsave(&cfspi->lock, flags);
+ if (cfspi->cmd == SPI_CMD_EOT && !cfspi_xmitlen(cfspi)
+ && !test_bit(SPI_SS_ON, &cfspi->state))
+ clear_bit(SPI_XFER, &cfspi->state);
+
+ spin_unlock_irqrestore(&cfspi->lock, flags);
+ }
+}
+
+struct platform_driver cfspi_spi_driver = {
+ .probe = cfspi_spi_probe,
+ .remove = cfspi_spi_remove,
+ .driver = {
+ .name = "cfspi_sspi",
+ .owner = THIS_MODULE,
+ },
+};
diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h
new file mode 100644
index 0000000..ce4570d
--- /dev/null
+++ b/include/net/caif/caif_spi.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_SPI_H_
+#define CAIF_SPI_H_
+
+#include <net/caif/caif_device.h>
+
+#define SPI_CMD_WR 0x00
+#define SPI_CMD_RD 0x01
+#define SPI_CMD_EOT 0x02
+#define SPI_CMD_IND 0x04
+
+#define SPI_DMA_BUF_LEN 8192
+
+#define WL_SZ 2 /* 16 bits. */
+#define SPI_CMD_SZ 4 /* 32 bits. */
+#define SPI_IND_SZ 4 /* 32 bits. */
+
+#define SPI_XFER 0
+#define SPI_SS_ON 1
+#define SPI_SS_OFF 2
+#define SPI_TERMINATE 3
+
+/* Minimum time between different levels is 50 microseconds. */
+#define MIN_TRANSITION_TIME_USEC 50
+
+/* Defines for calculating duration of SPI transfers for a particular
+ * number of bytes.
+ */
+#define SPI_MASTER_CLK_MHZ 13
+#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
+
+/* Normally this should be aligned on the modem in order to benefit from full
+ * duplex transfers. However a size of 8188 provokes errors when running with
+ * the modem. These errors occur when packet sizes approaches 4 kB of data.
+ */
+#define CAIF_MAX_SPI_FRAME 4092
+
+/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
+ * This number should correspond with the modem setting. The application side
+ * CAIF accepts any number of embedded downlink CAIF frames.
+ */
+#define CAIF_MAX_SPI_PKTS 9
+
+/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
+ * debugging. Both TX and RX buffers will be filled before the transfer.
+ */
+#define CFSPI_DBG_PREFILL 0
+
+/* Structure describing a SPI transfer. */
+struct cfspi_xfer {
+ u16 tx_dma_len;
+ u16 rx_dma_len;
+ void *va_tx;
+ dma_addr_t pa_tx;
+ void *va_rx;
+ dma_addr_t pa_rx;
+};
+
+/* Structure implemented by the SPI interface. */
+struct cfspi_ifc {
+ void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
+ void (*xfer_done_cb) (struct cfspi_ifc *ifc);
+ void *priv;
+};
+
+/* Structure implemented by SPI clients. */
+struct cfspi_dev {
+ int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
+ void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
+ struct cfspi_ifc *ifc;
+ char *name;
+ u32 clk_mhz;
+ void *priv;
+};
+
+/* Enumeration describing the CAIF SPI state. */
+enum cfspi_state {
+ CFSPI_STATE_WAITING = 0,
+ CFSPI_STATE_AWAKE,
+ CFSPI_STATE_FETCH_PKT,
+ CFSPI_STATE_GET_NEXT,
+ CFSPI_STATE_INIT_XFER,
+ CFSPI_STATE_WAIT_ACTIVE,
+ CFSPI_STATE_SIG_ACTIVE,
+ CFSPI_STATE_WAIT_XFER_DONE,
+ CFSPI_STATE_XFER_DONE,
+ CFSPI_STATE_WAIT_INACTIVE,
+ CFSPI_STATE_SIG_INACTIVE,
+ CFSPI_STATE_DELIVER_PKT,
+ CFSPI_STATE_MAX,
+};
+
+/* Structure implemented by SPI physical interfaces. */
+struct cfspi {
+ struct caif_dev_common cfdev;
+ struct net_device *ndev;
+ struct platform_device *pdev;
+ struct sk_buff_head qhead;
+ struct sk_buff_head chead;
+ u16 cmd;
+ u16 tx_cpck_len;
+ u16 tx_npck_len;
+ u16 rx_cpck_len;
+ u16 rx_npck_len;
+ struct cfspi_ifc ifc;
+ struct cfspi_xfer xfer;
+ struct cfspi_dev *dev;
+ unsigned long state;
+ struct work_struct work;
+ struct workqueue_struct *wq;
+ struct list_head list;
+ int flow_off_sent;
+ u32 qd_low_mark;
+ u32 qd_high_mark;
+ struct completion comp;
+ wait_queue_head_t wait;
+ spinlock_t lock;
+ bool flow_stop;
+#ifdef CONFIG_DEBUG_FS
+ enum cfspi_state dbg_state;
+ u16 pcmd;
+ u16 tx_ppck_len;
+ u16 rx_ppck_len;
+ struct dentry *dbgfs_dir;
+ struct dentry *dbgfs_state;
+ struct dentry *dbgfs_frame;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+extern int spi_frm_align;
+extern int spi_up_head_align;
+extern int spi_up_tail_align;
+extern int spi_down_head_align;
+extern int spi_down_tail_align;
+extern struct platform_driver cfspi_spi_driver;
+
+void cfspi_dbg_state(struct cfspi *cfspi, int state);
+int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_xmitlen(struct cfspi *cfspi);
+int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_spi_remove(struct platform_device *pdev);
+int cfspi_spi_probe(struct platform_device *pdev);
+int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+int cfspi_xmitlen(struct cfspi *cfspi);
+int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
+void cfspi_xfer(struct work_struct *work);
+
+#endif /* CAIF_SPI_H_ */
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/2] ipv6: Clamp reported valid_lft to a minimum of 0
From: Ben Hutchings @ 2010-06-26 21:37 UTC (permalink / raw)
To: David Miller
Cc: Hideaki YOSHIFUJI, Patrick McHardy, 514644, Piotr Lewandowski,
netdev
Since addresses are only revalidated every 2 minutes, the reported
valid_lft can underflow shortly before the address is deleted.
Clamp it to a minimum of 0, as for prefered_lft.
Reported-by: Piotr Lewandowski <piotr.lewandowski@gmail.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
This is compile-tested only. I don't claim any familiarity with this
code.
Ben.
net/ipv6/addrconf.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b97bb1f..1459eed 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3492,8 +3492,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
preferred -= tval;
else
preferred = 0;
- if (valid != INFINITY_LIFE_TIME)
- valid -= tval;
+ if (valid != INFINITY_LIFE_TIME) {
+ if (valid > tval)
+ valid -= tval;
+ else
+ valid = 0;
+ }
}
} else {
preferred = INFINITY_LIFE_TIME;
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] ipv6: Use interface max_desync_factor instead of static default
From: Ben Hutchings @ 2010-06-26 21:42 UTC (permalink / raw)
To: David Miller
Cc: Hideaki YOSHIFUJI, Patrick McHardy, 514646, Piotr Lewandowski,
netdev
In-Reply-To: <1277588267.26161.300.camel@localhost>
max_desync_factor can be configured per-interface, but nothing is
using the value.
Reported-by: Piotr Lewandowski <piotr.lewandowski@gmail.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
Also compile-tested only.
Note that there is nothing to stop temp_prefered_lft being set smaller
than max_desync_factor, which can result in underflow in calculation of
tmp_prefered_lft in ipv6_create_tempaddr(). However, the same applies
to the current static variable desync_factor.
Ben.
net/ipv6/addrconf.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1459eed..ec8c92f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -121,8 +121,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
static int __ipv6_regen_rndid(struct inet6_dev *idev);
static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
static void ipv6_regen_rndid(unsigned long data);
-
-static int desync_factor = MAX_DESYNC_FACTOR * HZ;
#endif
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
@@ -890,7 +888,8 @@ retry:
idev->cnf.temp_valid_lft);
tmp_prefered_lft = min_t(__u32,
ifp->prefered_lft,
- idev->cnf.temp_prefered_lft - desync_factor / HZ);
+ idev->cnf.temp_prefered_lft -
+ idev->cnf.max_desync_factor);
tmp_plen = ifp->prefix_len;
max_addresses = idev->cnf.max_addresses;
tmp_cstamp = ifp->cstamp;
@@ -1650,7 +1649,8 @@ static void ipv6_regen_rndid(unsigned long data)
expires = jiffies +
idev->cnf.temp_prefered_lft * HZ -
- idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
+ idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time -
+ idev->cnf.max_desync_factor * HZ;
if (time_before(expires, jiffies)) {
printk(KERN_WARNING
"ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] ip: correctly report 802.15.4 link type
From: Stephen Hemminger @ 2010-06-26 23:51 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netdev
OK but long-term fix is to get rid of hardcoded table
Jan Engelhardt <jengelh@medozas.de> wrote:
>Up until now, the "hardwpan" devices were displayed as link/[804].
>
>Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
>---
> lib/ll_types.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
>diff --git a/lib/ll_types.c b/lib/ll_types.c
>index 846cdb0..1cc46b6 100644
>--- a/lib/ll_types.c
>+++ b/lib/ll_types.c
>@@ -125,6 +125,9 @@ __PF(IEEE80211_PRISM,ieee802.11/prism)
> #ifdef ARPHRD_IEEE80211_RADIOTAP
> __PF(IEEE80211_RADIOTAP,ieee802.11/radiotap)
> #endif
>+#ifdef ARPHRD_IEEE802154
>+__PF(IEEE802154, ieee802.15.4)
>+#endif
> #ifdef ARPHRD_NONE
> __PF(NONE, none)
> #endif
>--
>1.7.1
>
^ permalink raw reply
* Re: [PATCH] usb: pegasus: fixed coding style issues
From: Petko Manolov @ 2010-06-27 2:47 UTC (permalink / raw)
To: Nicolas Kaiser; +Cc: Petko Manolov, linux-usb, netdev
In-Reply-To: <20100626185854.4a3eff43@absol.kitzblitz>
I think the old code is what "Lindent" script outputs. To me it doesn't
matter either way. :-)
Petko
On Sat, 26 Jun 2010, Nicolas Kaiser wrote:
> Fixed brace, static initialization, comment, whitespace and spacing
> coding style issues.
>
> Signed-off-by: Nicolas Kaiser <nikai@nikai.net>
> ---
> drivers/net/usb/pegasus.c | 125 +++++++++----------
> drivers/net/usb/pegasus.h | 296 ++++++++++++++++++++++----------------------
> 2 files changed, 209 insertions(+), 212 deletions(-)
>
> diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
> index 974d17f..6710f09 100644
> --- a/drivers/net/usb/pegasus.c
> +++ b/drivers/net/usb/pegasus.c
> @@ -21,11 +21,11 @@
> * behaves. Pegasus II support added since this version.
> * TODO: suppressing HCD warnings spewage on disconnect.
> * v0.4.13 Ethernet address is now set at probe(), not at open()
> - * time as this seems to break dhcpd.
> + * time as this seems to break dhcpd.
> * v0.5.0 branch to 2.5.x kernels
> * v0.5.1 ethtool support added
> * v0.5.5 rx socket buffers are in a pool and the their allocation
> - * is out of the interrupt routine.
> + * is out of the interrupt routine.
> */
>
> #include <linux/sched.h>
> @@ -55,9 +55,9 @@ static const char driver_name[] = "pegasus";
> #define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
> BMSR_100FULL | BMSR_ANEGCAPABLE)
>
> -static int loopback = 0;
> -static int mii_mode = 0;
> -static char *devid=NULL;
> +static int loopback;
> +static int mii_mode;
> +static char *devid;
>
> static struct usb_eth_dev usb_dev_id[] = {
> #define PEGASUS_DEV(pn, vid, pid, flags) \
> @@ -102,8 +102,8 @@ MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
>
> /* use ethtool to change the level for any given device */
> static int msg_level = -1;
> -module_param (msg_level, int, 0);
> -MODULE_PARM_DESC (msg_level, "Override default message level");
> +module_param(msg_level, int, 0);
> +MODULE_PARM_DESC(msg_level, "Override default message level");
>
> MODULE_DEVICE_TABLE(usb, pegasus_ids);
> static const struct net_device_ops pegasus_netdev_ops;
> @@ -141,7 +141,7 @@ static void ctrl_callback(struct urb *urb)
> wake_up(&pegasus->ctrl_wait);
> }
>
> -static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
> +static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
> void *data)
> {
> int ret;
> @@ -196,7 +196,7 @@ out:
> return ret;
> }
>
> -static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
> +static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
> void *data)
> {
> int ret;
> @@ -248,7 +248,7 @@ out:
> return ret;
> }
>
> -static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
> +static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
> {
> int ret;
> char *tmp;
> @@ -299,7 +299,7 @@ out:
> return ret;
> }
>
> -static int update_eth_regs_async(pegasus_t * pegasus)
> +static int update_eth_regs_async(pegasus_t *pegasus)
> {
> int ret;
>
> @@ -326,7 +326,7 @@ static int update_eth_regs_async(pegasus_t * pegasus)
> }
>
> /* Returns 0 on success, error on failure */
> -static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
> +static int read_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd)
> {
> int i;
> __u8 data[4] = { phy, 0, 0, indx };
> @@ -334,7 +334,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
> int ret;
>
> set_register(pegasus, PhyCtrl, 0);
> - set_registers(pegasus, PhyAddr, sizeof (data), data);
> + set_registers(pegasus, PhyAddr, sizeof(data), data);
> set_register(pegasus, PhyCtrl, (indx | PHY_READ));
> for (i = 0; i < REG_TIMEOUT; i++) {
> ret = get_registers(pegasus, PhyCtrl, 1, data);
> @@ -366,7 +366,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int loc)
> return (int)res;
> }
>
> -static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
> +static int write_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd)
> {
> int i;
> __u8 data[4] = { phy, 0, 0, indx };
> @@ -402,7 +402,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
> write_mii_word(pegasus, phy_id, loc, val);
> }
>
> -static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
> +static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
> {
> int i;
> __u8 tmp;
> @@ -433,7 +433,7 @@ fail:
> }
>
> #ifdef PEGASUS_WRITE_EEPROM
> -static inline void enable_eprom_write(pegasus_t * pegasus)
> +static inline void enable_eprom_write(pegasus_t *pegasus)
> {
> __u8 tmp;
> int ret;
> @@ -442,7 +442,7 @@ static inline void enable_eprom_write(pegasus_t * pegasus)
> set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
> }
>
> -static inline void disable_eprom_write(pegasus_t * pegasus)
> +static inline void disable_eprom_write(pegasus_t *pegasus)
> {
> __u8 tmp;
> int ret;
> @@ -452,7 +452,7 @@ static inline void disable_eprom_write(pegasus_t * pegasus)
> set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
> }
>
> -static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
> +static int write_eprom_word(pegasus_t *pegasus, __u8 index, __u16 data)
> {
> int i;
> __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
> @@ -484,7 +484,7 @@ fail:
> }
> #endif /* PEGASUS_WRITE_EEPROM */
>
> -static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
> +static inline void get_node_id(pegasus_t *pegasus, __u8 *id)
> {
> int i;
> __u16 w16;
> @@ -495,7 +495,7 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
> }
> }
>
> -static void set_ethernet_addr(pegasus_t * pegasus)
> +static void set_ethernet_addr(pegasus_t *pegasus)
> {
> __u8 node_id[6];
>
> @@ -503,12 +503,12 @@ static void set_ethernet_addr(pegasus_t * pegasus)
> get_registers(pegasus, 0x10, sizeof(node_id), node_id);
> } else {
> get_node_id(pegasus, node_id);
> - set_registers(pegasus, EthID, sizeof (node_id), node_id);
> + set_registers(pegasus, EthID, sizeof(node_id), node_id);
> }
> - memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
> + memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
> }
>
> -static inline int reset_mac(pegasus_t * pegasus)
> +static inline int reset_mac(pegasus_t *pegasus)
> {
> __u8 data = 0x8;
> int i;
> @@ -563,7 +563,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
> data[1] = 0;
> data[2] = (loopback & 1) ? 0x09 : 0x01;
>
> - memcpy(pegasus->eth_regs, data, sizeof (data));
> + memcpy(pegasus->eth_regs, data, sizeof(data));
> ret = set_registers(pegasus, EthCtrl0, 3, data);
>
> if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
> @@ -577,7 +577,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
> return ret;
> }
>
> -static void fill_skb_pool(pegasus_t * pegasus)
> +static void fill_skb_pool(pegasus_t *pegasus)
> {
> int i;
>
> @@ -595,7 +595,7 @@ static void fill_skb_pool(pegasus_t * pegasus)
> }
> }
>
> -static void free_skb_pool(pegasus_t * pegasus)
> +static void free_skb_pool(pegasus_t *pegasus)
> {
> int i;
>
> @@ -667,11 +667,11 @@ static void read_bulk_callback(struct urb *urb)
> netif_dbg(pegasus, rx_err, net,
> "RX packet error %x\n", rx_status);
> pegasus->stats.rx_errors++;
> - if (rx_status & 0x06) // long or runt
> + if (rx_status & 0x06) /* long or runt */
> pegasus->stats.rx_length_errors++;
> if (rx_status & 0x08)
> pegasus->stats.rx_crc_errors++;
> - if (rx_status & 0x10) // extra bits
> + if (rx_status & 0x10) /* extra bits */
> pegasus->stats.rx_frame_errors++;
> goto goon;
> }
> @@ -748,9 +748,8 @@ static void rx_fixup(unsigned long data)
> if (pegasus->flags & PEGASUS_RX_URB_FAIL)
> if (pegasus->rx_skb)
> goto try_again;
> - if (pegasus->rx_skb == NULL) {
> + if (pegasus->rx_skb == NULL)
> pegasus->rx_skb = pull_skb(pegasus);
> - }
> if (pegasus->rx_skb == NULL) {
> netif_warn(pegasus, rx_err, pegasus->net, "low on memory\n");
> tasklet_schedule(&pegasus->rx_tl);
> @@ -835,7 +834,7 @@ static void intr_callback(struct urb *urb)
> }
>
> if (urb->actual_length >= 6) {
> - u8 * d = urb->transfer_buffer;
> + u8 *d = urb->transfer_buffer;
>
> /* byte 0 == tx_status1, reg 2B */
> if (d[0] & (TX_UNDERRUN|EXCESSIVE_COL
> @@ -918,14 +917,14 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
> return &((pegasus_t *) netdev_priv(dev))->stats;
> }
>
> -static inline void disable_net_traffic(pegasus_t * pegasus)
> +static inline void disable_net_traffic(pegasus_t *pegasus)
> {
> __le16 tmp = cpu_to_le16(0);
>
> set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp);
> }
>
> -static inline void get_interrupt_interval(pegasus_t * pegasus)
> +static inline void get_interrupt_interval(pegasus_t *pegasus)
> {
> u16 data;
> u8 interval;
> @@ -961,7 +960,7 @@ static void set_carrier(struct net_device *net)
> netif_carrier_off(net);
> }
>
> -static void free_all_urbs(pegasus_t * pegasus)
> +static void free_all_urbs(pegasus_t *pegasus)
> {
> usb_free_urb(pegasus->intr_urb);
> usb_free_urb(pegasus->tx_urb);
> @@ -969,7 +968,7 @@ static void free_all_urbs(pegasus_t * pegasus)
> usb_free_urb(pegasus->ctrl_urb);
> }
>
> -static void unlink_all_urbs(pegasus_t * pegasus)
> +static void unlink_all_urbs(pegasus_t *pegasus)
> {
> usb_kill_urb(pegasus->intr_urb);
> usb_kill_urb(pegasus->tx_urb);
> @@ -977,12 +976,11 @@ static void unlink_all_urbs(pegasus_t * pegasus)
> usb_kill_urb(pegasus->ctrl_urb);
> }
>
> -static int alloc_urbs(pegasus_t * pegasus)
> +static int alloc_urbs(pegasus_t *pegasus)
> {
> pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
> - if (!pegasus->ctrl_urb) {
> + if (!pegasus->ctrl_urb)
> return 0;
> - }
> pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
> if (!pegasus->rx_urb) {
> usb_free_urb(pegasus->ctrl_urb);
> @@ -1019,7 +1017,7 @@ static int pegasus_open(struct net_device *net)
> return -ENOMEM;
>
> res = set_registers(pegasus, EthID, 6, net->dev_addr);
> -
> +
> usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
> usb_rcvbulkpipe(pegasus->usb, 1),
> pegasus->rx_skb->data, PEGASUS_MTU + 8,
> @@ -1033,7 +1031,7 @@ static int pegasus_open(struct net_device *net)
>
> usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
> usb_rcvintpipe(pegasus->usb, 3),
> - pegasus->intr_buff, sizeof (pegasus->intr_buff),
> + pegasus->intr_buff, sizeof(pegasus->intr_buff),
> intr_callback, pegasus, pegasus->intr_interval);
> if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
> if (res == -ENODEV)
> @@ -1076,9 +1074,9 @@ static void pegasus_get_drvinfo(struct net_device *dev,
> struct ethtool_drvinfo *info)
> {
> pegasus_t *pegasus = netdev_priv(dev);
> - strncpy(info->driver, driver_name, sizeof (info->driver) - 1);
> - strncpy(info->version, DRIVER_VERSION, sizeof (info->version) - 1);
> - usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info));
> + strncpy(info->driver, driver_name, sizeof(info->driver) - 1);
> + strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
> + usb_make_path(pegasus->usb, info->bus_info, sizeof(info->bus_info));
> }
>
> /* also handles three patterns of some kind in hardware */
> @@ -1098,7 +1096,7 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
> {
> pegasus_t *pegasus = netdev_priv(dev);
> u8 reg78 = 0x04;
> -
> +
> if (wol->wolopts & ~WOL_SUPPORTED)
> return -EINVAL;
>
> @@ -1118,7 +1116,7 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
> static inline void pegasus_reset_wol(struct net_device *dev)
> {
> struct ethtool_wolinfo wol;
> -
> +
> memset(&wol, 0, sizeof wol);
> (void) pegasus_set_wol(dev, &wol);
> }
> @@ -1178,7 +1176,7 @@ static const struct ethtool_ops ops = {
>
> static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
> {
> - __u16 *data = (__u16 *) & rq->ifr_ifru;
> + __u16 *data = (__u16 *) &rq->ifr_ifru;
> pegasus_t *pegasus = netdev_priv(net);
> int res;
>
> @@ -1223,7 +1221,7 @@ static void pegasus_set_multicast(struct net_device *net)
> ctrl_callback(pegasus->ctrl_urb);
> }
>
> -static __u8 mii_phy_probe(pegasus_t * pegasus)
> +static __u8 mii_phy_probe(pegasus_t *pegasus)
> {
> int i;
> __u16 tmp;
> @@ -1239,10 +1237,10 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
> return 0xff;
> }
>
> -static inline void setup_pegasus_II(pegasus_t * pegasus)
> +static inline void setup_pegasus_II(pegasus_t *pegasus)
> {
> __u8 data = 0xa5;
> -
> +
> set_register(pegasus, Reg1d, 0);
> set_register(pegasus, Reg7b, 1);
> mdelay(100);
> @@ -1254,16 +1252,15 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
> set_register(pegasus, 0x83, data);
> get_registers(pegasus, 0x83, 1, &data);
>
> - if (data == 0xa5) {
> + if (data == 0xa5)
> pegasus->chip = 0x8513;
> - } else {
> + else
> pegasus->chip = 0;
> - }
>
> set_register(pegasus, 0x80, 0xc0);
> set_register(pegasus, 0x83, 0xff);
> set_register(pegasus, 0x84, 0x01);
> -
> +
> if (pegasus->features & HAS_HOME_PNA && mii_mode)
> set_register(pegasus, Reg81, 6);
> else
> @@ -1272,7 +1269,7 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
>
>
> static int pegasus_count;
> -static struct workqueue_struct *pegasus_workqueue = NULL;
> +static struct workqueue_struct *pegasus_workqueue;
> #define CARRIER_CHECK_DELAY (2 * HZ)
>
> static void check_carrier(struct work_struct *work)
> @@ -1367,7 +1364,7 @@ static int pegasus_probe(struct usb_interface *intf,
> pegasus->mii.phy_id_mask = 0x1f;
> pegasus->mii.reg_num_mask = 0x1f;
> spin_lock_init(&pegasus->rx_pool_lock);
> - pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
> + pegasus->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV
> | NETIF_MSG_PROBE | NETIF_MSG_LINK);
>
> pegasus->features = usb_dev_id[dev_index].private;
> @@ -1442,11 +1439,11 @@ static void pegasus_disconnect(struct usb_interface *intf)
> pegasus_dec_workqueue();
> }
>
> -static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
> +static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
> {
> struct pegasus *pegasus = usb_get_intfdata(intf);
> -
> - netif_device_detach (pegasus->net);
> +
> + netif_device_detach(pegasus->net);
> cancel_delayed_work(&pegasus->carrier_check);
> if (netif_running(pegasus->net)) {
> usb_kill_urb(pegasus->rx_urb);
> @@ -1455,11 +1452,11 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
> return 0;
> }
>
> -static int pegasus_resume (struct usb_interface *intf)
> +static int pegasus_resume(struct usb_interface *intf)
> {
> struct pegasus *pegasus = usb_get_intfdata(intf);
>
> - netif_device_attach (pegasus->net);
> + netif_device_attach(pegasus->net);
> if (netif_running(pegasus->net)) {
> pegasus->rx_urb->status = 0;
> pegasus->rx_urb->actual_length = 0;
> @@ -1498,8 +1495,8 @@ static struct usb_driver pegasus_driver = {
>
> static void __init parse_id(char *id)
> {
> - unsigned int vendor_id=0, device_id=0, flags=0, i=0;
> - char *token, *name=NULL;
> + unsigned int vendor_id = 0, device_id = 0, flags = 0, i = 0;
> + char *token, *name = NULL;
>
> if ((token = strsep(&id, ":")) != NULL)
> name = token;
> @@ -1510,14 +1507,14 @@ static void __init parse_id(char *id)
> device_id = simple_strtoul(token, NULL, 16);
> flags = simple_strtoul(id, NULL, 16);
> pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
> - driver_name, name, vendor_id, device_id, flags);
> + driver_name, name, vendor_id, device_id, flags);
>
> if (vendor_id > 0x10000 || vendor_id == 0)
> return;
> if (device_id > 0x10000 || device_id == 0)
> return;
>
> - for (i=0; usb_dev_id[i].name; i++);
> + for (i = 0; usb_dev_id[i].name; i++);
> usb_dev_id[i].name = name;
> usb_dev_id[i].vendor = vendor_id;
> usb_dev_id[i].device = device_id;
> diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h
> index 29f5211..65b78b3 100644
> --- a/drivers/net/usb/pegasus.h
> +++ b/drivers/net/usb/pegasus.h
> @@ -68,7 +68,7 @@ enum pegasus_registers {
> EpromData = 0x21, /* 0x21 low, 0x22 high byte */
> EpromCtrl = 0x23,
> PhyAddr = 0x25,
> - PhyData = 0x26, /* 0x26 low, 0x27 high byte */
> + PhyData = 0x26, /* 0x26 low, 0x27 high byte */
> PhyCtrl = 0x28,
> UsbStst = 0x2a,
> EthTxStat0 = 0x2b,
> @@ -154,162 +154,162 @@ struct usb_eth_dev {
>
> #else /* PEGASUS_DEV */
>
> -PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
> - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
> -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
> +PEGASUS_DEV("3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
> + DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
> +PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
> VENDOR_ADMTEK, 0x8511,
> - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
> -PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
> + DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
> +PEGASUS_DEV("ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
> VENDOR_ADMTEK, 0x8513,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet",
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet",
> VENDOR_ADMTEK, 0x8515,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
> VENDOR_ADMTEK, 0x0986,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("AN986A USB MAC", VENDOR_ADMTEK, 1986,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> /*
> * Distinguish between this Belkin adaptor and the Belkin bluetooth adaptors
> * with the same product IDs by checking the device class too.
> */
> -PEGASUS_DEV_CLASS( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Belkin F5U122 10/100 USB Ethernet", VENDOR_BELKIN, 0x0122,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Corega FEther USB-TX", VENDOR_COREGA, 0x0004,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Corega FEther USB-TXS", VENDOR_COREGA, 0x000d,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
> - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
> -PEGASUS_DEV( "ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM, 0x4010,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "IO DATA USB ETX-US2", VENDOR_IODATA, 0x093a,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
> +PEGASUS_DEV_CLASS("Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Belkin F5U122 10/100 USB Ethernet", VENDOR_BELKIN, 0x0122,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Corega FEther USB-TX", VENDOR_COREGA, 0x0004,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Corega FEther USB-TXS", VENDOR_COREGA, 0x000d,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4102,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x400b,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x200c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("D-Link DSB-650", VENDOR_DLINK, 0xabc1,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
> + DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
> +PEGASUS_DEV("ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM, 0x4010,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("EasiDock Ethernet", VENDOR_MOBILITY, 0x0304,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
> DEFAULT_GPIO_RESET)
> -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005,
> - DEFAULT_GPIO_RESET | PEGASUS_II)
> -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204,
> - DEFAULT_GPIO_RESET | HAS_HOME_PNA )
> -PEGASUS_DEV( "Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206,
> - DEFAULT_GPIO_RESET | PEGASUS_II)
> -PEGASUS_DEV( "Linksys USBVPN1", VENDOR_LINKSYS2, 0x08b4,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "Microsoft MN-110", VENDOR_MICROSOFT, 0x007a,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "OCT USB TO Ethernet", VENDOR_OCT, 0x0901,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
> - DEFAULT_GPIO_RESET | PEGASUS_II)
> -PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
> - DEFAULT_GPIO_RESET )
> -PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> -PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
> - DEFAULT_GPIO_RESET | PEGASUS_II )
> +PEGASUS_DEV("GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("IO DATA USB ETX-US2", VENDOR_IODATA, 0x093a,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Linksys USB10TX", VENDOR_LINKSYS, 0x2202,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Linksys USB100TX", VENDOR_LINKSYS, 0x2203,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Linksys USB100TX", VENDOR_LINKSYS, 0x2204,
> + DEFAULT_GPIO_RESET | HAS_HOME_PNA)
> +PEGASUS_DEV("Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Linksys USBVPN1", VENDOR_LINKSYS2, 0x08b4,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Linksys USB10TX", VENDOR_LINKSYS, 0x200c,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("Microsoft MN-110", VENDOR_MICROSOFT, 0x007a,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("OCT Inc.", VENDOR_OCT, 0x0109,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("OCT USB TO Ethernet", VENDOR_OCT, 0x0901,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
> + DEFAULT_GPIO_RESET)
> +PEGASUS_DEV("SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
> +PEGASUS_DEV("SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
> + DEFAULT_GPIO_RESET | PEGASUS_II)
>
>
> #endif /* PEGASUS_DEV */
> --
> 1.7.1
>
^ permalink raw reply
* Re: dhclient, checksum and tap
From: David Miller @ 2010-06-27 3:03 UTC (permalink / raw)
To: mst; +Cc: herbert.xu, netdev
In-Reply-To: <20100626211419.GA3646@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Sun, 27 Jun 2010 00:14:19 +0300
> On Fri, Jun 25, 2010 at 11:21:52AM -0700, David Miller wrote:
>> We added the af_packet status as the migration path to deal with
>> this issue in the cleanest manner possible. Putting a new hack
>> into the TAP driver works contrary to that goal.
>
> Hmm, problem is, using the af_packets status requires
> userspace changes, and so does not help old clients.
> And for virt, clients might be running old kernels without this support.
> qemu has a hack to make old guests running within qemu work.
> I guess I can copy that hack into vhost - a bit ugly as I don't have
> access to the original skb there, so I will have to duplcate some logic,
> but doable. Is this what you suggest? OTOH if we had the workaround in
> tap, this could replace hacks in both vhost and qemu.
If you add the TAP thing you can _never_ remove it. Exactly for the
same reason that the qemu thing can never be removed. It'll always be
needed for the sake of old guests running old stuff.
This is why I truly believe that keeping the af_packet status thing as
the only kernel side assist is likely best in the long run.
^ permalink raw reply
* Re: [PATCH] net, ucc_geth: ethtool -d shows phy register values
From: David Miller @ 2010-06-27 4:20 UTC (permalink / raw)
To: holger.brunck; +Cc: netdev, christopher.varlese, leoli, avorontsov, tj
In-Reply-To: <1276610603-11589-1-git-send-email-holger.brunck@keymile.com>
From: Holger Brunck <holger.brunck@keymile.com>
Date: Tue, 15 Jun 2010 16:03:23 +0200
> From: Chris Varlese <christopher.varlese@keymile.com>
>
> Fixes MPC83xx UCC Ethernet driver so ethtool -d dumps values of
> the PHY registers (like other devices do) instead of the UCC registers
> of the MPC83xx.
>
> Signed-off-by: Chris Varlese <christopher.varlese@keymile.com>
> Signed-off-by: Holger Brunck <holger.brunck@keymile.com>
This doesn't look right at all.
ethtool -d dumps "chip registers", not the PHY registers. So the
current code looks correct, not what you're changing it to.
^ permalink raw reply
* Re: [PATCH 1/2] syncookies: do not store rcv_wscale in tcp timestamp
From: David Miller @ 2010-06-27 4:27 UTC (permalink / raw)
To: hagen; +Cc: fw, netdev, ilpo.jarvinen
In-Reply-To: <20100624221416.GA31116@nuttenaction>
From: Hagen Paul Pfeifer <hagen@jauu.net>
Date: Fri, 25 Jun 2010 00:14:16 +0200
> why not limit the window to 2^16 bytes which is sufficient for
> 99.9999% of the use case?
This may have been true 8 years ago, but it is not any longer.
You will underutilize your link with anything smaller than
~512k on the modern internet.
^ permalink raw reply
* Re: [PATCH 1/2] syncookies: do not store rcv_wscale in tcp timestamp
From: David Miller @ 2010-06-27 5:00 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <1277156925-7295-1-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Mon, 21 Jun 2010 23:48:44 +0200
> As pointed out by Fernando Gont there is no need to encode rcv_wscale
> into the cookie.
>
> We did not use the restored rcv_wscale anyway; it is recomputed
> via tcp_select_initial_window().
>
> Thus we can save 4 bits in the ts option space by removing rcv_wscale.
> In case window scaling was not supported, we set the (invalid) wscale
> value 0xf.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied.
^ permalink raw reply
* Re: [PATCH 2/2] syncookies: add support for ECN
From: David Miller @ 2010-06-27 5:00 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <1277156925-7295-2-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Mon, 21 Jun 2010 23:48:45 +0200
> Allows use of ECN when syncookies are in effect by encoding ecn_ok
> into the syn-ack tcp timestamp.
>
> While at it, remove a uneeded #ifdef CONFIG_SYN_COOKIES.
> With CONFIG_SYN_COOKIES=nm want_cookie is ifdef'd to 0 and gcc
> removes the "if (0)".
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Also applied, nice work Florian.
^ permalink raw reply
* Re: [PATCH] vxge: fix memory leak in vxge_alloc_msix() error path {nodisc}
From: David Miller @ 2010-06-27 5:12 UTC (permalink / raw)
To: Ramkrishna.Vepa; +Cc: mschmidt, netdev
In-Reply-To: <FCA91A92EE52B041906A0358FC28FCC38EF1837D08@FRE1EXCH02.hq.exar.com>
From: Ramkrishna Vepa <Ramkrishna.Vepa@exar.com>
Date: Fri, 25 Jun 2010 00:21:48 -0700
>> When pci_enable_msix() returned ret<0, entries and vxge_entries were
>> leaked.
>> While at it, use the centralized exit idiom in the function.
>>
>> Not tested. It compiles OK.
>>
>> Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
>
> Reviewed and tested the patch. Thanks!
>
> Acked-by: Ram Vepa <ram.vepa@exar.com>
Applied.
^ permalink raw reply
* Re: [PATCH] ISDN: hysdn, fix potential NULL dereference
From: David Miller @ 2010-06-27 5:12 UTC (permalink / raw)
To: jslaby; +Cc: isdn, linux-kernel, jirislaby, shemminger, kaber, netdev
In-Reply-To: <1277206896-27197-1-git-send-email-jslaby@suse.cz>
From: Jiri Slaby <jslaby@suse.cz>
Date: Tue, 22 Jun 2010 13:41:36 +0200
> Stanse found that lp is dereferenced earlier than checked for being
> NULL in hysdn_rx_netpkt. Move the initialization below the test.
>
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Applied.
^ permalink raw reply
* Re: [PATCH] phylib: Add autoload support for the LXT973 phy.
From: David Miller @ 2010-06-27 5:16 UTC (permalink / raw)
To: dwmw2; +Cc: richardcochran, netdev
In-Reply-To: <1277210293.21798.11.camel@localhost>
From: David Woodhouse <dwmw2@infradead.org>
Date: Tue, 22 Jun 2010 13:38:13 +0100
> Commit e13647c1 (phylib: Add support for the LXT973 phy.) added a new ID
> but neglected to also add it to the MODULE_DEVICE_TABLE.
>
> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Applied, thanks.
> When I did this stuff, I did wonder if we should make this happen
> automatically somehow. I pondered some dirty macro hack in
> phy_driver_register() which would do it somehow, but couldn't come up
> with anything that'd work.
>
> Removing the phy_id and phy_id_mask from struct phy_driver and having a
> pointer to a match table would suck, since each driver only really
> matches one device/mask. (Even where a single C file has multiple
> drivers, they often differ in some methods or flags.)
>
> The best option I can come up with right now, is probably to remove
> phy_id and phy_id_mask from phy_driver and put a pointer to the driver
> into the ID table, and take the ID table as the argument to
> phy_driver_register(). I'm not sure I like that very much though -- I'd
> prefer that we just remember to update the table and don't need to be
> forced :)
>
> (Another cheap option is to pass the ID table as an extra argument to
> the existing phy_device_register(), I suppose, and it can just print a
> warning if it doesn't find the same phy_id and phy_id_mask in the table)
As our experience shows, people aren't remembering to do it so we have
to do something hard handed to make sure this doesn't break.
A compile time error out is the best, but if that is too hard or ugly
and we do it at run time then we should fail the register (not just
print a warning) if the table is incomplete.
Otherwise we run into cases where a developer adds several new IDs,
forgets some of the table entries, but only tries testing the ones he
did remember to add and doesn't notice the warning message.
^ permalink raw reply
* Re: [RFC PATCH v7 01/19] Add a new structure for skb buffer from external.
From: Herbert Xu @ 2010-06-27 6:14 UTC (permalink / raw)
To: Dong, Eddie
Cc: Xin, Xiaohui, Stephen Hemminger, netdev@vger.kernel.org,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org, mst@redhat.com,
mingo@elte.hu, davem@davemloft.net, jdike@linux.intel.com
In-Reply-To: <1A42CE6F5F474C41B63392A5F80372B21F58D666@shsmsx501.ccr.corp.intel.com>
On Fri, Jun 25, 2010 at 09:03:46AM +0800, Dong, Eddie wrote:
>
> In current patch, each SKB for the assigned device (SRIOV VF or NIC or a complete queue pairs) uses the buffer from guest, so it eliminates copy completely in software and requires hardware to do so. If we can have an additonal place to store the buffer per skb (may cause copy later on), we can do copy later on or re-post the buffer to assigned NIC driver later on. But that may be not very clean either :(
OK, if I understand you correctly then I don't think have a
problem. With your current patch-set you have exactly the same
situation when the skb->data is reallocated as a kernel buffer.
This is OK because as you correctly argue, it is a rare situation.
With my proposal you will need to get this extra external buffer
in even less cases, because you'd only need to do it if the skb
head grows, which only happens if it becomes encapsulated.
So let me explain it in a bit more detail:
Our packet starts out as a purely non-linear skb, i.e., skb->head
contains nothing and all the page frags come from the guest.
During host processing we may pull data into skb->head but the
first frag will remain unless we pull all of it. If we did do
that then you would have a free external buffer anyway.
Now in the common case the header may be modified or pulled, but
it very rarely grows. So you can just copy the header back into
the first frag just before we give it to the guest.
Only in the case where the packet header grows (e.g., encapsulation)
would you need to get an extra external buffer.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] ip: correctly report 802.15.4 link type
From: Jan Engelhardt @ 2010-06-27 7:01 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <7q2rynq4hva9nlyv9hdbhr26.1277596268239@email.android.com>
On Sunday 2010-06-27 01:51, Stephen Hemminger wrote:
>OK but long-term fix is to get rid of hardcoded table
With what will you be replacing it?
>>Up until now, the "hardwpan" devices were displayed as link/[804].
>>
>>Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
>>---
>> lib/ll_types.c | 3 +++
>> 1 files changed, 3 insertions(+), 0 deletions(-)
>>
>>diff --git a/lib/ll_types.c b/lib/ll_types.c
>>index 846cdb0..1cc46b6 100644
>>--- a/lib/ll_types.c
>>+++ b/lib/ll_types.c
>>@@ -125,6 +125,9 @@ __PF(IEEE80211_PRISM,ieee802.11/prism)
>> #ifdef ARPHRD_IEEE80211_RADIOTAP
>> __PF(IEEE80211_RADIOTAP,ieee802.11/radiotap)
>> #endif
>>+#ifdef ARPHRD_IEEE802154
>>+__PF(IEEE802154, ieee802.15.4)
>>+#endif
>> #ifdef ARPHRD_NONE
>> __PF(NONE, none)
>> #endif
>>--
>>1.7.1
>>
>
^ permalink raw reply
* Re: dhclient, checksum and tap
From: Michael S. Tsirkin @ 2010-06-27 8:24 UTC (permalink / raw)
To: David Miller; +Cc: herbert.xu, netdev
In-Reply-To: <20100626.200320.43025947.davem@davemloft.net>
On Sat, Jun 26, 2010 at 08:03:20PM -0700, David Miller wrote:
> From: "Michael S. Tsirkin" <mst@redhat.com>
> Date: Sun, 27 Jun 2010 00:14:19 +0300
>
> > On Fri, Jun 25, 2010 at 11:21:52AM -0700, David Miller wrote:
> >> We added the af_packet status as the migration path to deal with
> >> this issue in the cleanest manner possible. Putting a new hack
> >> into the TAP driver works contrary to that goal.
> >
> > Hmm, problem is, using the af_packets status requires
> > userspace changes, and so does not help old clients.
> > And for virt, clients might be running old kernels without this support.
> > qemu has a hack to make old guests running within qemu work.
> > I guess I can copy that hack into vhost - a bit ugly as I don't have
> > access to the original skb there, so I will have to duplcate some logic,
> > but doable. Is this what you suggest? OTOH if we had the workaround in
> > tap, this could replace hacks in both vhost and qemu.
>
> If you add the TAP thing you can _never_ remove it. Exactly for the
> same reason that the qemu thing can never be removed. It'll always be
> needed for the sake of old guests running old stuff.
>
> This is why I truly believe that keeping the af_packet status thing as
> the only kernel side assist is likely best in the long run.
Just to spell it out for me, you think the hack should be done
in vhost-net?
--
MST
^ permalink raw reply
* [PATCH] vhost: break out of polling loop on error
From: Michael S. Tsirkin @ 2010-06-27 8:59 UTC (permalink / raw)
To: Sridhar Samudrala, Arnd Bergmann, Paul E. McKenney, Juan Quintela,
Rusty Russell
When ring parsing fails, we currently handle this
as ring empty condition. This means that we enable
kicks and recheck ring empty: if this not empty,
we re-start polling which of course will fail again.
Instead, let's return a negative error code and stop polling.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, I'm sending this out so it can get reviewed.
I'll put this on my vhost tree
so no need for you to pick this patch directly.
drivers/vhost/net.c | 12 ++++++++++--
drivers/vhost/vhost.c | 33 +++++++++++++++++----------------
drivers/vhost/vhost.h | 8 ++++----
3 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 0f41c91..54096ee 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned head, out, in, s;
+ unsigned out, in, s;
+ int head;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
@@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net)
ARRAY_SIZE(vq->iov),
&out, &in,
NULL, NULL);
+ /* On error, stop handling until the next kick. */
+ if (head < 0)
+ break;
/* Nothing new? Wait for eventfd to tell us they refilled. */
if (head == vq->num) {
wmem = atomic_read(&sock->sk->sk_wmem_alloc);
@@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net)
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned head, out, in, log, s;
+ unsigned out, in, log, s;
+ int head;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net)
ARRAY_SIZE(vq->iov),
&out, &in,
vq_log, &log);
+ /* On error, stop handling until the next kick. */
+ if (head < 0)
+ break;
/* OK, now we need to know about added descriptors. */
if (head == vq->num) {
if (unlikely(vhost_enable_notify(vq))) {
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 3b83382..5ccd384 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
* number of output then some number of input descriptors, it's actually two
* iovecs, but we pack them into one and note how many of each there were.
*
- * This function returns the descriptor number found, or vq->num (which
- * is never a valid descriptor number) if none was found. */
-unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
- struct iovec iov[], unsigned int iov_size,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num)
+ * This function returns the descriptor number found, or vq->num (which is
+ * never a valid descriptor number) if none was found. A negative code is
+ * returned on error. */
+int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+ struct iovec iov[], unsigned int iov_size,
+ unsigned int *out_num, unsigned int *in_num,
+ struct vhost_log *log, unsigned int *log_num)
{
struct vring_desc desc;
unsigned int i, head, found = 0;
@@ -890,13 +891,13 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
if (get_user(vq->avail_idx, &vq->avail->idx)) {
vq_err(vq, "Failed to access avail idx at %p\n",
&vq->avail->idx);
- return vq->num;
+ return -EFAULT;
}
if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) {
vq_err(vq, "Guest moved used index from %u to %u",
last_avail_idx, vq->avail_idx);
- return vq->num;
+ return -EFAULT;
}
/* If there's nothing new since last we looked, return invalid. */
@@ -912,14 +913,14 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
vq_err(vq, "Failed to read head: idx %d address %p\n",
last_avail_idx,
&vq->avail->ring[last_avail_idx % vq->num]);
- return vq->num;
+ return -EFAULT;
}
/* If their number is silly, that's an error. */
if (head >= vq->num) {
vq_err(vq, "Guest says index %u > %u is available",
head, vq->num);
- return vq->num;
+ return -EINVAL;
}
/* When we start there are none of either input nor output. */
@@ -933,19 +934,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
if (i >= vq->num) {
vq_err(vq, "Desc index is %u > %u, head = %u",
i, vq->num, head);
- return vq->num;
+ return -EINVAL;
}
if (++found > vq->num) {
vq_err(vq, "Loop detected: last one at %u "
"vq size %u head %u\n",
i, vq->num, head);
- return vq->num;
+ return -EINVAL;
}
ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
if (ret) {
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
i, vq->desc + i);
- return vq->num;
+ return -EFAULT;
}
if (desc.flags & VRING_DESC_F_INDIRECT) {
ret = get_indirect(dev, vq, iov, iov_size,
@@ -954,7 +955,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
if (ret < 0) {
vq_err(vq, "Failure detected "
"in indirect descriptor at idx %d\n", i);
- return vq->num;
+ return ret;
}
continue;
}
@@ -964,7 +965,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
if (ret < 0) {
vq_err(vq, "Translation failure %d descriptor idx %d\n",
ret, i);
- return vq->num;
+ return ret;
}
if (desc.flags & VRING_DESC_F_WRITE) {
/* If this is an input descriptor,
@@ -981,7 +982,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
if (*in_num) {
vq_err(vq, "Descriptor has out after in: "
"idx %d\n", i);
- return vq->num;
+ return -EINVAL;
}
*out_num += ret;
}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 44591ba..11ee13d 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
int vhost_vq_access_ok(struct vhost_virtqueue *vq);
int vhost_log_access_ok(struct vhost_dev *);
-unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
- struct iovec iov[], unsigned int iov_count,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num);
+int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
+ struct iovec iov[], unsigned int iov_count,
+ unsigned int *out_num, unsigned int *in_num,
+ struct vhost_log *log, unsigned int *log_num);
void vhost_discard_vq_desc(struct vhost_virtqueue *);
int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
--
1.7.1.12.g42b7f
^ permalink raw reply related
* [PATCH] net/Makefile: conditionally descend to wireless and ieee802154
From: Nicolas Kaiser @ 2010-06-27 10:00 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kbuild, linux-kernel
Don't descend to wireless and ieee802154 unless they are actually used.
Signed-off-by: Nicolas Kaiser <nikai@nikai.net>
---
net/Makefile | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/Makefile b/net/Makefile
index cb7bdc1..41d4200 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -50,7 +50,7 @@ endif
obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
obj-$(CONFIG_RDS) += rds/
-obj-y += wireless/
+obj-$(CONFIG_WIRELESS) += wireless/
obj-$(CONFIG_MAC80211) += mac80211/
obj-$(CONFIG_TIPC) += tipc/
obj-$(CONFIG_NETLABEL) += netlabel/
@@ -61,7 +61,7 @@ obj-$(CONFIG_CAIF) += caif/
ifneq ($(CONFIG_DCB),)
obj-y += dcb/
endif
-obj-y += ieee802154/
+obj-$(CONFIG_IEEE802154) += ieee802154/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
--
1.7.1
^ permalink raw reply related
* [PATCH 1/2 v3] mv643xx_eth: use sw csum for big packets
From: Saeed Bishara @ 2010-06-27 10:26 UTC (permalink / raw)
To: netdev; +Cc: Saeed Bishara
Some controllers (KW, Dove) limits the TX IP/layer4 checksum offloading to a max size.
Signed-off-by: Saeed Bishara <saeed@marvell.com>
Acked-by: Lennert Buytenhek <buytenh@wantstofly.org>
---
drivers/net/mv643xx_eth.c | 9 +++++++--
include/linux/mv643xx_eth.h | 5 +++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index e345ec8..73bb8ea 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -289,6 +289,7 @@ struct mv643xx_eth_shared_private {
unsigned int t_clk;
int extended_rx_coal_limit;
int tx_bw_control;
+ int tx_csum_limit;
};
#define TX_BW_CONTROL_ABSENT 0
@@ -776,13 +777,16 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
l4i_chk = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int hdr_len;
int tag_bytes;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
- tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN;
- if (unlikely(tag_bytes & ~12)) {
+ hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
+ tag_bytes = hdr_len - ETH_HLEN;
+ if (skb->len - hdr_len > mp->shared->tx_csum_limit ||
+ unlikely(tag_bytes & ~12)) {
if (skb_checksum_help(skb) == 0)
goto no_csum;
kfree_skb(skb);
@@ -2666,6 +2670,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
* Detect hardware parameters.
*/
msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
+ msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024;
infer_hw_params(msp);
platform_set_drvdata(pdev, msp);
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index cbbbe9b..30b0c4e 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -19,6 +19,11 @@ struct mv643xx_eth_shared_platform_data {
struct mbus_dram_target_info *dram;
struct platform_device *shared_smi;
unsigned int t_clk;
+ /*
+ * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
+ * limit of 9KiB will be used.
+ */
+ int tx_csum_limit;
};
#define MV643XX_ETH_PHY_ADDR_DEFAULT 0
--
1.6.0.4
^ permalink raw reply related
* [PATCH 1/4] vsprintf: Recursive vsnprintf: Add "%pV", struct va_format
From: Joe Perches @ 2010-06-27 11:02 UTC (permalink / raw)
To: Andrew Morton, David Miller; +Cc: linux-kernel, netdev
In-Reply-To: <cover.1277636090.git.joe@perches.com>
Add the ability to print a format and va_list from a structure pointer
Allows __dev_printk to be implemented as a single printk while
minimizing string space duplication.
%pV should not be used without some mechanism to verify the
format and argument use ala __attribute__(format (printf(...))).
Signed-off-by: Joe Perches <joe@perches.com>
---
include/linux/kernel.h | 5 +++++
lib/vsprintf.c | 9 +++++++++
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 8317ec4..01dfc05 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -171,6 +171,11 @@ static inline void might_fault(void)
}
#endif
+struct va_format {
+ const char *fmt;
+ va_list *va;
+};
+
extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b8a2f54..4ee19d0 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -980,6 +980,11 @@ char *uuid_string(char *buf, char *end, const u8 *addr,
* [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
* little endian output byte order is:
* [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
+ * - 'V' For a struct va_format which contains a format string * and va_list *,
+ * call vsnprintf(->format, *->va_list).
+ * Implements a "recursive vsnprintf".
+ * Do not use this feature without some mechanism to verify the
+ * correctness of the format string and va_list arguments.
*
* Note: The difference between 'S' and 'F' is that on ia64 and ppc64
* function pointers are really function descriptors, which contain a
@@ -1025,6 +1030,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
break;
case 'U':
return uuid_string(buf, end, ptr, spec, fmt);
+ case 'V':
+ return buf + vsnprintf(buf, end - buf,
+ ((struct va_format *)ptr)->fmt,
+ *(((struct va_format *)ptr)->va));
}
spec.flags |= SMALL;
if (spec.field_width == -1) {
--
1.7.1.337.g6068.dirty
^ permalink raw reply related
* [PATCH 2/4] device.h drivers/base/core.c Convert dev_<level> logging macros to functions
From: Joe Perches @ 2010-06-27 11:02 UTC (permalink / raw)
To: Andrew Morton, David Miller; +Cc: linux-kernel, netdev
In-Reply-To: <cover.1277636090.git.joe@perches.com>
Reduces an x86 defconfig text and data ~55k, .6% smaller.
$ size vmlinux*
text data bss dec hex filename
7205273 716016 1366288 9287577 8db799 vmlinux
7258890 719768 1366288 9344946 8e97b2 vmlinux.master
Uses %pV and struct va_format
Format arguments are verified before printk
The dev_info macro is converted to _dev_info because there are
existing uses of variables named dev_info in the kernel tree
like drivers/net/pcmcia/pcnet_cs.c
A dev_info macro is created to call _dev_info
Signed-off-by: Joe Perches <joe@perches.com>
---
drivers/base/core.c | 64 +++++++++++++++++++++++++++
include/linux/device.h | 112 ++++++++++++++++++++++++++++++++++++-----------
2 files changed, 150 insertions(+), 26 deletions(-)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 9630fbd..38bbbd0 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1819,3 +1819,67 @@ void device_shutdown(void)
spin_unlock(&devices_kset->list_lock);
async_synchronize_full();
}
+
+/*
+ * Device logging functions
+ */
+
+#ifdef CONFIG_PRINTK
+
+static int __dev_printk(const char *level, const struct device *dev,
+ struct va_format *vaf)
+{
+ if (!dev)
+ return printk("%s(NULL device *): %pV", level, vaf);
+
+ return printk("%s%s %s: %pV",
+ level, dev_driver_string(dev), dev_name(dev), vaf);
+}
+
+int dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ r = __dev_printk(level, dev, &vaf);
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(dev_printk);
+
+#define define_dev_printk_level(func, kern_level) \
+int func(const struct device *dev, const char *fmt, ...) \
+{ \
+ struct va_format vaf; \
+ va_list args; \
+ int r; \
+ \
+ va_start(args, fmt); \
+ \
+ vaf.fmt = fmt; \
+ vaf.va = &args; \
+ \
+ r = __dev_printk(kern_level, dev, &vaf); \
+ va_end(args); \
+ \
+ return r; \
+} \
+EXPORT_SYMBOL(func);
+
+define_dev_printk_level(dev_emerg, KERN_EMERG);
+define_dev_printk_level(dev_alert, KERN_ALERT);
+define_dev_printk_level(dev_crit, KERN_CRIT);
+define_dev_printk_level(dev_err, KERN_ERR);
+define_dev_printk_level(dev_warn, KERN_WARNING);
+define_dev_printk_level(dev_notice, KERN_NOTICE);
+define_dev_printk_level(_dev_info, KERN_INFO);
+
+#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index 0713e10..6a8276f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -638,43 +638,103 @@ extern void sysdev_shutdown(void);
/* debugging and troubleshooting/diagnostic helpers. */
extern const char *dev_driver_string(const struct device *dev);
-#define dev_printk(level, dev, format, arg...) \
- printk(level "%s %s: " format , dev_driver_string(dev) , \
- dev_name(dev) , ## arg)
-
-#define dev_emerg(dev, format, arg...) \
- dev_printk(KERN_EMERG , dev , format , ## arg)
-#define dev_alert(dev, format, arg...) \
- dev_printk(KERN_ALERT , dev , format , ## arg)
-#define dev_crit(dev, format, arg...) \
- dev_printk(KERN_CRIT , dev , format , ## arg)
-#define dev_err(dev, format, arg...) \
- dev_printk(KERN_ERR , dev , format , ## arg)
-#define dev_warn(dev, format, arg...) \
- dev_printk(KERN_WARNING , dev , format , ## arg)
-#define dev_notice(dev, format, arg...) \
- dev_printk(KERN_NOTICE , dev , format , ## arg)
-#define dev_info(dev, format, arg...) \
- dev_printk(KERN_INFO , dev , format , ## arg)
+
+
+#ifdef CONFIG_PRINTK
+
+extern int dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern int dev_emerg(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int dev_alert(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int dev_crit(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int dev_err(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int dev_warn(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int dev_notice(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int _dev_info(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+#else
+
+static inline int dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+static inline int dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...)
+ { return 0; }
+
+static inline int dev_emerg(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_emerg(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int dev_crit(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_crit(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int dev_alert(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_alert(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int dev_err(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_err(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int dev_warn(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_warn(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int dev_notice(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int dev_notice(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+static inline int _dev_info(const struct device *dev, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+static inline int _dev_info(const struct device *dev, const char *fmt, ...)
+ { return 0; }
+
+#endif
+
+/*
+ * Stupid hackaround for existing uses of non-printk uses dev_info
+ *
+ * Note that the definition of dev_info below is actually _dev_info
+ * and a macro is used to avoid redefining dev_info
+ */
+
+#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
#if defined(DEBUG)
#define dev_dbg(dev, format, arg...) \
- dev_printk(KERN_DEBUG , dev , format , ## arg)
+ dev_printk(KERN_DEBUG, dev, format, ##arg)
#elif defined(CONFIG_DYNAMIC_DEBUG)
-#define dev_dbg(dev, format, ...) do { \
+#define dev_dbg(dev, format, ...) \
+do { \
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
- } while (0)
+} while (0)
#else
-#define dev_dbg(dev, format, arg...) \
- ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+#define dev_dbg(dev, format, arg...) \
+({ \
+ if (0) \
+ dev_printk(KERN_DEBUG, dev, format, ##arg); \
+ 0; \
+})
#endif
#ifdef VERBOSE_DEBUG
#define dev_vdbg dev_dbg
#else
-
-#define dev_vdbg(dev, format, arg...) \
- ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+#define dev_vdbg(dev, format, arg...) \
+({ \
+ if (0) \
+ dev_printk(KERN_DEBUG, dev, format, ##arg); \
+ 0; \
+})
#endif
/*
--
1.7.1.337.g6068.dirty
^ permalink raw reply related
* [PATCH 3/4] netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions
From: Joe Perches @ 2010-06-27 11:02 UTC (permalink / raw)
To: Andrew Morton, David Miller; +Cc: linux-kernel, netdev
In-Reply-To: <cover.1277636090.git.joe@perches.com>
Reduces an x86 defconfig text and data ~2k.
text is smaller, data is larger.
$ size vmlinux*
text data bss dec hex filename
7198862 720112 1366288 9285262 8dae8e vmlinux
7205273 716016 1366288 9287577 8db799 vmlinux.device_h
Uses %pV and struct va_format
Format arguments are verified before printk
Signed-off-by: Joe Perches <joe@perches.com>
---
include/linux/netdevice.h | 36 ++++++++++++-------------
net/core/dev.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 19 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 40291f3..7f3197d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2227,25 +2227,23 @@ static inline const char *netdev_name(const struct net_device *dev)
return dev->name;
}
-#define netdev_printk(level, netdev, format, args...) \
- dev_printk(level, (netdev)->dev.parent, \
- "%s: " format, \
- netdev_name(netdev), ##args)
-
-#define netdev_emerg(dev, format, args...) \
- netdev_printk(KERN_EMERG, dev, format, ##args)
-#define netdev_alert(dev, format, args...) \
- netdev_printk(KERN_ALERT, dev, format, ##args)
-#define netdev_crit(dev, format, args...) \
- netdev_printk(KERN_CRIT, dev, format, ##args)
-#define netdev_err(dev, format, args...) \
- netdev_printk(KERN_ERR, dev, format, ##args)
-#define netdev_warn(dev, format, args...) \
- netdev_printk(KERN_WARNING, dev, format, ##args)
-#define netdev_notice(dev, format, args...) \
- netdev_printk(KERN_NOTICE, dev, format, ##args)
-#define netdev_info(dev, format, args...) \
- netdev_printk(KERN_INFO, dev, format, ##args)
+extern int netdev_printk(const char *level, const struct net_device *dev,
+ const char *format, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern int netdev_emerg(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_alert(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_crit(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_err(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_warn(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_notice(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int netdev_info(const struct net_device *dev, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
#if defined(DEBUG)
#define netdev_dbg(__dev, format, args...) \
diff --git a/net/core/dev.c b/net/core/dev.c
index 2b3bf53..6f6e1f4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5790,6 +5790,68 @@ char *netdev_drivername(const struct net_device *dev, char *buffer, int len)
return buffer;
}
+static int __netdev_printk(const char *level, const struct net_device *dev,
+ struct va_format *vaf)
+{
+ int r;
+
+ if (dev && dev->dev.parent)
+ r = dev_printk(level, dev->dev.parent, "%s: %pV",
+ netdev_name(dev), vaf);
+ else if (dev)
+ r = printk("%s%s: %pV", level, netdev_name(dev), vaf);
+ else
+ r = printk("%s(NULL net_device): %pV", level, vaf);
+
+ return r;
+}
+
+int netdev_printk(const char *level, const struct net_device *dev,
+ const char *format, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, format);
+
+ vaf.fmt = format;
+ vaf.va = &args;
+
+ r = __netdev_printk(level, dev, &vaf);
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(netdev_printk);
+
+#define define_netdev_printk_level(func, level) \
+int func(const struct net_device *dev, const char *fmt, ...) \
+{ \
+ int r; \
+ struct va_format vaf; \
+ va_list args; \
+ \
+ va_start(args, fmt); \
+ \
+ vaf.fmt = fmt; \
+ vaf.va = &args; \
+ \
+ r = __netdev_printk(level, dev, &vaf); \
+ va_end(args); \
+ \
+ return r; \
+} \
+EXPORT_SYMBOL(func);
+
+define_netdev_printk_level(netdev_emerg, KERN_EMERG);
+define_netdev_printk_level(netdev_alert, KERN_ALERT);
+define_netdev_printk_level(netdev_crit, KERN_CRIT);
+define_netdev_printk_level(netdev_err, KERN_ERR);
+define_netdev_printk_level(netdev_warn, KERN_WARNING);
+define_netdev_printk_level(netdev_notice, KERN_NOTICE);
+define_netdev_printk_level(netdev_info, KERN_INFO);
+
static void __net_exit netdev_exit(struct net *net)
{
kfree(net->dev_name_head);
--
1.7.1.337.g6068.dirty
^ permalink raw reply related
* [PATCH 0/4] Introduce and use printk pointer extension %pV
From: Joe Perches @ 2010-06-27 11:02 UTC (permalink / raw)
To: Andrew Morton, David Miller; +Cc: linux-kernel, netdev
Recursive printk can reduce the total image size of an x86 defconfig about 1%
by reducing duplicated KERN_<level> strings and centralizing the functions
used by macros in new separate functions.
Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format
device.h drivers/base/core.c Convert dev_<level> logging macros to functions
netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions
netdevice.h: Change netif_<level> macros to call netdev_<level> functions
drivers/base/core.c | 64 +++++++++++++++++++++++++
include/linux/device.h | 112 ++++++++++++++++++++++++++++++++++----------
include/linux/kernel.h | 5 ++
include/linux/netdevice.h | 56 ++++++++++++----------
lib/vsprintf.c | 9 ++++
net/core/dev.c | 62 +++++++++++++++++++++++++
6 files changed, 256 insertions(+), 52 deletions(-)
^ 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