* [v4 Patch 3/3] bonding: make bonding support netpoll
From: Amerigo Wang @ 2010-04-27 7:56 UTC (permalink / raw)
To: linux-kernel
Cc: Matt Mackall, netdev, bridge, Andy Gospodarek, Neil Horman,
Amerigo Wang, Jeff Moyer, Stephen Hemminger, bonding-devel,
Jay Vosburgh, David Miller
In-Reply-To: <20100427075937.4908.18468.sendpatchset@localhost.localdomain>
Based on Andy's work, but I modified a lot.
Similar to the patch for bridge, this patch does:
1) implement the 2 methods to support netpoll for bonding;
2) modify netpoll during forwarding packets via bonding;
3) disable netpoll support of bonding when a netpoll-unabled device
is added to bonding;
4) enable netpoll support when all underlying devices support netpoll.
Cc: Andy Gospodarek <gospo@redhat.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Matt Mackall <mpm@selenic.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Jay Vosburgh <fubar@us.ibm.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: WANG Cong <amwang@redhat.com>
---
Index: linux-2.6/drivers/net/bonding/bond_main.c
===================================================================
--- linux-2.6.orig/drivers/net/bonding/bond_main.c
+++ linux-2.6/drivers/net/bonding/bond_main.c
@@ -59,6 +59,7 @@
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
+#include <linux/netpoll.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/etherdevice.h>
@@ -430,7 +431,18 @@ int bond_dev_queue_xmit(struct bonding *
}
skb->priority = 1;
- dev_queue_xmit(skb);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
+ struct netpoll *np = bond->dev->npinfo->netpoll;
+ slave_dev->npinfo = bond->dev->npinfo;
+ np->real_dev = np->dev = skb->dev;
+ slave_dev->priv_flags |= IFF_IN_NETPOLL;
+ netpoll_send_skb(np, skb);
+ slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
+ np->dev = bond->dev;
+ } else
+#endif
+ dev_queue_xmit(skb);
return 0;
}
@@ -1329,6 +1341,61 @@ static void bond_detach_slave(struct bon
bond->slave_cnt--;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * You must hold read lock on bond->lock before calling this.
+ */
+static bool slaves_support_netpoll(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ int i = 0;
+ bool ret = true;
+
+ bond_for_each_slave(bond, slave, i) {
+ if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL)
+ || !slave->dev->netdev_ops->ndo_poll_controller)
+ ret = false;
+ }
+ return i != 0 && ret;
+}
+
+static void bond_poll_controller(struct net_device *bond_dev)
+{
+ struct net_device *dev = bond_dev->npinfo->netpoll->real_dev;
+ if (dev != bond_dev)
+ netpoll_poll_dev(dev);
+}
+
+static void bond_netpoll_cleanup(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ const struct net_device_ops *ops;
+ int i;
+
+ read_lock(&bond->lock);
+ bond_dev->npinfo = NULL;
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->dev) {
+ ops = slave->dev->netdev_ops;
+ if (ops->ndo_netpoll_cleanup)
+ ops->ndo_netpoll_cleanup(slave->dev);
+ else
+ slave->dev->npinfo = NULL;
+ }
+ }
+ read_unlock(&bond->lock);
+}
+
+#else
+
+static void bond_netpoll_cleanup(struct net_device *bond_dev)
+{
+}
+
+#endif
+
/*---------------------------------- IOCTL ----------------------------------*/
static int bond_sethwaddr(struct net_device *bond_dev,
@@ -1735,6 +1802,18 @@ int bond_enslave(struct net_device *bond
bond_set_carrier(bond);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (bond_dev->npinfo)
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+ bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
+ pr_info("New slave device %s does not support netpoll\n",
+ slave_dev->name);
+ pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+ }
+#endif
read_unlock(&bond->lock);
res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1801,6 +1880,7 @@ int bond_release(struct net_device *bond
return -EINVAL;
}
+ netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE);
write_lock_bh(&bond->lock);
slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -1929,6 +2009,17 @@ int bond_release(struct net_device *bond
netdev_set_master(slave_dev, NULL);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ read_lock_bh(&bond->lock);
+ if (slaves_support_netpoll(bond_dev))
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ read_unlock_bh(&bond->lock);
+ if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
+ slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
+ else
+ slave_dev->npinfo = NULL;
+#endif
+
/* close slave before restoring its mac address */
dev_close(slave_dev);
@@ -4448,6 +4539,10 @@ static const struct net_device_ops bond_
.ndo_vlan_rx_register = bond_vlan_rx_register,
.ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_netpoll_cleanup = bond_netpoll_cleanup,
+ .ndo_poll_controller = bond_poll_controller,
+#endif
};
static void bond_destructor(struct net_device *bond_dev)
@@ -4541,6 +4636,8 @@ static void bond_uninit(struct net_devic
{
struct bonding *bond = netdev_priv(bond_dev);
+ bond_netpoll_cleanup(bond_dev);
+
/* Release the bonded slaves */
bond_release_all(bond_dev);
^ permalink raw reply
* Re: Intel Pro1000 on CN5020, hangs Uboot
From: Jack Daniel @ 2010-04-27 8:59 UTC (permalink / raw)
To: netdev; +Cc: davem
In-Reply-To: <y2pf6b367b71004140118s93d7b47rfa88399bfbe5b91b@mail.gmail.com>
Just an update that "Intel Pro/1000 MT Desktop Adapter" have problems
booting on an Octeon 5xxx. The "GT" and "PT" adapters seem to work
fine.
Regards,
Jack
On Wed, Apr 14, 2010 at 1:48 PM, Jack Daniel <wanders.thirst@gmail.com> wrote:
> Hi,
>
> I have a OCTEON CN5020, on which I tried plugging in an Intel Pro 1000
> PCI NIC. But Uboot hangs with a trap exception. Uboot has no problems
> with a Realtek RTL8139 NIC PCI card that supports 100MBps. Could
> someone tell me the reason for such a behaviour?
>
> Regards,
> Jack
>
>
> Uboot Version (as reported by Uboot) : U-Boot 1.1.1 (Development
> build, svnversion: u-boot:47725, exec:47725)
> Uboot start up message:
> PAL rev: 1.01, MCU rev: 1.07, CPU voltage: 1.20
> DRAM: 512 MB
> Clearing DRAM....... done
> Flash: 8 MB
> BIST check passed.
> Starting PCI
> PCI Status: PCI 32-bit
> Reg: 0x0 0x0
> Reg: 0x1 0x62
> Reg: 0x2 0x0
> Reg: 0x3 0x0
> Reg: 0x4 0x0
> Reg: 0x5 0xE
> Reg: 0x6 0x1
> Reg: 0x7 0xFFFFFFFFC00D5C70
> Reg: 0x8 0x800119040000000E
> Reg: 0x9 0x61784
> Reg: 0xA 0xFFFFFFFFC0000A4C
> Reg: 0xB 0xFFFFFFFFC0062208
> Reg: 0xC 0xFFFFFFFFC0062550
> Reg: 0xD 0xFFFFFFFFC005E4A0
> Reg: 0xE 0x20
> Reg: 0xF 0x0
> Reg: 0x10 0xFFFFFFFFC00D5CA0
> Reg: 0x11 0xFFFFFFFFC008F490
> Reg: 0x12 0x0
> Reg: 0x13 0x0
> Reg: 0x14 0x0
> Reg: 0x15 0x0
> Reg: 0x16 0xFF00
> Reg: 0x17 0xFFFFFFFFC00D5CA6
> Reg: 0x18 0xFFFFFFFFC0062550
> Reg: 0x19 0xFFFFFFFFC0038E24
> Reg: 0x1A 0xFFFFFFFFFFFF8000
> Reg: 0x1B 0x30
> Reg: 0x1C 0xFFFFFFFFBFC621D0
> Reg: 0x1D 0xFFFFFFFFFFFF97F8
> Reg: 0x1E 0xFFFFFFFFC00D5CA4
> Reg: 0x1F 0xFFFFFFFFBFC00AE0
> status: 0x504000E7
> cause: 0x4000801C
> epc: 0xFFFFFFFFC0038EC8
> badvaddr: 0x0
>
^ permalink raw reply
* [PATCH 0/3] [RFC] ptp: IEEE 1588 clock support
From: Richard Cochran @ 2010-04-27 9:13 UTC (permalink / raw)
To: netdev
Now and again there has been some talk on this list of adding PTP
support into Linux. One part of the picture is already in place, the
SO_TIMESTAMPING API for hardware time stamping. It has been pointed
out that this API is not perfect, however, it is good enough for many
real world uses of IEEE 1588. The second needed part has not, AFAICT,
ever been addressed.
Here I offer an early draft of an idea how to bring the missing
functionality into Linux. I don't yet have all of the features
implemented, as described below. Still I would like to get your
feedback concerning this idea before getting too far into it. I do
have all of the hardware mentioned at hand, so I have a good idea that
the proposed API covers the features of those clocks.
Thanks in advance for your comments,
Richard
* PTP infrastructure for Linux
This patch set introduces support for IEEE 1588 PTP clocks in
Linux. Together with the SO_TIMESTAMPING socket options, this
presents standardized method for developing PTP user space programs,
synchronizing Linux with external clocks, and using the ancillary
features of PTP hardware clocks.
A new class driver exports a kernel interface for specific clock
drivers and a user space interface. The infrastructure supports a
complete set of PTP functionality.
+ Basic clock operations
- Set time
- Get time
- Shift the clock by a given offset atomically
- Adjust clock frequency
+ Ancillary clock features
- One short or periodic alarms, with signal delivery to user program
- Time stamp external events
- Period output signals configurable from user space
- Synchronization of the Linux system time via the PPS subsystem
** PTP kernel API
A PTP clock driver registers itself with the class driver. The
class driver handles all of the dealings with user space. The
author of a clock driver need only implement the details of
programming the clock hardware. The clock driver notifies the class
driver of asynchronous events (alarms and external time stamps) via
a simple message passing interface.
The class driver supports multiple PTP clock drivers. In normal use
cases, only one PTP clock is needed. However, for testing and
development, it can be useful to have more than one clock in a
single system, in order to allow performance comparisons.
** PTP user space API
The class driver creates a character device for each registered PTP
clock. User space programs may control the clock via standardized
ioctls. A program may query, enable, configure, and disable the
ancillary clock features. User space can receive time stamped
events via blocking read() and poll(). One shot and periodic
signals may be configured via an ioctl API with similar semantics
to the POSIX timer_settime() system call.
** Supported hardware
+ Standard Linux system timer
- No special PTP features
- For use with software time stamping
+ Freescale eTSEC gianfar
- 2 Time stamp external triggers, programmable polarity (opt. interrupt)
- 2 Alarm registers (optional interrupt)
- 3 Periodic signals (optional interrupt)
+ National DP83640
- 6 GPIOs programmable as inputs or outputs
- 6 GPIOs with dedicated functions (LED/JTAG/clock) can also be
used as general inputs or outputs
- GPIO inputs can time stamp external triggers
- GPIO outputs can produce periodic signals
- 1 interrupt pin
+ Intel IXP465
- Auxiliary Slave/Master Mode Snapshot (optional interrupt)
- Target Time (optional interrupt)
Richard Cochran (3):
ptp: Added a brand new class driver for ptp clocks.
ptp: Added a clock that uses the Linux system time.
ptp: Added a clock that uses the eTSEC found on the MPC85xx.
Documentation/ptp/testptp.c | 130 +++++++++++++++++
Documentation/ptp/testptp.mk | 33 +++++
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/net/Makefile | 1 +
drivers/net/gianfar_ptp.c | 269 +++++++++++++++++++++++++++++++++++
drivers/net/gianfar_ptp_reg.h | 107 ++++++++++++++
drivers/ptp/Kconfig | 51 +++++++
drivers/ptp/Makefile | 6 +
drivers/ptp/ptp_clock.c | 287 ++++++++++++++++++++++++++++++++++++++
drivers/ptp/ptp_linux.c | 119 ++++++++++++++++
include/linux/Kbuild | 1 +
include/linux/ptp_clock.h | 37 +++++
include/linux/ptp_clock_kernel.h | 132 +++++++++++++++++
kernel/time/ntp.c | 2 +
15 files changed, 1178 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ptp/testptp.c
create mode 100644 Documentation/ptp/testptp.mk
create mode 100644 drivers/net/gianfar_ptp.c
create mode 100644 drivers/net/gianfar_ptp_reg.h
create mode 100644 drivers/ptp/Kconfig
create mode 100644 drivers/ptp/Makefile
create mode 100644 drivers/ptp/ptp_clock.c
create mode 100644 drivers/ptp/ptp_linux.c
create mode 100644 include/linux/ptp_clock.h
create mode 100644 include/linux/ptp_clock_kernel.h
^ permalink raw reply
* [PATCH 1/3] ptp: Added a brand new class driver for ptp clocks.
From: Richard Cochran @ 2010-04-27 9:14 UTC (permalink / raw)
To: netdev
This patch adds an infrastructure for hardware clocks that implement
IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a
registration method to particular hardware clock drivers. Each clock is
exposed to user space as a character device with ioctls that allow tuning
of the PTP clock.
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
Documentation/ptp/testptp.c | 130 +++++++++++++++++
Documentation/ptp/testptp.mk | 33 +++++
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/ptp/Kconfig | 26 ++++
drivers/ptp/Makefile | 5 +
drivers/ptp/ptp_clock.c | 287 ++++++++++++++++++++++++++++++++++++++
include/linux/Kbuild | 1 +
include/linux/ptp_clock.h | 37 +++++
include/linux/ptp_clock_kernel.h | 132 +++++++++++++++++
10 files changed, 654 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ptp/testptp.c
create mode 100644 Documentation/ptp/testptp.mk
create mode 100644 drivers/ptp/Kconfig
create mode 100644 drivers/ptp/Makefile
create mode 100644 drivers/ptp/ptp_clock.c
create mode 100644 include/linux/ptp_clock.h
create mode 100644 include/linux/ptp_clock_kernel.h
diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c
new file mode 100644
index 0000000..d3ad918
--- /dev/null
+++ b/Documentation/ptp/testptp.c
@@ -0,0 +1,130 @@
+/*
+ * PTP 1588 clock support - User space test program
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/ptp_clock.h>
+
+static void usage (char* progname)
+{
+ fprintf(stderr,
+ "usage: %s [options] \n"
+ " -d name device to open \n"
+ " -f val adjust the ptp clock frequency by 'val' PPB \n"
+ " -g get the ptp clock time \n"
+ " -h prints this message \n"
+ " -s set the ptp clock time from the system time \n"
+ " -t val shift the ptp clock time by 'val' seconds \n"
+ " -v query the ptp clock api version \n"
+ ,progname);
+}
+
+int main(int argc,char *argv[])
+{
+ struct timespec ts;
+ char *progname;
+ int c, fd, val=0;
+
+ char *device = "/dev/ptp_clock_0";
+ int adjfreq=0x7fffffff;
+ int adjtime=0;
+ int gettime=0;
+ int settime=0;
+ int version=0;
+
+ progname = strrchr(argv[0],'/');
+ progname = progname ? 1+progname : argv[0];
+ while (EOF != (c = getopt(argc, argv, "d:f:ghst:v"))) {
+ switch (c) {
+ case 'd': device = optarg; break;
+ case 'f': adjfreq = atoi(optarg); break;
+ case 'g': gettime = 1; break;
+ case 's': settime = 1; break;
+ case 't': adjtime = atoi(optarg); break;
+ case 'v': version = 1; break;
+ case 'h': usage(progname); return 0;
+ case '?': usage(progname); return -1;
+ default: usage(progname); return -1;
+ }
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr,"cannot open %s: %s", device, strerror(errno));
+ return -1;
+ }
+
+ if (version) {
+ if (ioctl(fd, PTP_CLOCK_APIVERS, &val)) {
+ perror("PTP_CLOCK_APIVERS");
+ } else {
+ printf("version = 0x%08x \n",val);
+ }
+ }
+
+ if (0x7fffffff != adjfreq) {
+ if (ioctl(fd, PTP_CLOCK_ADJFREQ, adjfreq)) {
+ perror("PTP_CLOCK_ADJFREQ");
+ } else {
+ puts("frequency adjustment okay");
+ }
+ }
+
+ if (adjtime) {
+ ts.tv_sec = adjtime;
+ ts.tv_nsec = 0;
+ if (ioctl(fd, PTP_CLOCK_ADJTIME, &ts)) {
+ perror("PTP_CLOCK_ADJTIME");
+ } else {
+ puts("time shift okay");
+ }
+ }
+
+ if (gettime) {
+ if (ioctl(fd, PTP_CLOCK_GETTIME, &ts)) {
+ perror("PTP_CLOCK_GETTIME");
+ } else {
+ printf("clock time: %ld.%09ld or %s",
+ ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec));
+ }
+ }
+
+ if (settime) {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ if (ioctl(fd, PTP_CLOCK_SETTIME, &ts)) {
+ perror("PTP_CLOCK_SETTIME");
+ } else {
+ puts("set time okay");
+ }
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/Documentation/ptp/testptp.mk b/Documentation/ptp/testptp.mk
new file mode 100644
index 0000000..4ef2d97
--- /dev/null
+++ b/Documentation/ptp/testptp.mk
@@ -0,0 +1,33 @@
+# PTP 1588 clock support - User space test program
+#
+# Copyright (C) 2010 OMICRON electronics GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+CC = $(CROSS_COMPILE)gcc
+INC = -I$(KBUILD_OUTPUT)/usr/include
+CFLAGS = -Wall $(INC)
+LDLIBS = -lrt
+PROGS = testptp
+
+all: $(PROGS)
+
+testptp: testptp.o
+
+clean:
+ rm -f testptp.o
+
+distclean: clean
+ rm -f $(PROGS)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index a2b902f..774fbd7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/spi/Kconfig"
source "drivers/pps/Kconfig"
+source "drivers/ptp/Kconfig"
+
source "drivers/gpio/Kconfig"
source "drivers/w1/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 34f1e10..7dea7c8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/ media/
obj-$(CONFIG_PPS) += pps/
+obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
new file mode 100644
index 0000000..458d0fe
--- /dev/null
+++ b/drivers/ptp/Kconfig
@@ -0,0 +1,26 @@
+#
+# PTP clock support configuration
+#
+
+menu "PTP clock support"
+
+config PTP_1588_CLOCK
+ tristate "PTP clock support"
+ depends on EXPERIMENTAL
+ help
+ The IEEE 1588 standard defines a method to precisely
+ synchronize distributed clocks over Ethernet networks. The
+ standard defines a Precision Time Protocol (PTP), which can
+ be used to achieve synchronization within a few dozen
+ microseconds. In addition, with the help of special hardware
+ time stamping units, it can be possible to achieve
+ synchronization to within a few hundred nanoseconds.
+
+ This driver adds support for PTP clocks as character
+ devices. If you want to use a PTP clock, then you should
+ also enable at least one clock driver as well.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ptp_clock.ko.
+
+endmenu
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
new file mode 100644
index 0000000..b86695c
--- /dev/null
+++ b/drivers/ptp/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for PTP 1588 clock support.
+#
+
+obj-$(CONFIG_PTP_1588_CLOCK) += ptp_clock.o
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
new file mode 100644
index 0000000..a1c3846
--- /dev/null
+++ b/drivers/ptp/ptp_clock.c
@@ -0,0 +1,287 @@
+/*
+ * PTP 1588 clock support
+ *
+ * Partially adapted from the Linux PPS driver.
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/ptp_clock.h>
+
+#define PTP_MAX_CLOCKS 4
+
+struct ptp_clock {
+ struct cdev cdev;
+ struct device *dev;
+ struct ptp_clock_info *info;
+ dev_t devid;
+ int index; /* index into clocks[], also the minor number */
+ struct semaphore mux; /* one process at a time on a device */
+};
+
+
+/* private globals */
+
+static const struct file_operations ptp_fops;
+static dev_t ptp_devt;
+static struct class *ptp_class;
+struct ptp_clock *clocks[PTP_MAX_CLOCKS];
+DEFINE_SPINLOCK(clocks_lock);
+
+/* public interface */
+
+int ptp_clock_register(struct ptp_clock_info *info)
+{
+ struct ptp_clock *ptp;
+ int err, i, index, major = MAJOR(ptp_devt);
+ unsigned long flags;
+
+ /* Find a free clock slot and reserve it. */
+ spin_lock_irqsave(&clocks_lock, flags);
+ for (i = 0; i < PTP_MAX_CLOCKS; i++) {
+ if (!clocks[i]) {
+ clocks[i] = (struct ptp_clock*)1;
+ break;
+ }
+ }
+ index = i < PTP_MAX_CLOCKS ? i : -1;
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ if (-1 == index)
+ return -EBUSY;
+
+ /* Initialize a clock structure. */
+ err = -ENOMEM;
+ ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
+ if (ptp == NULL)
+ goto no_clock;
+
+ clocks[index] = ptp;
+
+ ptp->info = info;
+ ptp->devid = MKDEV(major, index);
+ ptp->index = index;
+ init_MUTEX(&ptp->mux);
+
+ /* Create a new device in our class. */
+ ptp->dev = device_create(ptp_class, NULL, ptp->devid, ptp,
+ "ptp_clock_%d", ptp->index);
+ if (IS_ERR(ptp->dev))
+ goto no_device;
+ dev_set_drvdata(ptp->dev, ptp);
+
+ /* Register a character device. */
+ cdev_init(&ptp->cdev, &ptp_fops);
+ ptp->cdev.owner = info->owner;
+ err = cdev_add(&ptp->cdev, ptp->devid, 1);
+ if (err)
+ goto no_cdev;
+
+ return 0;
+
+no_cdev:
+ device_destroy(ptp_class, ptp->devid);
+no_device:
+ kfree(ptp);
+no_clock:
+ clocks[index] = NULL;
+ return err;
+}
+EXPORT_SYMBOL(ptp_clock_register);
+
+int ptp_clock_unregister(struct ptp_clock_info *info)
+{
+ struct ptp_clock *ptp = NULL;
+ int i;
+
+ for (i = 0; i < PTP_MAX_CLOCKS; i++) {
+ if (clocks[i] && !strcmp(clocks[i]->info->name, info->name)) {
+ ptp = clocks[i];
+ break;
+ }
+ }
+ if (!ptp)
+ return -EINVAL;
+
+ cdev_del(&ptp->cdev);
+ device_destroy(ptp_class, ptp->devid);
+ kfree(ptp);
+ clocks[i] = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(ptp_clock_unregister);
+
+void ptp_clock_event(struct ptp_clock_event event)
+{
+}
+EXPORT_SYMBOL(ptp_clock_event);
+
+/* character device operations */
+
+static int ptp_ioctl(struct inode *node, struct file *fp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ptp_clock *ptp = fp->private_data;
+ struct ptp_clock_info *ops = ptp->info;
+ void *priv = ops->priv;
+ struct timespec ts;
+ int err = 0;
+
+ switch (cmd) {
+
+ case PTP_CLOCK_APIVERS:
+ err = put_user(PTP_CLOCK_VERSION, (u32 __user*)arg);
+ break;
+
+ case PTP_CLOCK_ADJFREQ:
+ err = ops->adjfreq(priv, arg);
+ break;
+
+ case PTP_CLOCK_ADJTIME:
+ if (copy_from_user(&ts, (void __user*)arg, sizeof(ts)))
+ err = -EFAULT;
+ else
+ err = ops->adjtime(priv, &ts);
+ break;
+
+ case PTP_CLOCK_GETTIME:
+ err = ops->gettime(priv, &ts);
+ if (err)
+ break;
+ err = copy_to_user((void __user*)arg, &ts, sizeof(ts));
+ break;
+
+ case PTP_CLOCK_SETTIME:
+ if (copy_from_user(&ts, (void __user*)arg, sizeof(ts)))
+ err = -EFAULT;
+ else
+ err = ops->settime(priv, &ts);
+ break;
+
+ default:
+ err = -ENOTTY;
+ break;
+ }
+ return err;
+}
+
+static int ptp_open(struct inode *inode, struct file *fp)
+{
+ struct ptp_clock *ptp;
+ ptp = container_of(inode->i_cdev, struct ptp_clock, cdev);
+
+ if (down_interruptible(&ptp->mux))
+ return -ERESTARTSYS;
+
+ fp->private_data = ptp;
+
+ return 0;
+}
+
+static unsigned int ptp_poll(struct file *fp, poll_table *wait)
+{
+ return 0;
+}
+
+static int ptp_release(struct inode *inode, struct file *fp)
+{
+ struct ptp_clock *ptp = fp->private_data;
+ up(&ptp->mux);
+ return 0;
+}
+
+static const struct file_operations ptp_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = ptp_ioctl,
+ .open = ptp_open,
+ .poll = ptp_poll,
+ .release = ptp_release,
+};
+
+/* sysfs */
+
+static ssize_t ptp_show_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ptp_clock *ptp = dev_get_drvdata(dev);
+ return sprintf(buf,
+ "maximum adjustment: %d\n"
+ "programmable alarms: %d\n"
+ "external timestamps: %d\n"
+ "periodic outputs: %d\n"
+ "has pps: %d\n"
+ "device index: %d\n"
+ ,ptp->info->max_adj
+ ,ptp->info->n_alarm
+ ,ptp->info->n_ext_ts
+ ,ptp->info->n_per_out
+ ,ptp->info->pps
+ ,ptp->index);
+}
+
+struct device_attribute ptp_attrs[] = {
+ __ATTR(capabilities, S_IRUGO, ptp_show_status, NULL),
+ __ATTR_NULL,
+};
+
+/* module operations */
+
+static void __exit ptp_exit(void)
+{
+ class_destroy(ptp_class);
+ unregister_chrdev_region(ptp_devt, PTP_MAX_CLOCKS);
+}
+
+static int __init ptp_init(void)
+{
+ int err;
+
+ ptp_class = class_create(THIS_MODULE, "ptp");
+ if (!ptp_class) {
+ printk(KERN_ERR "ptp: failed to allocate class\n");
+ return -ENOMEM;
+ }
+ ptp_class->dev_attrs = ptp_attrs;
+
+ err = alloc_chrdev_region(&ptp_devt, 0, PTP_MAX_CLOCKS, "ptp");
+ if (err < 0) {
+ printk(KERN_ERR "ptp: failed to allocate char device region\n");
+ goto no_region;
+ }
+
+ pr_info("PTP clock support registered\n");
+ return 0;
+
+no_region:
+ class_destroy(ptp_class);
+ return err;
+}
+
+subsys_initcall(ptp_init);
+module_exit(ptp_exit);
+
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_DESCRIPTION("PTP clocks support");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 2fc8e14..2d616cb 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -318,6 +318,7 @@ unifdef-y += poll.h
unifdef-y += ppp_defs.h
unifdef-y += ppp-comp.h
unifdef-y += pps.h
+unifdef-y += ptp_clock.h
unifdef-y += ptrace.h
unifdef-y += quota.h
unifdef-y += random.h
diff --git a/include/linux/ptp_clock.h b/include/linux/ptp_clock.h
new file mode 100644
index 0000000..5064b19
--- /dev/null
+++ b/include/linux/ptp_clock.h
@@ -0,0 +1,37 @@
+/*
+ * PTP 1588 clock support - user space interface
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _PTP_CLOCK_H_
+#define _PTP_CLOCK_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define PTP_CLOCK_VERSION 0x00000001
+
+#define PTP_CLK_MAGIC '='
+
+#define PTP_CLOCK_APIVERS _IOR (PTP_CLK_MAGIC, 1, __u32)
+#define PTP_CLOCK_ADJFREQ _IO (PTP_CLK_MAGIC, 2)
+#define PTP_CLOCK_ADJTIME _IOW (PTP_CLK_MAGIC, 3, struct timespec)
+#define PTP_CLOCK_GETTIME _IOR (PTP_CLK_MAGIC, 4, struct timespec)
+#define PTP_CLOCK_SETTIME _IOW (PTP_CLK_MAGIC, 5, struct timespec)
+
+#endif
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
new file mode 100644
index 0000000..fd80969
--- /dev/null
+++ b/include/linux/ptp_clock_kernel.h
@@ -0,0 +1,132 @@
+/*
+ * PTP 1588 clock support
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _PTP_CLOCK_KERNEL_H_
+#define _PTP_CLOCK_KERNEL_H_
+
+enum ptp_clock_events {
+ PTP_CLOCK_ALARM,
+ PTP_CLOCK_EXTTS,
+ PTP_CLOCK_PEROUT,
+ PTP_CLOCK_PPS,
+};
+
+/**
+ * struct ptp_clock_request - parameter for the enable() operation
+ *
+ * @type: One of the ptp_clock_events enumeration values.
+ * @index: Selects one resource of the given type.
+ * @ts: Desired one shot or recurring period for alarms and output signals.
+ */
+
+struct ptp_clock_request {
+ int type;
+ int index;
+ struct itimerspec ts;
+};
+
+/**
+ * struct ptp_clock_info - decribes a PTP hardware clock
+ *
+ * @owner: The clock driver should set to THIS_MODULE.
+ * @name: A short name to identify the clock.
+ * @max_adj: The maximum possible frequency adjustment, in parts per billon.
+ * @n_alarm: The number of programmable alarms.
+ * @n_ext_ts: The number of external time stamp channels.
+ * @n_per_out: The number of programmable periodic signals.
+ * @pps: Indicates whether the clock supports a PPS callback.
+ * @priv: Passed to the clock operations, for the driver's private use.
+ *
+ * clock operations
+ *
+ * @adjfreq: Adjusts the frequency of the hardware clock.
+ * parameter delta: Desired period change in parts per billion.
+ *
+ * @adjtime: Shifts the time of the hardware clock.
+ * parameter ts: Desired change in seconds and nanoseconds.
+ *
+ * @gettime: Reads the current time from the hardware clock.
+ * parameter ts: Holds the result.
+ *
+ * @settime: Set the current time on the hardware clock.
+ * parameter ts: Time value to set.
+ *
+ * @enable: Request driver to enable or disable an ancillary feature.
+ * parameter request: Desired resource to enable or disable.
+ * parameter on: Caller passes one to enable or zero to disable.
+ *
+ * The callbacks must all return zero on success, non-zero otherwise.
+ */
+
+struct ptp_clock_info {
+ struct module *owner;
+ char name[16];
+ s32 max_adj;
+ int n_alarm;
+ int n_ext_ts;
+ int n_per_out;
+ int pps;
+ void *priv;
+ int (*adjfreq)(void *priv, s32 delta);
+ int (*adjtime)(void *priv, struct timespec *ts);
+ int (*gettime)(void *priv, struct timespec *ts);
+ int (*settime)(void *priv, struct timespec *ts);
+ int (*enable) (void *priv, struct ptp_clock_request request, int on);
+};
+
+/**
+ * ptp_clock_register() - register a PTP hardware clock driver
+ *
+ * @info: Structure describing the new clock.
+ */
+
+extern int ptp_clock_register(struct ptp_clock_info *info);
+
+/**
+ * ptp_clock_unregister() - unregister a PTP hardware clock driver
+ *
+ * @info: The clock to remove from service.
+ */
+
+extern int ptp_clock_unregister(struct ptp_clock_info *info);
+
+/**
+ * struct ptp_clock_event - decribes a PTP hardware clock event
+ *
+ * @type: One of the ptp_clock_events enumeration values.
+ * @index: Identifies the source of the event.
+ * @timestamp: When the event occured.
+ */
+
+struct ptp_clock_event {
+ int type;
+ int index;
+ u64 timestamp;
+};
+
+/**
+ * ptp_clock_event() - notify the PTP layer about an event
+ *
+ * @event: Message structure describing the event.
+ */
+
+extern void ptp_clock_event(struct ptp_clock_event event);
+
+#endif
--
1.6.0.4
^ permalink raw reply related
* [PATCH 2/3] ptp: Added a clock that uses the Linux system time.
From: Richard Cochran @ 2010-04-27 9:14 UTC (permalink / raw)
To: netdev
This PTP clock simply uses the NTP time adjustment system calls. The
driver can be used in systems that lack a special hardware PTP clock.
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
drivers/ptp/Kconfig | 12 +++++
drivers/ptp/Makefile | 1 +
drivers/ptp/ptp_linux.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
kernel/time/ntp.c | 2 +
4 files changed, 134 insertions(+), 0 deletions(-)
create mode 100644 drivers/ptp/ptp_linux.c
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 458d0fe..7113bef 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -23,4 +23,16 @@ config PTP_1588_CLOCK
To compile this driver as a module, choose M here: the module
will be called ptp_clock.ko.
+config PTP_1588_CLOCK_LINUX
+ tristate "Linux system timer as PTP clock"
+ depends on PTP_1588_CLOCK
+ help
+ This driver adds support for using the standard Linux time
+ source as a PTP clock. This clock is only useful if your PTP
+ programs are using software time stamps for the PTP Ethernet
+ packets.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ptp_linux.ko.
+
endmenu
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index b86695c..1651d52 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_PTP_1588_CLOCK) += ptp_clock.o
+obj-$(CONFIG_PTP_1588_CLOCK_LINUX) += ptp_linux.o
diff --git a/drivers/ptp/ptp_linux.c b/drivers/ptp/ptp_linux.c
new file mode 100644
index 0000000..0eaa6c3
--- /dev/null
+++ b/drivers/ptp/ptp_linux.c
@@ -0,0 +1,119 @@
+/*
+ * PTP 1588 clock using the Linux system clock
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timex.h>
+
+#include <linux/ptp_clock_kernel.h>
+
+DEFINE_SPINLOCK(adjtime_lock);
+
+static int ptp_linux_adjfreq(void *priv, s32 delta)
+{
+ struct timex txc;
+ s64 tmp = delta;
+ int err;
+ txc.freq = div_s64(tmp<<16, 1000);
+ txc.modes = ADJ_FREQUENCY;
+ err = do_adjtimex(&txc);
+ return err < 0 ? err : 0;
+}
+
+static int ptp_linux_adjtime(void *priv, struct timespec *ts)
+{
+ s64 delta;
+ ktime_t now;
+ struct timespec t2;
+ unsigned long flags;
+ int err;
+
+ delta = 1000000000LL * ts->tv_sec + ts->tv_nsec;
+
+ spin_lock_irqsave(&adjtime_lock, flags);
+
+ now = ktime_get_real();
+
+ now = delta < 0 ? ktime_sub_ns(now,-delta) : ktime_add_ns(now,delta);
+
+ t2 = ktime_to_timespec(now);
+
+ err = do_settimeofday(&t2);
+
+ spin_unlock_irqrestore(&adjtime_lock, flags);
+
+ return err;
+}
+
+static int ptp_linux_gettime(void *priv, struct timespec *ts)
+{
+ getnstimeofday(ts);
+ return 0;
+}
+
+static int ptp_linux_settime(void *priv, struct timespec *ts)
+{
+ return do_settimeofday(ts);
+}
+
+static int ptp_linux_enable(void *priv, struct ptp_clock_request rq, int on)
+{
+ /* We do not offer any ancillary features at all. */
+ return -EINVAL;
+}
+
+struct ptp_clock_info ptp_linux_caps = {
+ .owner = THIS_MODULE,
+ .name = "Linux timer",
+ .max_adj = 512000,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .pps = 0,
+ .priv = NULL,
+ .adjfreq = ptp_linux_adjfreq,
+ .adjtime = ptp_linux_adjtime,
+ .gettime = ptp_linux_gettime,
+ .settime = ptp_linux_settime,
+ .enable = ptp_linux_enable,
+};
+
+/* module operations */
+
+static void __exit ptp_linux_exit(void)
+{
+ ptp_clock_unregister(&ptp_linux_caps);
+}
+
+static int __init ptp_linux_init(void)
+{
+ int err;
+ err = ptp_clock_register(&ptp_linux_caps);
+ return err;
+}
+
+subsys_initcall(ptp_linux_init);
+module_exit(ptp_linux_exit);
+
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_DESCRIPTION("PTP clock using the Linux system timer");
+MODULE_LICENSE("GPL");
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 7c0f180..efd1ff8 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -14,6 +14,7 @@
#include <linux/timex.h>
#include <linux/time.h>
#include <linux/mm.h>
+#include <linux/module.h>
/*
* NTP timekeeping variables:
@@ -535,6 +536,7 @@ int do_adjtimex(struct timex *txc)
return result;
}
+EXPORT_SYMBOL(do_adjtimex);
static int __init ntp_tick_adj_setup(char *str)
{
--
1.6.0.4
^ permalink raw reply related
* [PATCH 3/3] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Richard Cochran @ 2010-04-27 9:14 UTC (permalink / raw)
To: netdev
The eTSEC includes a PTP clock with quite a few features. This patch adds
support for the basic clock adjustment functions.
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
drivers/net/Makefile | 1 +
drivers/net/gianfar_ptp.c | 269 +++++++++++++++++++++++++++++++++++++++++
drivers/net/gianfar_ptp_reg.h | 107 ++++++++++++++++
drivers/ptp/Kconfig | 13 ++
4 files changed, 390 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/gianfar_ptp.c
create mode 100644 drivers/net/gianfar_ptp_reg.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index ebf80b9..8f2c2ff 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_ATL2) += atlx/
obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_ATL1C) += atl1c/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
obj-$(CONFIG_TEHUTI) += tehuti.o
obj-$(CONFIG_ENIC) += enic/
obj-$(CONFIG_JME) += jme.o
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c
new file mode 100644
index 0000000..eed3246
--- /dev/null
+++ b/drivers/net/gianfar_ptp.c
@@ -0,0 +1,269 @@
+/*
+ * PTP 1588 clock using the eTSEC
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timex.h>
+#include <asm/io.h>
+
+#include <linux/ptp_clock_kernel.h>
+
+#include "gianfar_ptp_reg.h"
+
+/*
+ *
+ * TODO - get the following from device tree
+ *
+ */
+#define TMR_BASE_KERNEL 0xe0024e00 // CONFIG_PPC_85xx 0xffe24e00
+#define TIMER_OSC 166666666
+#define TCLK_PERIOD 10
+#define NOMINAL_FREQ 100000000
+#define DEF_TMR_PRSC 100
+#define DEF_TMR_ADD 0x999999A4
+#define DEFAULT_CKSEL 1
+
+#define REG_SIZE (4 + TMR_ETTS2_L)
+
+struct etsects {
+ void *regs;
+ u32 timer_osc; /* Hz */
+ u32 tclk_period; /* nanoseconds */
+ s64 nominal_freq; /* Hz */
+ u32 tmr_prsc;
+ u32 tmr_add;
+ u32 cksel;
+};
+
+/* Private globals */
+static struct etsects the_clock;
+DEFINE_SPINLOCK(adjtime_lock);
+
+/*
+ * Register access functions
+ */
+
+static inline u32 reg_read(struct etsects *etsects, unsigned long offset)
+{
+ return in_be32(etsects->regs + offset);
+}
+
+static inline void reg_write(struct etsects *etsects,
+ unsigned long offset, u32 val)
+{
+ out_be32(etsects->regs + offset, val);
+}
+
+static u64 tmr_cnt_read(struct etsects *etsects)
+{
+ u64 ns;
+ u32 lo, hi;
+ lo = reg_read(etsects, TMR_CNT_L);
+ hi = reg_read(etsects, TMR_CNT_H);
+ ns = ((u64) hi) << 32;
+ ns |= lo;
+ return ns;
+}
+
+static void tmr_cnt_write(struct etsects *etsects, u64 ns)
+{
+ u32 hi = ns >> 32;
+ u32 lo = ns & 0xffffffff;
+ reg_write(etsects, TMR_CNT_L, lo);
+ reg_write(etsects, TMR_CNT_H, hi);
+}
+
+static void set_alarm(struct etsects *etsects)
+{
+ u64 ns;
+ u32 lo, hi;
+ ns = tmr_cnt_read(etsects) + 1500000000ULL;
+ ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
+ ns -= etsects->tclk_period;
+ hi = ns >> 32;
+ lo = ns & 0xffffffff;
+ reg_write(etsects, TMR_ALARM1_L, lo);
+ reg_write(etsects, TMR_ALARM1_H, hi);
+}
+
+static void set_fipers(struct etsects *etsects)
+{
+ u32 tmr_ctrl = reg_read(etsects, TMR_CTRL);
+
+ reg_write(etsects, TMR_CTRL, tmr_ctrl & (~TE));
+ reg_write(etsects, TMR_PRSC, etsects->tmr_prsc);
+ reg_write(etsects, TMR_FIPER1, 0x3B9AC9F6);
+ reg_write(etsects, TMR_FIPER2, 0x00018696);
+ set_alarm(etsects);
+ reg_write(etsects, TMR_CTRL, tmr_ctrl|TE);
+}
+
+/*
+ * PTP clock operations
+ */
+
+static int ptp_gianfar_adjfreq(void *priv, s32 ppb)
+{
+ u64 adj;
+ u32 diff, tmr_add;
+ int neg_adj = 0;
+ struct etsects *etsects = priv;
+
+ if (!ppb)
+ return 0;
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ tmr_add = etsects->tmr_add;
+ adj = tmr_add;
+ adj *= ppb;
+ diff = div_u64(adj, 1000000000ULL);
+
+ tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
+
+ reg_write(etsects, TMR_ADD, tmr_add);
+
+ return 0;
+}
+
+static int ptp_gianfar_adjtime(void *priv, struct timespec *ts)
+{
+ s64 delta, now;
+ unsigned long flags;
+ struct etsects *etsects = priv;
+
+ delta = 1000000000LL * ts->tv_sec;
+ delta += ts->tv_nsec;
+
+ spin_lock_irqsave(&adjtime_lock, flags);
+
+ now = tmr_cnt_read(etsects);
+ now += delta;
+ tmr_cnt_write(etsects, now);
+
+ spin_unlock_irqrestore(&adjtime_lock, flags);
+
+ set_fipers(etsects);
+
+ return 0;
+}
+
+static int ptp_gianfar_gettime(void *priv, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ struct etsects *etsects = priv;
+ ns = tmr_cnt_read(etsects);
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+ return 0;
+}
+
+static int ptp_gianfar_settime(void *priv, struct timespec *ts)
+{
+ u64 ns;
+ struct etsects *etsects = priv;
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+ tmr_cnt_write(etsects, ns);
+ set_fipers(etsects);
+ return 0;
+}
+
+static int ptp_gianfar_enable(void *priv, struct ptp_clock_request rq, int on)
+{
+ /* We do not (yet) offer any ancillary features. */
+ return -EINVAL;
+}
+
+struct ptp_clock_info ptp_gianfar_caps = {
+ .owner = THIS_MODULE,
+ .name = "gianfar clock",
+ .max_adj = 512000,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .pps = 0,
+ .priv = &the_clock,
+ .adjfreq = ptp_gianfar_adjfreq,
+ .adjtime = ptp_gianfar_adjtime,
+ .gettime = ptp_gianfar_gettime,
+ .settime = ptp_gianfar_settime,
+ .enable = ptp_gianfar_enable,
+};
+
+/* module operations */
+
+static void __exit ptp_gianfar_exit(void)
+{
+ ptp_clock_unregister(&ptp_gianfar_caps);
+ iounmap(the_clock.regs);
+}
+
+static int __init ptp_gianfar_init(void)
+{
+ struct etsects *etsects = &the_clock;
+ struct timespec now;
+ phys_addr_t reg_addr = TMR_BASE_KERNEL;
+ unsigned long reg_size = REG_SIZE;
+ u32 tmr_ctrl;
+ int err;
+
+ etsects->regs = ioremap(reg_addr, reg_size);
+ if (!etsects->regs) {
+ pr_err("ioremap ptp registers failed\n");
+ return -EINVAL;
+ }
+ etsects->timer_osc = TIMER_OSC;
+ etsects->tclk_period = TCLK_PERIOD;
+ etsects->nominal_freq = NOMINAL_FREQ;
+ etsects->tmr_prsc = DEF_TMR_PRSC;
+ etsects->tmr_add = DEF_TMR_ADD;
+ etsects->cksel = DEFAULT_CKSEL;
+
+ tmr_ctrl =
+ (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
+ (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT;
+
+ getnstimeofday(&now);
+ ptp_gianfar_settime(etsects, &now);
+
+ reg_write(etsects, TMR_CTRL, tmr_ctrl);
+ reg_write(etsects, TMR_ADD, etsects->tmr_add);
+ reg_write(etsects, TMR_PRSC, etsects->tmr_prsc);
+ reg_write(etsects, TMR_FIPER1, 0x3B9AC9F6);
+ reg_write(etsects, TMR_FIPER2, 0x00018696);
+ set_alarm(etsects);
+ reg_write(etsects, TMR_CTRL, tmr_ctrl|FS|RTPE|TE);
+
+ err = ptp_clock_register(&ptp_gianfar_caps);
+ return err;
+}
+
+subsys_initcall(ptp_gianfar_init);
+module_exit(ptp_gianfar_exit);
+
+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_DESCRIPTION("PTP clock using the eTSEC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/gianfar_ptp_reg.h b/drivers/net/gianfar_ptp_reg.h
new file mode 100644
index 0000000..9c94677
--- /dev/null
+++ b/drivers/net/gianfar_ptp_reg.h
@@ -0,0 +1,107 @@
+/* gianfar_ptp_reg.h
+ * Generated by regen.tcl on Thu Apr 15 02:21:02 PM CEST 2010
+ *
+ * PTP 1588 clock using the gianfar eTSEC
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _GIANFAR_PTP_REG_H_
+#define _GIANFAR_PTP_REG_H_
+
+#define TMR_CTRL 0x00000000 /* Timer control register */
+#define TMR_TEVENT 0x00000004 /* Timestamp event register */
+#define TMR_TEMASK 0x00000008 /* Timer event mask register */
+#define TMR_PEVENT 0x0000000c /* Timestamp event register */
+#define TMR_PEMASK 0x00000010 /* Timer event mask register */
+#define TMR_STAT 0x00000014 /* Timestamp status register */
+#define TMR_CNT_H 0x00000018 /* Timer counter high register */
+#define TMR_CNT_L 0x0000001c /* Timer counter low register */
+#define TMR_ADD 0x00000020 /* Timer drift compensation addend register */
+#define TMR_ACC 0x00000024 /* Timer accumulator register */
+#define TMR_PRSC 0x00000028 /* Timer prescale */
+#define TMROFF_H 0x00000030 /* Timer offset high */
+#define TMROFF_L 0x00000034 /* Timer offset low */
+#define TMR_ALARM1_H 0x00000040 /* Timer alarm 1 high register */
+#define TMR_ALARM1_L 0x00000044 /* Timer alarm 1 high register */
+#define TMR_ALARM2_H 0x00000048 /* Timer alarm 2 high register */
+#define TMR_ALARM2_L 0x0000004c /* Timer alarm 2 high register */
+#define TMR_FIPER1 0x00000080 /* Timer fixed period interval */
+#define TMR_FIPER2 0x00000084 /* Timer fixed period interval */
+#define TMR_FIPER3 0x00000088 /* Timer fixed period interval */
+#define TMR_ETTS1_H 0x000000a0 /* Timestamp of general purpose external trigger */
+#define TMR_ETTS1_L 0x000000a4 /* Timestamp of general purpose external trigger */
+#define TMR_ETTS2_H 0x000000a8 /* Timestamp of general purpose external trigger */
+#define TMR_ETTS2_L 0x000000ac /* Timestamp of general purpose external trigger */
+
+/* Bit definitions for the TMR_CTRL register */
+#define ALM1P (1<<31) /* Alarm1 output polarity */
+#define ALM2P (1<<30) /* Alarm2 output polarity */
+#define FS (1<<28) /* FIPER start indication */
+#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */
+#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */
+#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */
+#define TCLK_PERIOD_MASK (0x3ff)
+#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */
+#define FRD (1<<14) /* FIPER Realignment Disable */
+#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */
+#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */
+#define ETEP2 (1<<9) /* External trigger 2 edge polarity */
+#define ETEP1 (1<<8) /* External trigger 1 edge polarity */
+#define COPH (1<<7) /* Generated clock (TSEC_1588_GCLK) output phase. */
+#define CIPH (1<<6) /* External oscillator input clock phase. */
+#define TMSR (1<<5) /* Timer soft reset. When enabled, it resets all the timer registers and state machines. */
+#define BYP (1<<3) /* Bypass drift compensated clock */
+#define TE (1<<2) /* 1588 timer enable. If not enabled, all the timer registers and state machines are disabled. */
+#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source select. */
+#define CKSEL_MASK (0x3)
+
+/* Bit definitions for the TMR_TEVENT register */
+#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */
+#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */
+#define ALM2 (1<<17) /* Current time equaled alarm time register 2 */
+#define ALM1 (1<<16) /* Current time equaled alarm time register 1 */
+#define PP1 (1<<7) /* Indicates that a periodic pulse has been generated based on FIPER1 register */
+#define PP2 (1<<6) /* Indicates that a periodic pulse has been generated based on FIPER2 register */
+#define PP3 (1<<5) /* Indicates that a periodic pulse has been generated based on FIPER3 register */
+
+/* Bit definitions for the TMR_TEMASK register */
+#define ETS2EN (1<<25) /* External trigger 2 timestamp sample event enable */
+#define ETS1EN (1<<24) /* External trigger 1 timestamp sample event enable */
+#define ALM2EN (1<<17) /* Timer ALM2 event enable */
+#define ALM1EN (1<<16) /* Timer ALM1 event enable */
+#define PP1EN (1<<7) /* Periodic pulse event 1 enable */
+#define PP2EN (1<<6) /* Periodic pulse event 2 enable */
+
+/* Bit definitions for the TMR_PEVENT register */
+#define TXP2 (1<<9) /* Indicates that a PTP frame has been transmitted and its timestamp is stored in TXTS2 register */
+#define TXP1 (1<<8) /* Indicates that a PTP frame has been transmitted and its timestamp is stored in TXTS1 register */
+#define RXP (1<<0) /* Indicates that a PTP frame has been received */
+
+/* Bit definitions for the TMR_PEMASK register */
+#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */
+#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */
+#define RXPEN (1<<0) /* Receive PTP packet event enable */
+
+/* Bit definitions for the TMR_STAT register */
+#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */
+#define STAT_VEC_MASK (0x3f)
+
+/* Bit definitions for the TMR_PRSC register */
+#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */
+#define PRSC_OCK_MASK (0xffff)
+
+#endif
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 7113bef..2f8ab67 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -35,4 +35,17 @@ config PTP_1588_CLOCK_LINUX
To compile this driver as a module, choose M here: the module
will be called ptp_linux.ko.
+config PTP_1588_CLOCK_GIANFAR
+ tristate "Freescale eTSEC as PTP clock"
+ depends on PTP_1588_CLOCK
+ depends on GIANFAR
+ help
+ This driver adds support for using the eTSEC as a PTP
+ clock. This clock is only useful if your PTP programs are
+ getting hardware time stamps on the PTP Ethernet packets
+ using the SO_TIMESTAMPING API.
+
+ To compile this driver as a module, choose M here: the module
+ will be called gianfar_ptp.ko.
+
endmenu
--
1.6.0.4
^ permalink raw reply related
* [patch] ipheth: potential null dereferences on error path
From: Dan Carpenter @ 2010-04-27 9:20 UTC (permalink / raw)
To: Diego Giagio
Cc: David S. Miller, L. Alberto Giménez, netdev, kernel-janitors
The calls to usb_free_buffer() dereference rx_urb and tx_urb in the
parameter list but those could be NULL.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index fd10331..418825d 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -122,25 +122,25 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (tx_urb == NULL)
- goto error;
+ goto error_nomem;
rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (rx_urb == NULL)
- goto error;
+ goto free_tx_urb;
tx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&tx_urb->transfer_dma);
if (tx_buf == NULL)
- goto error;
+ goto free_rx_urb;
rx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&rx_urb->transfer_dma);
if (rx_buf == NULL)
- goto error;
+ goto free_tx_buf;
iphone->tx_urb = tx_urb;
@@ -149,13 +149,14 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
iphone->rx_buf = rx_buf;
return 0;
-error:
- usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, rx_buf,
- rx_urb->transfer_dma);
+free_tx_buf:
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
+free_rx_urb:
usb_free_urb(rx_urb);
+free_tx_urb:
usb_free_urb(tx_urb);
+error_nomem:
return -ENOMEM;
}
^ permalink raw reply related
* [PATCH v2] net: reimplement softnet_data.output_queue as a FIFO queue
From: Changli Gao @ 2010-04-27 9:06 UTC (permalink / raw)
To: David S. Miller; +Cc: Eric Dumazet, netdev, Changli Gao
reimplement softnet_data.output_queue as a FIFO queue.
reimplement softnet_data.output_queue as a FIFO queue to keep the fairness among
the qdiscs rescheduled.
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
include/linux/netdevice.h | 1 +
net/core/dev.c | 22 ++++++++++++----------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3c5ed5f..c04ca24 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1385,6 +1385,7 @@ static inline int unregister_gifconf(unsigned int family)
*/
struct softnet_data {
struct Qdisc *output_queue;
+ struct Qdisc **output_queue_tailp;
struct list_head poll_list;
struct sk_buff *completion_queue;
diff --git a/net/core/dev.c b/net/core/dev.c
index 4d43f1a..3d31491 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1557,8 +1557,9 @@ static inline void __netif_reschedule(struct Qdisc *q)
local_irq_save(flags);
sd = &__get_cpu_var(softnet_data);
- q->next_sched = sd->output_queue;
- sd->output_queue = q;
+ q->next_sched = NULL;
+ *sd->output_queue_tailp = q;
+ sd->output_queue_tailp = &q->next_sched;
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
}
@@ -2529,6 +2530,7 @@ static void net_tx_action(struct softirq_action *h)
local_irq_disable();
head = sd->output_queue;
sd->output_queue = NULL;
+ sd->output_queue_tailp = &sd->output_queue;
local_irq_enable();
while (head) {
@@ -5594,7 +5596,6 @@ static int dev_cpu_callback(struct notifier_block *nfb,
void *ocpu)
{
struct sk_buff **list_skb;
- struct Qdisc **list_net;
struct sk_buff *skb;
unsigned int cpu, oldcpu = (unsigned long)ocpu;
struct softnet_data *sd, *oldsd;
@@ -5615,13 +5616,13 @@ static int dev_cpu_callback(struct notifier_block *nfb,
*list_skb = oldsd->completion_queue;
oldsd->completion_queue = NULL;
- /* Find end of our output_queue. */
- list_net = &sd->output_queue;
- while (*list_net)
- list_net = &(*list_net)->next_sched;
/* Append output queue from offline CPU. */
- *list_net = oldsd->output_queue;
- oldsd->output_queue = NULL;
+ if (oldsd->output_queue) {
+ *sd->output_queue_tailp = oldsd->output_queue;
+ sd->output_queue_tailp = oldsd->output_queue_tailp;
+ oldsd->output_queue = NULL;
+ oldsd->output_queue_tailp = &oldsd->output_queue;
+ }
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_enable();
@@ -5851,7 +5852,8 @@ static int __init net_dev_init(void)
skb_queue_head_init(&sd->input_pkt_queue);
sd->completion_queue = NULL;
INIT_LIST_HEAD(&sd->poll_list);
-
+ sd->output_queue = NULL;
+ sd->output_queue_tailp = &sd->output_queue;
#ifdef CONFIG_RPS
sd->csd.func = rps_trigger_softirq;
sd->csd.info = sd;
^ permalink raw reply related
* Re: [PATCH 0/3] [RFC] ptp: IEEE 1588 clock support
From: Richard Cochran @ 2010-04-27 10:20 UTC (permalink / raw)
To: netdev
In-Reply-To: <20100427091344.GA5086@riccoc20.at.omicron.at>
BTW,
To show how the API works from the user space, I also patches For the
popular ptpd program to that project.
https://sourceforge.net/tracker/?func=detail&aid=2992845&group_id=139814&atid=744634
Richard
^ permalink raw reply
* [net-2.6 PATCH] ixgbe: Properly display 1 gig downshift warning for backplane
From: Jeff Kirsher @ 2010-04-27 10:37 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Anjali Singhai, Jeff Kirsher
From: Anjali Singhai <anjali.singhai@intel.com>
Description: When using Intel smartspeed, the patch displays a
warning when the link down shifts to 1 Gig.
Signed-off-by: Anjali Singhai <anjali.singhai@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_82599.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index b405a00..217237c 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -608,6 +608,7 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
s32 i, j;
bool link_up = false;
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ struct ixgbe_adapter *adapter = hw->back;
hw_dbg(hw, "ixgbe_setup_mac_link_smartspeed.\n");
@@ -692,6 +693,10 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
autoneg_wait_to_complete);
out:
+ if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
+ netif_info(adapter, hw, adapter->netdev, "Smartspeed has"
+ " downgraded the link speed from the maximum"
+ " advertised\n");
return status;
}
^ permalink raw reply related
* [net-2.6 PATCH] ixgbe: Power down PHY during driver resets
From: Jeff Kirsher @ 2010-04-27 10:38 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
From: Peter Waskiewicz <peter.p.waskiewicz.jr@intel.com>
The PHY laser is still on during driver init. It's allowing
garbage to hit our FIFO, which eventually can cause the entire
device to die. Power down the laser while setting up the device,
and re-enable the laser before getting link.
Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_82599.c | 62 ++++++++++++++++++++++++++++++---------
drivers/net/ixgbe/ixgbe_main.c | 22 ++++++++------
drivers/net/ixgbe/ixgbe_type.h | 2 +
3 files changed, 62 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 217237c..78da45d 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -39,6 +39,8 @@
#define IXGBE_82599_MC_TBL_SIZE 128
#define IXGBE_82599_VFT_TBL_SIZE 128
+void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
@@ -69,8 +71,14 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+ mac->ops.disable_tx_laser =
+ &ixgbe_disable_tx_laser_multispeed_fiber;
+ mac->ops.enable_tx_laser =
+ &ixgbe_enable_tx_laser_multispeed_fiber;
mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
} else {
+ mac->ops.disable_tx_laser = NULL;
+ mac->ops.enable_tx_laser = NULL;
mac->ops.flap_tx_laser = NULL;
if ((mac->ops.get_media_type(hw) ==
ixgbe_media_type_backplane) &&
@@ -415,6 +423,44 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
return status;
}
+ /**
+ * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * The base drivers may require better control over SFP+ module
+ * PHY states. This includes selectively shutting down the Tx
+ * laser on the PHY, effectively halting physical link.
+ **/
+void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+ /* Disable tx laser; allow 100us to go dark per spec */
+ esdp_reg |= IXGBE_ESDP_SDP3;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(100);
+}
+
+/**
+ * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * The base drivers may require better control over SFP+ module
+ * PHY states. This includes selectively turning on the Tx
+ * laser on the PHY, effectively starting physical link.
+ **/
+void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+ /* Enable tx laser; allow 100ms to light up */
+ esdp_reg &= ~IXGBE_ESDP_SDP3;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
+ msleep(100);
+}
+
/**
* ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
* @hw: pointer to hardware structure
@@ -429,23 +475,11 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
**/
void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
- u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
-
hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
if (hw->mac.autotry_restart) {
- /* Disable tx laser; allow 100us to go dark per spec */
- esdp_reg |= IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- IXGBE_WRITE_FLUSH(hw);
- udelay(100);
-
- /* Enable tx laser; allow 100ms to light up */
- esdp_reg &= ~IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- IXGBE_WRITE_FLUSH(hw);
- msleep(100);
-
+ ixgbe_disable_tx_laser_multispeed_fiber(hw);
+ ixgbe_enable_tx_laser_multispeed_fiber(hw);
hw->mac.autotry_restart = false;
}
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 8f677cb..6c00ee4 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -2982,6 +2982,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
else
ixgbe_configure_msi_and_legacy(adapter);
+ /* enable the optics */
+ if (hw->phy.multispeed_fiber)
+ hw->mac.ops.enable_tx_laser(hw);
+
clear_bit(__IXGBE_DOWN, &adapter->state);
ixgbe_napi_enable_all(adapter);
@@ -3243,6 +3247,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
+ /* power down the optics */
+ if (hw->phy.multispeed_fiber)
+ hw->mac.ops.disable_tx_laser(hw);
+
/* disable receive for all VFs and wait one second */
if (adapter->num_vfs) {
/* ping all the active vfs to let them know we are going down */
@@ -6253,6 +6261,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
goto err_eeprom;
}
+ /* power down the optics */
+ if (hw->phy.multispeed_fiber)
+ hw->mac.ops.disable_tx_laser(hw);
+
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &ixgbe_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -6400,16 +6412,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
del_timer_sync(&adapter->sfp_timer);
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->sfp_task);
- if (adapter->hw.phy.multispeed_fiber) {
- struct ixgbe_hw *hw = &adapter->hw;
- /*
- * Restart clause 37 autoneg, disable and re-enable
- * the tx laser, to clear & alert the link partner
- * that it needs to restart autotry
- */
- hw->mac.autotry_restart = true;
- hw->mac.ops.flap_tx_laser(hw);
- }
cancel_work_sync(&adapter->multispeed_fiber_task);
cancel_work_sync(&adapter->sfp_config_module_task);
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 4ec6dc1..534affc 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -2398,6 +2398,8 @@ struct ixgbe_mac_operations {
s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
/* Link */
+ void (*disable_tx_laser)(struct ixgbe_hw *);
+ void (*enable_tx_laser)(struct ixgbe_hw *);
void (*flap_tx_laser)(struct ixgbe_hw *);
s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
^ permalink raw reply related
* [net-2.6 PATCH] ixgbevf: Fix link speed display
From: Jeff Kirsher @ 2010-04-27 10:38 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Greg Rose, Jeff Kirsher
From: Greg Rose <gregory.v.rose@intel.com>
The ixgbevf driver would always report 10Gig speeds even when the link
speed is downshifted to 1Gig. This patch fixes that problem.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbevf/defines.h | 12 +++++++-----
drivers/net/ixgbevf/vf.c | 3 ++-
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ixgbevf/defines.h b/drivers/net/ixgbevf/defines.h
index c44fdb0..ca2c81f 100644
--- a/drivers/net/ixgbevf/defines.h
+++ b/drivers/net/ixgbevf/defines.h
@@ -41,11 +41,13 @@ typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
-#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
-#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */
-#define IXGBE_TXDCTL_ENABLE 0x02000000 /* Enable specific Tx Queue */
-#define IXGBE_LINKS_UP 0x40000000
-#define IXGBE_LINKS_SPEED 0x20000000
+#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
+#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */
+#define IXGBE_TXDCTL_ENABLE 0x02000000 /* Enable specific Tx Queue */
+#define IXGBE_LINKS_UP 0x40000000
+#define IXGBE_LINKS_SPEED_82599 0x30000000
+#define IXGBE_LINKS_SPEED_10G_82599 0x30000000
+#define IXGBE_LINKS_SPEED_1G_82599 0x20000000
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
#define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8
diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c
index 4b5dec0..6694c37 100644
--- a/drivers/net/ixgbevf/vf.c
+++ b/drivers/net/ixgbevf/vf.c
@@ -359,7 +359,8 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
else
*link_up = false;
- if (links_reg & IXGBE_LINKS_SPEED)
+ if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_10G_82599)
*speed = IXGBE_LINK_SPEED_10GB_FULL;
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;
^ permalink raw reply related
* [net-next-2.6 PATCH] ixgb: Use pr_<level> and netdev_<level>
From: Jeff Kirsher @ 2010-04-27 10:50 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Joe Perches, Jeff Kirsher
From: Joe Perches <joe@perches.com>
Convert DEBUGOUTx to pr_debug
Convert DEBUGFUNC to more commonly used ENTER
Convert mac address output to %pM
Use #define pr_fmt
Convert a few printks to pr_<level>
Improve ixgb_mc_addr_list_update: use a temporary for current mc address
Use etherdevice.h functions for mac address testing
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgb/ixgb.h | 8 ++
drivers/net/ixgb/ixgb_ee.c | 14 ++--
drivers/net/ixgb/ixgb_hw.c | 147 +++++++++++++++++------------------------
drivers/net/ixgb/ixgb_hw.h | 12 ---
drivers/net/ixgb/ixgb_main.c | 33 ++++-----
drivers/net/ixgb/ixgb_osdep.h | 16 +---
drivers/net/ixgb/ixgb_param.c | 31 ++++-----
7 files changed, 105 insertions(+), 156 deletions(-)
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 92d2e71..521c0c7 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -78,9 +78,13 @@ struct ixgb_adapter;
#define PFX "ixgb: "
#ifdef _DEBUG_DRIVER_
-#define IXGB_DBG(args...) printk(KERN_DEBUG PFX args)
+#define IXGB_DBG(fmt, args...) printk(KERN_DEBUG PFX fmt, ##args)
#else
-#define IXGB_DBG(args...)
+#define IXGB_DBG(fmt, args...) \
+do { \
+ if (0) \
+ printk(KERN_DEBUG PFX fmt, ##args); \
+} while (0)
#endif
/* TX/RX descriptor defines */
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 89ffa72..06303a3 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -26,6 +26,8 @@
*******************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "ixgb_hw.h"
#include "ixgb_ee.h"
/* Local prototypes */
@@ -467,11 +469,11 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
u16 checksum = 0;
struct ixgb_ee_map_type *ee_map;
- DEBUGFUNC("ixgb_get_eeprom_data");
+ ENTER();
ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- DEBUGOUT("ixgb_ee: Reading eeprom data\n");
+ pr_debug("Reading eeprom data\n");
for (i = 0; i < IXGB_EEPROM_SIZE ; i++) {
u16 ee_data;
ee_data = ixgb_read_eeprom(hw, i);
@@ -480,7 +482,7 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
}
if (checksum != (u16) EEPROM_SUM) {
- DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+ pr_debug("Checksum invalid\n");
/* clear the init_ctrl_reg_1 to signify that the cache is
* invalidated */
ee_map->init_ctrl_reg_1 = cpu_to_le16(EEPROM_ICW1_SIGNATURE_CLEAR);
@@ -489,7 +491,7 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
!= cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
- DEBUGOUT("ixgb_ee: Signature invalid.\n");
+ pr_debug("Signature invalid\n");
return(false);
}
@@ -555,13 +557,13 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
int i;
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- DEBUGFUNC("ixgb_get_ee_mac_addr");
+ ENTER();
if (ixgb_check_and_get_eeprom_data(hw) == true) {
for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
mac_addr[i] = ee_map->mac_addr[i];
- DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
}
+ pr_debug("eeprom mac address = %pM\n", mac_addr);
}
}
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index ff67a84..cd247b8 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -30,9 +30,13 @@
* Shared functions for accessing and configuring the adapter
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "ixgb_hw.h"
#include "ixgb_ids.h"
+#include <linux/etherdevice.h>
+
/* Local function prototypes */
static u32 ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr);
@@ -120,13 +124,13 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
u32 ctrl_reg;
u32 icr_reg;
- DEBUGFUNC("ixgb_adapter_stop");
+ ENTER();
/* If we are stopped or resetting exit gracefully and wait to be
* started again before accessing the hardware.
*/
if (hw->adapter_stopped) {
- DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+ pr_debug("Exiting because the adapter is already stopped!!!\n");
return false;
}
@@ -136,7 +140,7 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
hw->adapter_stopped = true;
/* Clear interrupt mask to stop board from generating interrupts */
- DEBUGOUT("Masking off all interrupts\n");
+ pr_debug("Masking off all interrupts\n");
IXGB_WRITE_REG(hw, IMC, 0xFFFFFFFF);
/* Disable the Transmit and Receive units. Then delay to allow
@@ -152,12 +156,12 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
* the current PCI configuration. The global reset bit is self-
* clearing, and should clear within a microsecond.
*/
- DEBUGOUT("Issuing a global reset to MAC\n");
+ pr_debug("Issuing a global reset to MAC\n");
ctrl_reg = ixgb_mac_reset(hw);
/* Clear interrupt mask to stop board from generating interrupts */
- DEBUGOUT("Masking off all interrupts\n");
+ pr_debug("Masking off all interrupts\n");
IXGB_WRITE_REG(hw, IMC, 0xffffffff);
/* Clear any pending interrupt events. */
@@ -183,7 +187,7 @@ ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
u16 vendor_name[5];
ixgb_xpak_vendor xpak_vendor;
- DEBUGFUNC("ixgb_identify_xpak_vendor");
+ ENTER();
/* Read the first few bytes of the vendor string from the XPAK NVR
* registers. These are standard XENPAK/XPAK registers, so all XPAK
@@ -222,12 +226,12 @@ ixgb_identify_phy(struct ixgb_hw *hw)
ixgb_phy_type phy_type;
ixgb_xpak_vendor xpak_vendor;
- DEBUGFUNC("ixgb_identify_phy");
+ ENTER();
/* Infer the transceiver/phy type from the device id */
switch (hw->device_id) {
case IXGB_DEVICE_ID_82597EX:
- DEBUGOUT("Identified TXN17401 optics\n");
+ pr_debug("Identified TXN17401 optics\n");
phy_type = ixgb_phy_type_txn17401;
break;
@@ -237,30 +241,30 @@ ixgb_identify_phy(struct ixgb_hw *hw)
* type of optics. */
xpak_vendor = ixgb_identify_xpak_vendor(hw);
if (xpak_vendor == ixgb_xpak_vendor_intel) {
- DEBUGOUT("Identified TXN17201 optics\n");
+ pr_debug("Identified TXN17201 optics\n");
phy_type = ixgb_phy_type_txn17201;
} else {
- DEBUGOUT("Identified G6005 optics\n");
+ pr_debug("Identified G6005 optics\n");
phy_type = ixgb_phy_type_g6005;
}
break;
case IXGB_DEVICE_ID_82597EX_LR:
- DEBUGOUT("Identified G6104 optics\n");
+ pr_debug("Identified G6104 optics\n");
phy_type = ixgb_phy_type_g6104;
break;
case IXGB_DEVICE_ID_82597EX_CX4:
- DEBUGOUT("Identified CX4\n");
+ pr_debug("Identified CX4\n");
xpak_vendor = ixgb_identify_xpak_vendor(hw);
if (xpak_vendor == ixgb_xpak_vendor_intel) {
- DEBUGOUT("Identified TXN17201 optics\n");
+ pr_debug("Identified TXN17201 optics\n");
phy_type = ixgb_phy_type_txn17201;
} else {
- DEBUGOUT("Identified G6005 optics\n");
+ pr_debug("Identified G6005 optics\n");
phy_type = ixgb_phy_type_g6005;
}
break;
default:
- DEBUGOUT("Unknown physical layer module\n");
+ pr_debug("Unknown physical layer module\n");
phy_type = ixgb_phy_type_unknown;
break;
}
@@ -296,18 +300,18 @@ ixgb_init_hw(struct ixgb_hw *hw)
u32 ctrl_reg;
bool status;
- DEBUGFUNC("ixgb_init_hw");
+ ENTER();
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
* clearing, and should clear within a microsecond.
*/
- DEBUGOUT("Issuing a global reset to MAC\n");
+ pr_debug("Issuing a global reset to MAC\n");
ctrl_reg = ixgb_mac_reset(hw);
- DEBUGOUT("Issuing an EE reset to MAC\n");
+ pr_debug("Issuing an EE reset to MAC\n");
#ifdef HP_ZX1
/* Workaround for 82597EX reset errata */
IXGB_WRITE_REG_IO(hw, CTRL1, IXGB_CTRL1_EE_RST);
@@ -335,7 +339,7 @@ ixgb_init_hw(struct ixgb_hw *hw)
* If it is not valid, we fail hardware init.
*/
if (!mac_addr_valid(hw->curr_mac_addr)) {
- DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+ pr_debug("MAC address invalid after ixgb_init_rx_addrs\n");
return(false);
}
@@ -346,7 +350,7 @@ ixgb_init_hw(struct ixgb_hw *hw)
ixgb_get_bus_info(hw);
/* Zero out the Multicast HASH table */
- DEBUGOUT("Zeroing the MTA\n");
+ pr_debug("Zeroing the MTA\n");
for (i = 0; i < IXGB_MC_TBL_SIZE; i++)
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
@@ -379,7 +383,7 @@ ixgb_init_rx_addrs(struct ixgb_hw *hw)
{
u32 i;
- DEBUGFUNC("ixgb_init_rx_addrs");
+ ENTER();
/*
* If the current mac address is valid, assume it is a software override
@@ -391,28 +395,19 @@ ixgb_init_rx_addrs(struct ixgb_hw *hw)
/* Get the MAC address from the eeprom for later reference */
ixgb_get_ee_mac_addr(hw, hw->curr_mac_addr);
- DEBUGOUT3(" Keeping Permanent MAC Addr =%.2X %.2X %.2X ",
- hw->curr_mac_addr[0],
- hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
- DEBUGOUT3("%.2X %.2X %.2X\n",
- hw->curr_mac_addr[3],
- hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+ pr_debug("Keeping Permanent MAC Addr = %pM\n",
+ hw->curr_mac_addr);
} else {
/* Setup the receive address. */
- DEBUGOUT("Overriding MAC Address in RAR[0]\n");
- DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
- hw->curr_mac_addr[0],
- hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
- DEBUGOUT3("%.2X %.2X %.2X\n",
- hw->curr_mac_addr[3],
- hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+ pr_debug("Overriding MAC Address in RAR[0]\n");
+ pr_debug("New MAC Addr = %pM\n", hw->curr_mac_addr);
ixgb_rar_set(hw, hw->curr_mac_addr, 0);
}
/* Zero out the other 15 receive addresses. */
- DEBUGOUT("Clearing RAR[1-15]\n");
+ pr_debug("Clearing RAR[1-15]\n");
for (i = 1; i < IXGB_RAR_ENTRIES; i++) {
/* Write high reg first to disable the AV bit first */
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -444,64 +439,50 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
u32 hash_value;
u32 i;
u32 rar_used_count = 1; /* RAR[0] is used for our MAC address */
+ u8 *mca;
- DEBUGFUNC("ixgb_mc_addr_list_update");
+ ENTER();
/* Set the new number of MC addresses that we are being requested to use. */
hw->num_mc_addrs = mc_addr_count;
/* Clear RAR[1-15] */
- DEBUGOUT(" Clearing RAR[1-15]\n");
+ pr_debug("Clearing RAR[1-15]\n");
for (i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
- DEBUGOUT(" Clearing MTA\n");
+ pr_debug("Clearing MTA\n");
for (i = 0; i < IXGB_MC_TBL_SIZE; i++)
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* Add the new addresses */
+ mca = mc_addr_list;
for (i = 0; i < mc_addr_count; i++) {
- DEBUGOUT(" Adding the multicast addresses:\n");
- DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
- 1],
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
- 2],
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
- 3],
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
- 4],
- mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
- 5]);
+ pr_debug("Adding the multicast addresses:\n");
+ pr_debug("MC Addr #%d = %pM\n", i, mca);
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
if (rar_used_count < IXGB_RAR_ENTRIES) {
- ixgb_rar_set(hw,
- mc_addr_list +
- (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
- rar_used_count);
- DEBUGOUT1("Added a multicast address to RAR[%d]\n", i);
+ ixgb_rar_set(hw, mca, rar_used_count);
+ pr_debug("Added a multicast address to RAR[%d]\n", i);
rar_used_count++;
} else {
- hash_value = ixgb_hash_mc_addr(hw,
- mc_addr_list +
- (i *
- (IXGB_ETH_LENGTH_OF_ADDRESS
- + pad)));
+ hash_value = ixgb_hash_mc_addr(hw, mca);
- DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
+ pr_debug("Hash value = 0x%03X\n", hash_value);
ixgb_mta_set(hw, hash_value);
}
+
+ mca += IXGB_ETH_LENGTH_OF_ADDRESS + pad;
}
- DEBUGOUT("MC Update Complete\n");
+ pr_debug("MC Update Complete\n");
return;
}
@@ -520,7 +501,7 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
{
u32 hash_value = 0;
- DEBUGFUNC("ixgb_hash_mc_addr");
+ ENTER();
/* The portion of the address that is used for the hash table is
* determined by the mc_filter_type setting.
@@ -547,7 +528,7 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
break;
default:
/* Invalid mc_filter_type, what should we do? */
- DEBUGOUT("MC filter type param set incorrectly\n");
+ pr_debug("MC filter type param set incorrectly\n");
ASSERT(0);
break;
}
@@ -603,7 +584,7 @@ ixgb_rar_set(struct ixgb_hw *hw,
{
u32 rar_low, rar_high;
- DEBUGFUNC("ixgb_rar_set");
+ ENTER();
/* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
@@ -666,7 +647,7 @@ ixgb_setup_fc(struct ixgb_hw *hw)
u32 pap_reg = 0; /* by default, assume no pause time */
bool status = true;
- DEBUGFUNC("ixgb_setup_fc");
+ ENTER();
/* Get the current control reg 0 settings */
ctrl_reg = IXGB_READ_REG(hw, CTRL0);
@@ -710,7 +691,7 @@ ixgb_setup_fc(struct ixgb_hw *hw)
break;
default:
/* We should never get here. The value should be 0-3. */
- DEBUGOUT("Flow control param set incorrectly\n");
+ pr_debug("Flow control param set incorrectly\n");
ASSERT(0);
break;
}
@@ -940,7 +921,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
u32 status_reg;
u32 xpcss_reg;
- DEBUGFUNC("ixgb_check_for_link");
+ ENTER();
xpcss_reg = IXGB_READ_REG(hw, XPCSS);
status_reg = IXGB_READ_REG(hw, STATUS);
@@ -950,7 +931,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
hw->link_up = true;
} else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
(status_reg & IXGB_STATUS_LU)) {
- DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
+ pr_debug("XPCSS Not Aligned while Status:LU is set\n");
hw->link_up = ixgb_link_reset(hw);
} else {
/*
@@ -981,8 +962,7 @@ bool ixgb_check_for_bad_link(struct ixgb_hw *hw)
newRFC = IXGB_READ_REG(hw, RFC);
if ((hw->lastLFC + 250 < newLFC)
|| (hw->lastRFC + 250 < newRFC)) {
- DEBUGOUT
- ("BAD LINK! too many LFC/RFC since last check\n");
+ pr_debug("BAD LINK! too many LFC/RFC since last check\n");
bad_link_returncode = true;
}
hw->lastLFC = newLFC;
@@ -1002,11 +982,11 @@ ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
{
volatile u32 temp_reg;
- DEBUGFUNC("ixgb_clear_hw_cntrs");
+ ENTER();
/* if we are stopped or resetting exit gracefully */
if (hw->adapter_stopped) {
- DEBUGOUT("Exiting because the adapter is stopped!!!\n");
+ pr_debug("Exiting because the adapter is stopped!!!\n");
return;
}
@@ -1156,26 +1136,21 @@ static bool
mac_addr_valid(u8 *mac_addr)
{
bool is_valid = true;
- DEBUGFUNC("mac_addr_valid");
+ ENTER();
/* Make sure it is not a multicast address */
- if (IS_MULTICAST(mac_addr)) {
- DEBUGOUT("MAC address is multicast\n");
+ if (is_multicast_ether_addr(mac_addr)) {
+ pr_debug("MAC address is multicast\n");
is_valid = false;
}
/* Not a broadcast address */
- else if (IS_BROADCAST(mac_addr)) {
- DEBUGOUT("MAC address is broadcast\n");
+ else if (is_broadcast_ether_addr(mac_addr)) {
+ pr_debug("MAC address is broadcast\n");
is_valid = false;
}
/* Reject the zero address */
- else if (mac_addr[0] == 0 &&
- mac_addr[1] == 0 &&
- mac_addr[2] == 0 &&
- mac_addr[3] == 0 &&
- mac_addr[4] == 0 &&
- mac_addr[5] == 0) {
- DEBUGOUT("MAC address is all zeros\n");
+ else if (is_zero_ether_addr(mac_addr)) {
+ pr_debug("MAC address is all zeros\n");
is_valid = false;
}
return (is_valid);
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index af6ca3a..873d32b 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -636,18 +636,6 @@ struct ixgb_flash_buffer {
u8 filler3[0xAAAA];
};
-/*
- * This is a little-endian specific check.
- */
-#define IS_MULTICAST(Address) \
- (bool)(((u8 *)(Address))[0] & ((u8)0x01))
-
-/*
- * Check whether an address is broadcast.
- */
-#define IS_BROADCAST(Address) \
- ((((u8 *)(Address))[0] == ((u8)0xff)) && (((u8 *)(Address))[1] == ((u8)0xff)))
-
/* Flow control parameters */
struct ixgb_fc {
u32 high_water; /* Flow Control High-water */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 912dd1d..3cf7951 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -26,6 +26,8 @@
*******************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "ixgb.h"
char ixgb_driver_name[] = "ixgb";
@@ -146,10 +148,8 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
static int __init
ixgb_init_module(void)
{
- printk(KERN_INFO "%s - version %s\n",
- ixgb_driver_string, ixgb_driver_version);
-
- printk(KERN_INFO "%s\n", ixgb_copyright);
+ pr_info("%s - version %s\n", ixgb_driver_string, ixgb_driver_version);
+ pr_info("%s\n", ixgb_copyright);
return pci_register_driver(&ixgb_driver);
}
@@ -374,8 +374,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} else {
if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) ||
(err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) {
- printk(KERN_ERR
- "ixgb: No usable DMA configuration, aborting\n");
+ pr_err("No usable DMA configuration, aborting\n");
goto err_dma_mask;
}
pci_using_dac = 0;
@@ -1118,15 +1117,14 @@ ixgb_watchdog(unsigned long data)
if (adapter->hw.link_up) {
if (!netif_carrier_ok(netdev)) {
- printk(KERN_INFO "ixgb: %s NIC Link is Up 10 Gbps "
- "Full Duplex, Flow Control: %s\n",
- netdev->name,
- (adapter->hw.fc.type == ixgb_fc_full) ?
- "RX/TX" :
- ((adapter->hw.fc.type == ixgb_fc_rx_pause) ?
- "RX" :
- ((adapter->hw.fc.type == ixgb_fc_tx_pause) ?
- "TX" : "None")));
+ netdev_info(netdev,
+ "NIC Link is Up 10 Gbps Full Duplex, Flow Control: %s\n",
+ (adapter->hw.fc.type == ixgb_fc_full) ?
+ "RX/TX" :
+ (adapter->hw.fc.type == ixgb_fc_rx_pause) ?
+ "RX" :
+ (adapter->hw.fc.type == ixgb_fc_tx_pause) ?
+ "TX" : "None");
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
@@ -1135,8 +1133,7 @@ ixgb_watchdog(unsigned long data)
if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
- printk(KERN_INFO "ixgb: %s NIC Link is Down\n",
- netdev->name);
+ netdev_info(netdev, "NIC Link is Down\n");
netif_carrier_off(netdev);
}
}
@@ -2322,7 +2319,7 @@ static void ixgb_io_resume(struct pci_dev *pdev)
if (netif_running(netdev)) {
if (ixgb_up(adapter)) {
- printk ("ixgb: can't bring device back up after reset\n");
+ pr_err("can't bring device back up after reset\n");
return;
}
}
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 371a6be..e361185 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -41,20 +41,8 @@
#undef ASSERT
#define ASSERT(x) BUG_ON(!(x))
-#define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B)
-
-#ifdef DBG
-#define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
-#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
-#else
-#define DEBUGOUT(S)
-#define DEBUGOUT1(S, A...)
-#endif
-
-#define DEBUGFUNC(F) DEBUGOUT(F)
-#define DEBUGOUT2 DEBUGOUT1
-#define DEBUGOUT3 DEBUGOUT2
-#define DEBUGOUT7 DEBUGOUT3
+
+#define ENTER() pr_debug("%s\n", __func__);
#define IXGB_WRITE_REG(a, reg, value) ( \
writel((value), ((a)->hw_addr + IXGB_##reg)))
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index af35e1d..88a08f0 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -26,6 +26,8 @@
*******************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "ixgb.h"
/* This is the only thing that needs to be changed to adjust the
@@ -209,16 +211,16 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
case enable_option:
switch (*value) {
case OPTION_ENABLED:
- printk(KERN_INFO "%s Enabled\n", opt->name);
+ pr_info("%s Enabled\n", opt->name);
return 0;
case OPTION_DISABLED:
- printk(KERN_INFO "%s Disabled\n", opt->name);
+ pr_info("%s Disabled\n", opt->name);
return 0;
}
break;
case range_option:
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
- printk(KERN_INFO "%s set to %i\n", opt->name, *value);
+ pr_info("%s set to %i\n", opt->name, *value);
return 0;
}
break;
@@ -230,7 +232,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
ent = &opt->arg.l.p[i];
if (*value == ent->i) {
if (ent->str[0] != '\0')
- printk(KERN_INFO "%s\n", ent->str);
+ pr_info("%s\n", ent->str);
return 0;
}
}
@@ -240,8 +242,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
BUG();
}
- printk(KERN_INFO "Invalid %s specified (%i) %s\n",
- opt->name, *value, opt->err);
+ pr_info("Invalid %s specified (%i) %s\n", opt->name, *value, opt->err);
*value = opt->def;
return -1;
}
@@ -261,9 +262,8 @@ ixgb_check_options(struct ixgb_adapter *adapter)
{
int bd = adapter->bd_number;
if (bd >= IXGB_MAX_NIC) {
- printk(KERN_NOTICE
- "Warning: no configuration for board #%i\n", bd);
- printk(KERN_NOTICE "Using defaults for all values\n");
+ pr_notice("Warning: no configuration for board #%i\n", bd);
+ pr_notice("Using defaults for all values\n");
}
{ /* Transmit Descriptor Count */
@@ -363,8 +363,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
adapter->hw.fc.high_water = opt.def;
}
if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
- printk(KERN_INFO
- "Ignoring RxFCHighThresh when no RxFC\n");
+ pr_info("Ignoring RxFCHighThresh when no RxFC\n");
}
{ /* Receive Flow Control Low Threshold */
const struct ixgb_option opt = {
@@ -383,8 +382,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
adapter->hw.fc.low_water = opt.def;
}
if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
- printk(KERN_INFO
- "Ignoring RxFCLowThresh when no RxFC\n");
+ pr_info("Ignoring RxFCLowThresh when no RxFC\n");
}
{ /* Flow Control Pause Time Request*/
const struct ixgb_option opt = {
@@ -404,17 +402,14 @@ ixgb_check_options(struct ixgb_adapter *adapter)
adapter->hw.fc.pause_time = opt.def;
}
if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
- printk(KERN_INFO
- "Ignoring FCReqTimeout when no RxFC\n");
+ pr_info("Ignoring FCReqTimeout when no RxFC\n");
}
/* high low and spacing check for rx flow control thresholds */
if (adapter->hw.fc.type & ixgb_fc_tx_pause) {
/* high must be greater than low */
if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
/* set defaults */
- printk(KERN_INFO
- "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
- "Using Defaults\n");
+ pr_info("RxFCHighThresh must be >= (RxFCLowThresh + 8), Using Defaults\n");
adapter->hw.fc.high_water = DEFAULT_FCRTH;
adapter->hw.fc.low_water = DEFAULT_FCRTL;
}
^ permalink raw reply related
* [net-next-2.6 PATCH 1/2] igb: double increment nr_frags
From: Jeff Kirsher @ 2010-04-27 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Koki Sanagi, Jeff Kirsher
From: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
There is no need to increment nr_frags because skb_fill_page_desc increments
it.
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index c19b1e0..a14303a 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -5248,7 +5248,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
buffer_info->page_dma = 0;
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
buffer_info->page,
buffer_info->page_offset,
length);
^ permalink raw reply related
* [net-next-2.6 PATCH 2/2] igbvf: double increment nr_frags
From: Jeff Kirsher @ 2010-04-27 11:01 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Koki Sanagi, Jeff Kirsher
In-Reply-To: <20100427110107.23872.86247.stgit@localhost.localdomain>
From: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
There is no need to increment nr_frags because skb_fill_page_desc increments
it.
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igbvf/netdev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index cc23090..9ac3f94 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -289,7 +289,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter,
PCI_DMA_FROMDEVICE);
buffer_info->page_dma = 0;
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
buffer_info->page,
buffer_info->page_offset,
length);
^ permalink raw reply related
* [net-next-2.6 PATCH] igb: add support for reporting 5GT/s during probe on PCIe Gen2
From: Jeff Kirsher @ 2010-04-27 11:02 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change corrects the fact that we were not reporting Gen2 link speeds
when we were in fact connected at Gen2 rates.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/e1000_defines.h | 4 ----
drivers/net/igb/e1000_mac.c | 27 ++++++++++++++++++++-------
drivers/net/igb/igb_main.c | 1 +
include/linux/pci_regs.h | 3 +++
4 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 31d24e0..24d9be6 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -610,11 +610,7 @@
#define IGP_LED3_MODE 0x07000000
/* PCI/PCI-X/PCI-EX Config space */
-#define PCIE_LINK_STATUS 0x12
#define PCIE_DEVICE_CONTROL2 0x28
-
-#define PCIE_LINK_WIDTH_MASK 0x3F0
-#define PCIE_LINK_WIDTH_SHIFT 4
#define PCIE_DEVICE_CONTROL2_16ms 0x0005
#define PHY_REVISION_MASK 0xFFFFFFF0
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index be8d010..90c5e01 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -53,17 +53,30 @@ s32 igb_get_bus_info_pcie(struct e1000_hw *hw)
u16 pcie_link_status;
bus->type = e1000_bus_type_pci_express;
- bus->speed = e1000_bus_speed_2500;
ret_val = igb_read_pcie_cap_reg(hw,
- PCIE_LINK_STATUS,
- &pcie_link_status);
- if (ret_val)
+ PCI_EXP_LNKSTA,
+ &pcie_link_status);
+ if (ret_val) {
bus->width = e1000_bus_width_unknown;
- else
+ bus->speed = e1000_bus_speed_unknown;
+ } else {
+ switch (pcie_link_status & PCI_EXP_LNKSTA_CLS) {
+ case PCI_EXP_LNKSTA_CLS_2_5GB:
+ bus->speed = e1000_bus_speed_2500;
+ break;
+ case PCI_EXP_LNKSTA_CLS_5_0GB:
+ bus->speed = e1000_bus_speed_5000;
+ break;
+ default:
+ bus->speed = e1000_bus_speed_unknown;
+ break;
+ }
+
bus->width = (enum e1000_bus_width)((pcie_link_status &
- PCIE_LINK_WIDTH_MASK) >>
- PCIE_LINK_WIDTH_SHIFT);
+ PCI_EXP_LNKSTA_NLW) >>
+ PCI_EXP_LNKSTA_NLW_SHIFT);
+ }
reg = rd32(E1000_STATUS);
bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index a14303a..919e363 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1638,6 +1638,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
netdev->name,
((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+ (hw->bus.speed == e1000_bus_speed_5000) ? "5.0Gb/s" :
"unknown"),
((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
(hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" :
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index c8f3029..c4c3d68 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -442,7 +442,10 @@
#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Lnk Autonomous Bandwidth Interrupt Enable */
#define PCI_EXP_LNKSTA 18 /* Link Status */
#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */
+#define PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
+#define PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Nogotiated Link Width */
+#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */
#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */
#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
^ permalink raw reply related
* [net-2.6 PATCH] ixgbe: cleanup ethtool autoneg input
From: Jeff Kirsher @ 2010-04-27 11:25 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Don Skidmore, Jeff Kirsher
From: Don Skidmore <donald.c.skidmore@intel.com>
The way we were setting autoneg via ethtool was inconstant with that
of our other drivers. It will change the following:
If autoneg is off:
>ethtool -a eth0
Pause parameters for eth0:
Autonegotiate: off
RX: off
TX: off
Before:
>ethtool -A eth0 autoneg on
>ethtool -a eth0
Pause parameters for eth0:
Autonegotiate: off
RX: off
TX: off
Now:
>ethtool -A eth0 autoneg on
>ethtool -a eth0
Pause parameters for eth0:
Autonegotiate: on
RX: on
TX: on
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 8f461d5..7b391f9 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -365,7 +365,7 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
else
fc.disable_fc_autoneg = false;
- if (pause->rx_pause && pause->tx_pause)
+ if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
fc.requested_mode = ixgbe_fc_full;
else if (pause->rx_pause && !pause->tx_pause)
fc.requested_mode = ixgbe_fc_rx_pause;
^ permalink raw reply related
* [net-next-2.6 PATCH 1/2] ixgbe: enable extremely low latency
From: Jeff Kirsher @ 2010-04-27 11:37 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Jesse Brandeburg, Jeff Kirsher
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
82598/82599 can support EITR == 0, which allows for the
absolutely lowest latency setting in the hardware. This disables
writeback batching and anything else that relies upon a delayed
interrupt. This patch enables the feature of "override" when a
user sets rx-usecs to zero, the driver will respect that setting
over using RSC, and automatically disable RSC. If rx-usecs is
used to set the EITR value to 0, then the driver should disable
LRO (aka RSC) internally until EITR is set to non-zero again.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 87 +++++++++++++++++++++++++++++++++----
drivers/net/ixgbe/ixgbe_main.c | 9 ++++
2 files changed, 87 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 7b391f9..b72a997 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2079,6 +2079,27 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
return 0;
}
+/*
+ * this function must be called before setting the new value of
+ * rx_itr_setting
+ */
+static void ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
+ struct ethtool_coalesce *ec)
+{
+ /* check the old value and enable RSC if necessary */
+ if ((adapter->rx_itr_setting == 0) &&
+ (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
+ adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+ adapter->netdev->features |= NETIF_F_LRO;
+ DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
+ ec->rx_coalesce_usecs);
+ if (netif_running(adapter->netdev))
+ ixgbe_reinit_locked(adapter);
+ else
+ ixgbe_reset(adapter);
+ }
+}
+
static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -2095,11 +2116,20 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
if (ec->rx_coalesce_usecs > 1) {
+ u32 max_int;
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+ max_int = IXGBE_MAX_RSC_INT_RATE;
+ else
+ max_int = IXGBE_MAX_INT_RATE;
+
/* check the limits */
- if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
+ if ((1000000/ec->rx_coalesce_usecs > max_int) ||
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
+ /* check the old value and enable RSC if necessary */
+ ixgbe_reenable_rsc(adapter, ec);
+
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2108,6 +2138,9 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
/* clear the lower bit as its used for dynamic state */
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
+ /* check the old value and enable RSC if necessary */
+ ixgbe_reenable_rsc(adapter, ec);
+
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
adapter->rx_itr_setting = 1;
@@ -2116,14 +2149,34 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
* any other value means disable eitr, which is best
* served by setting the interrupt rate very high
*/
- if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
- adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
- else
- adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
+ adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
adapter->rx_itr_setting = 0;
+
+ /*
+ * if hardware RSC is enabled, disable it when
+ * setting low latency mode, to avoid errata, assuming
+ * that when the user set low latency mode they want
+ * it at the cost of anything else
+ */
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+ adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+ netdev->features &= ~NETIF_F_LRO;
+ DPRINTK(PROBE, INFO,
+ "rx-usecs set to 0, disabling RSC\n");
+
+ if (netif_running(netdev))
+ ixgbe_reinit_locked(adapter);
+ else
+ ixgbe_reset(adapter);
+ return 0;
+ }
}
if (ec->tx_coalesce_usecs > 1) {
+ /*
+ * don't have to worry about max_int as above because
+ * tx vectors don't do hardware RSC (an rx function)
+ */
/* check the limits */
if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
(1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
@@ -2178,10 +2231,26 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
ethtool_op_set_flags(netdev, data);
/* if state changes we need to update adapter->flags and reset */
- if ((!!(data & ETH_FLAG_LRO)) !=
- (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
- adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
- need_reset = true;
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) {
+ /*
+ * cast both to bool and verify if they are set the same
+ * but only enable RSC if itr is non-zero, as
+ * itr=0 and RSC are mutually exclusive
+ */
+ if (((!!(data & ETH_FLAG_LRO)) !=
+ (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) &&
+ adapter->rx_itr_setting) {
+ adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ need_reset = true;
+ break;
+ default:
+ break;
+ }
+ } else if (!adapter->rx_itr_setting) {
+ netdev->features &= ~ETH_FLAG_LRO;
+ }
}
/*
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 32781b3..0c4ca68 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1190,6 +1190,15 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
itr_reg |= (itr_reg << 16);
} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
/*
+ * 82599 can support a value of zero, so allow it for
+ * max interrupt rate, but there is an errata where it can
+ * not be zero with RSC
+ */
+ if (itr_reg == 8 &&
+ !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
+ itr_reg = 0;
+
+ /*
* set the WDIS bit to not clear the timer bits and cause an
* immediate assertion of the interrupt
*/
^ permalink raw reply related
* [net-next-2.6 PATCH 2/2] ixgbe: fix bug when EITR=0 causing no writebacks
From: Jeff Kirsher @ 2010-04-27 11:37 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Jesse Brandeburg, Jeff Kirsher
In-Reply-To: <20100427113651.24431.9221.stgit@localhost.localdomain>
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
writebacks can be held indefinitely by hardware if EITR=0, when
combined with TXDCTL.WTHRESH=8. When EITR=0, WTHRESH should be
set back to zero.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 31 +++++++++++++++++++------------
drivers/net/ixgbe/ixgbe_main.c | 9 +++++++--
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index b72a997..dfbfe35 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2083,7 +2083,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
* this function must be called before setting the new value of
* rx_itr_setting
*/
-static void ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
+static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
struct ethtool_coalesce *ec)
{
/* check the old value and enable RSC if necessary */
@@ -2093,11 +2093,9 @@ static void ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
adapter->netdev->features |= NETIF_F_LRO;
DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
ec->rx_coalesce_usecs);
- if (netif_running(adapter->netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
+ return true;
}
+ return false;
}
static int ixgbe_set_coalesce(struct net_device *netdev,
@@ -2106,6 +2104,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_q_vector *q_vector;
int i;
+ bool need_reset = false;
/* don't accept tx specific changes if we've got mixed RxTx vectors */
if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
@@ -2128,7 +2127,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
return -EINVAL;
/* check the old value and enable RSC if necessary */
- ixgbe_reenable_rsc(adapter, ec);
+ need_reset = ixgbe_reenable_rsc(adapter, ec);
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2139,7 +2138,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
/* check the old value and enable RSC if necessary */
- ixgbe_reenable_rsc(adapter, ec);
+ need_reset = ixgbe_reenable_rsc(adapter, ec);
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
@@ -2164,11 +2163,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
DPRINTK(PROBE, INFO,
"rx-usecs set to 0, disabling RSC\n");
- if (netif_running(netdev))
- ixgbe_reinit_locked(adapter);
- else
- ixgbe_reset(adapter);
- return 0;
+ need_reset = true;
}
}
@@ -2220,6 +2215,18 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
ixgbe_write_eitr(q_vector);
}
+ /*
+ * do reset here at the end to make sure EITR==0 case is handled
+ * correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings
+ * also locks in RSC enable/disable which requires reset
+ */
+ if (need_reset) {
+ if (netif_running(netdev))
+ ixgbe_reinit_locked(adapter);
+ else
+ ixgbe_reset(adapter);
+ }
+
return 0;
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 0c4ca68..fe7e260 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -2945,8 +2945,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) {
j = adapter->tx_ring[i]->reg_idx;
txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
- /* enable WTHRESH=8 descriptors, to encourage burst writeback */
- txdctl |= (8 << 16);
+ if (adapter->rx_itr_setting == 0) {
+ /* cannot set wthresh when itr==0 */
+ txdctl &= ~0x007F0000;
+ } else {
+ /* enable WTHRESH=8 descriptors, to encourage burst writeback */
+ txdctl |= (8 << 16);
+ }
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
}
^ permalink raw reply related
* [net-next-2.6 PATCH] ixgbe: ixgbe_down needs to stop dev_watchdog
From: Jeff Kirsher @ 2010-04-27 12:13 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, John Fastabend, Peter P Waskiewicz Jr,
Jeff Kirsher
From: John Fastabend <john.r.fastabend@intel.com>
There is a small race between when the tx queues are stopped
and when netif_carrier_off() is called in ixgbe_down. If the
dev_watchdog() timer fires during this time it is possible for
a false tx timeout to occur.
This patch moves the netif_carrier_off() so that it is called before
the tx queues are stopped preventing the dev_watchdog timer from
detecting false tx timeouts. The race is seen occosionally when
FCoE or DCB settings are being configured or changed.
Testing note, running ifconfig up/down will not reproduce this
issue because dev_open/dev_close call dev_deactivate() and then
dev_activate().
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_main.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index fe7e260..5258b3d 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3291,22 +3291,23 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
- netif_tx_disable(netdev);
-
IXGBE_WRITE_FLUSH(hw);
msleep(10);
netif_tx_stop_all_queues(netdev);
- ixgbe_irq_disable(adapter);
-
- ixgbe_napi_disable_all(adapter);
-
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->sfp_timer);
del_timer_sync(&adapter->watchdog_timer);
cancel_work_sync(&adapter->watchdog_task);
+ netif_carrier_off(netdev);
+ netif_tx_disable(netdev);
+
+ ixgbe_irq_disable(adapter);
+
+ ixgbe_napi_disable_all(adapter);
+
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
@@ -3324,8 +3325,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
~IXGBE_DMATXCTL_TE));
- netif_carrier_off(netdev);
-
/* clear n-tuple filters that are cached */
ethtool_ntuple_flush(netdev);
^ permalink raw reply related
* Re: [PATCH RFC: linux-next 1/2] irq: Add CPU mask affinity hint callback framework
From: Thomas Gleixner @ 2010-04-27 12:32 UTC (permalink / raw)
To: Peter P Waskiewicz Jr; +Cc: davem, arjan, netdev, linux-kernel
In-Reply-To: <20100419045741.30276.23233.stgit@ppwaskie-hc2.jf.intel.com>
On Sun, 18 Apr 2010, Peter P Waskiewicz Jr wrote:
> +/**
> + * struct irqaffinityhint - per interrupt affinity helper
> + * @callback: device driver callback function
> + * @dev: reference for the affected device
> + * @irq: interrupt number
> + */
> +struct irqaffinityhint {
> + irq_affinity_hint_t callback;
> + void *dev;
> + int irq;
> +};
Why do you need that extra data structure ? The device and the irq
number are known, so all you need is the callback itself. So no need
for allocating memory ....
> +static ssize_t irq_affinity_hint_proc_write(struct file *file,
> + const char __user *buffer, size_t count, loff_t *pos)
> +{
> + /* affinity_hint is read-only from proc */
> + return -EOPNOTSUPP;
> +}
> +
Why do you want a write function when the file is read only ?
Thanks,
tglx
^ permalink raw reply
* Re: [net-next-2.6 PATCH 1/2] Add ndo_set_vf_port_profile
From: Arnd Bergmann @ 2010-04-27 12:35 UTC (permalink / raw)
To: Scott Feldman
Cc: Rose, Gregory V, David Miller, netdev@vger.kernel.org,
chrisw@redhat.com, Williams, Mitch A
In-Reply-To: <C7FB77DB.2BC42%scofeldm@cisco.com>
On Tuesday 27 April 2010, Scott Feldman wrote:
> > Yes, I believe that's there today:
> >
> > NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
> >
> > The number of VFs is returned in RTM_GETLINK. But, it's only returned if:
> >
> > if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent)
> >
> > For my proposal, I'll need to return IFLA_NUM_VF unconditionally so callers
> > can get num VFs.
>
> Hmmm...seems IFLA_NUM_VF assumes a PCI device supporting SR-IOV when it uses
> dev_num_vf(). I think a better option would have been to query the device
> for the number of VFs, without assuming SR-IOV or even PCI.
>
> I see a ndo_get_num_vf() coming...
Shouldn't the number of registered port profiles be totally independent of
the number of virtual functions?
Any of the VFs could multiplex multiple guests using macvlan, which means you
need to register each guest separately, not each VF.
Anything that ties port profiles to VFs seems fundamentally flawed AFAICT,
at least when we want to extend this to adapters that don't do it in firmware.
Arnd
^ permalink raw reply
* [PATCH net-next-2.6] rps: inet_rps_save_rxhash() argument is not const
From: Eric Dumazet @ 2010-04-27 12:42 UTC (permalink / raw)
To: David Miller; +Cc: netdev
const qualifier on sock argument is misleading, since we can modify rxhash.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index b487bc1..c1d4295 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -248,7 +248,7 @@ static inline void inet_rps_reset_flow(const struct sock *sk)
#endif
}
-static inline void inet_rps_save_rxhash(const struct sock *sk, u32 rxhash)
+static inline void inet_rps_save_rxhash(struct sock *sk, u32 rxhash)
{
#ifdef CONFIG_RPS
if (unlikely(inet_sk(sk)->rxhash != rxhash)) {
^ permalink raw reply related
* [PATCH 0/4] net: ipmr netlink interface for route dumping
From: Patrick, McHardy, kaber @ 2010-04-27 13:26 UTC (permalink / raw)
To: davem; +Cc: netdev
These patches add support to ipmr to dump routes of all tables over
netlink. The /proc interface contains an unterminated list of oifs
at the end of a line, therefore it can't be extended to print the
routing table number without breaking backwards compatibility.
These patches fully decouple rtnetlink families from real address
families and add a new family RTNL_FAMILY_IPMR for ipmr as well as
a RTM_GETROUTE handler.
The first patch additionally marks the fib_rules_ops templates as
const __net_initdata. This is not directly related to the netlink
interface, but was already queued in my tree.
Please apply or pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/kaber/ipmr-2.6.git master
Thanks!
^ permalink raw reply
* [PATCH 2/3] net: rtnetlink: decouple rtnetlink address families from real address families
From: Patrick, McHardy, kaber @ 2010-04-27 13:26 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1272374785-3858-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Decouple rtnetlink address families from real address families in socket.h to
be able to add rtnetlink interfaces to code that is not a real address family
without increasing AF_MAX/NPROTO.
This will be used to add support for multicast route dumping from all tables
as the proc interface can't be extended to support anything but the main table
without breaking compatibility.
This partialy undoes the patch to introduce independant families for routing
rules and converts ipmr routing rules to a new rtnetlink family. Similar to
that patch, values up to 127 are reserved for real address families, values
above that may be used arbitrarily.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/fib_rules.h | 8 --------
include/linux/rtnetlink.h | 6 ++++++
net/core/rtnetlink.c | 14 +++++++-------
net/decnet/dn_rules.c | 2 +-
net/ipv4/fib_rules.c | 2 +-
net/ipv4/ipmr.c | 2 +-
net/ipv6/fib6_rules.c | 2 +-
7 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index 04a3976..51da65b 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -15,14 +15,6 @@
/* try to find source address in routing lookups */
#define FIB_RULE_FIND_SADDR 0x00010000
-/* fib_rules families. values up to 127 are reserved for real address
- * families, values above 128 may be used arbitrarily.
- */
-#define FIB_RULES_IPV4 AF_INET
-#define FIB_RULES_IPV6 AF_INET6
-#define FIB_RULES_DECNET AF_DECnet
-#define FIB_RULES_IPMR 128
-
struct fib_rule_hdr {
__u8 family;
__u8 dst_len;
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index d1c7c90..5a42c36 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -7,6 +7,12 @@
#include <linux/if_addr.h>
#include <linux/neighbour.h>
+/* rtnetlink families. Values up to 127 are reserved for real address
+ * families, values above 128 may be used arbitrarily.
+ */
+#define RTNL_FAMILY_IPMR 128
+#define RTNL_FAMILY_MAX 128
+
/****
* Routing/neighbour discovery messages.
****/
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 78c8598..fd781b6 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -98,7 +98,7 @@ int lockdep_rtnl_is_held(void)
EXPORT_SYMBOL(lockdep_rtnl_is_held);
#endif /* #ifdef CONFIG_PROVE_LOCKING */
-static struct rtnl_link *rtnl_msg_handlers[NPROTO];
+static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1];
static inline int rtm_msgindex(int msgtype)
{
@@ -118,7 +118,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
{
struct rtnl_link *tab;
- if (protocol < NPROTO)
+ if (protocol <= RTNL_FAMILY_MAX)
tab = rtnl_msg_handlers[protocol];
else
tab = NULL;
@@ -133,7 +133,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
{
struct rtnl_link *tab;
- if (protocol < NPROTO)
+ if (protocol <= RTNL_FAMILY_MAX)
tab = rtnl_msg_handlers[protocol];
else
tab = NULL;
@@ -167,7 +167,7 @@ int __rtnl_register(int protocol, int msgtype,
struct rtnl_link *tab;
int msgindex;
- BUG_ON(protocol < 0 || protocol >= NPROTO);
+ BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
msgindex = rtm_msgindex(msgtype);
tab = rtnl_msg_handlers[protocol];
@@ -219,7 +219,7 @@ int rtnl_unregister(int protocol, int msgtype)
{
int msgindex;
- BUG_ON(protocol < 0 || protocol >= NPROTO);
+ BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
msgindex = rtm_msgindex(msgtype);
if (rtnl_msg_handlers[protocol] == NULL)
@@ -241,7 +241,7 @@ EXPORT_SYMBOL_GPL(rtnl_unregister);
*/
void rtnl_unregister_all(int protocol)
{
- BUG_ON(protocol < 0 || protocol >= NPROTO);
+ BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
kfree(rtnl_msg_handlers[protocol]);
rtnl_msg_handlers[protocol] = NULL;
@@ -1384,7 +1384,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
if (s_idx == 0)
s_idx = 1;
- for (idx = 1; idx < NPROTO; idx++) {
+ for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) {
int type = cb->nlh->nlmsg_type-RTM_BASE;
if (idx < s_idx || idx == PF_PACKET)
continue;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 1226bca..48fdf10 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -217,7 +217,7 @@ static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
}
static const struct fib_rules_ops __net_initdata dn_fib_rules_ops_template = {
- .family = FIB_RULES_DECNET,
+ .family = AF_DECnet,
.rule_size = sizeof(struct dn_fib_rule),
.addr_size = sizeof(u16),
.action = dn_fib_rule_action,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 8ab62a5..76daeb5 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -246,7 +246,7 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
}
static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = {
- .family = FIB_RULES_IPV4,
+ .family = AF_INET,
.rule_size = sizeof(struct fib4_rule),
.addr_size = sizeof(u32),
.action = fib4_rule_action,
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 7d3e382..41e8fc0 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -217,7 +217,7 @@ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
}
static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = {
- .family = FIB_RULES_IPMR,
+ .family = RTNL_FAMILY_IPMR,
.rule_size = sizeof(struct ipmr_rule),
.addr_size = sizeof(u32),
.action = ipmr_rule_action,
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 35f6949..8e44f8f 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -238,7 +238,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
}
static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = {
- .family = FIB_RULES_IPV6,
+ .family = AF_INET6,
.rule_size = sizeof(struct fib6_rule),
.addr_size = sizeof(struct in6_addr),
.action = fib6_rule_action,
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox