* Re: Disabling "TCP Treason uncloaked"
From: Herbert Xu @ 2006-05-02 23:00 UTC (permalink / raw)
To: Just Marc; +Cc: netdev
In-Reply-To: <44578691.4020402@corky.net>
Just Marc <marc@corky.net> wrote:
>
> Looking at mailing list archives there has been much talk of this print
> in the past, given the fact that this check/print is surrounded by an
A good number of these turned out to be a bug in the Linux TCP stack.
If this message wasn't there we would've never found it.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* VJ Channel API - driver level (PATCH)
From: Alex Aizman @ 2006-05-02 22:53 UTC (permalink / raw)
To: netdev
Signed-off-by: Alex Aizman <alex@xxxxxxxxxx>
Hacked netdevice.h to support multiple channels.
--- netdevice-orig.h 2006-03-04 10:01:38.000000000 -0800
+++ netdevice-channel.h 2006-03-09 10:17:11.419955200 -0800
@@ -246,6 +246,147 @@
extern int __init netdev_boot_setup(char *str);
+#ifdef CONFIG_NET_CHANNELS
+/*************** NETDEVICE HW CHANNELS data structures *****************/
+/**
+ * enum netdev_hwchannel_rx_flow_e - Hardware receive channel "flow" types.
+ * @HWCH_RX_FLOW_NONE: does not filter rx packets.
+ * @HWCH_RX_FLOW_MACADDR: filters based upon the rx mac address
+ * @HWCH_RX_FLOW_VLAN_ID: filters based upon the rx vlan id tag
+ * @HWCH_RX_FLOW_VLAN_QOS: fikters based upon the vlan qos field
+ * @HWCH_RX_FLOW_PORT: filters based upon the tcp or udp receive port number
+ * @HWCH_RX_FLOW_L4_HASH: filters based upon a hash of the tcp session id
+ * @HWCH_RX_FLOW_L4_SPDM: filters based upon a hash of the four-tuple of the
+ * following: source ip, source port, destination ip, destinaton port
+ *
+ * A rx is bound to a specific device. When one of thsese enums is used,
+ * traffic is filtered onto the queue of only the requested type. By default
+ * we use HWCH_RX_FLOW_NONE as we usually want all traffic from this device.
+ **/
+typedef enum netdev_hwchannel_rx_flow_e {
+ HWCH_RX_FLOW_NONE,
+ HWCH_RX_FLOW_MACADDR,
+ HWCH_RX_FLOW_VLAN_ID,
+ HWCH_RX_FLOW_VLAN_QOS,
+ HWCH_RX_FLOW_PORT,
+ HWCH_RX_FLOW_L4_HASH,
+ HWCH_RX_FLOW_L4_SPDM,
+} netdev_hwchan_rx_flow_e;
+
+/**
+ * enum enum netdev_hwchannel_priority_e - Hardware channel priorities.
+ * @HWCH_PRIORITY_NONE: no priority, process as fast as possible
+ * @HWCH_PRIORITY_LOWEST: process all other channels first
+ * @HWCH_PRIORITY_LOW: channel with low priority
+ * @HWCH_PRIORITY_MEDIUM: channel with medium priority
+ * @HWCH_PRIORITY_HIGH: channel with high priority
+ * @HWCH_PRIORITY_HIGHEST: process this channel before all others
+ *
+ * Channel priorities can be set on both tx and rx channels. A default
+ * priority of HWCH_PRIORITY_NONE means all channels are considered equal by
+ * the hardware. If a priority is set then HWCH_PRIORITY_HIGHEST is treated
+ * first and HWCH_PRIORITY_LOWEST is treated last.
+ *
+ **/
+typedef enum netdev_hwchannel_priority_e {
+ HWCH_PRIORITY_NONE,
+ HWCH_PRIORITY_LOWEST,
+ HWCH_PRIORITY_LOW,
+ HWCH_PRIORITY_MEDIUM,
+ HWCH_PRIORITY_HIGH,
+ HWCH_PRIORITY_HIGHEST,
+} netdev_hwchan_priority_e;
+
+/**
+ * struct netdev_rx_flow - Uniquely identifies the traffic flow for a given
+ * rx channel.
+ * @type: specifies what type of traffic flow this channel will use. This
+ * also specifies which of the fields in the union will be examined.
+ * @macaddr: if type is set to HWCH_RX_FLOW_MACADDR this field will be used
+ * to only accept traffic from this mac address
+ * @vlan_id: if type is set to HWCH_RX_FLOW_VLAN_ID this field will be used
+ * to only accept traffic from packets with this vlan id
+ * @vlan_qos: if type is set to HWCH_RX_FLOW_VLAN_QOS this field will be used
+ * to only accept traffic from packets with this vlan qos tag
+ * @port: if type is set to HWCH_RX_FLOW_PORT this field will be used to only
+ * accept traffic from tcp or udp packets with this destination port number
+ * @session_id: if type is set to HWCH_RX_FLOW_L4_HASH this field will be used
+ * to only allow tcp traffic from this specific session id
+ * @l4_4tuple: if type ie set to HWCH_RX_FLOW_L4_SPDM this struct will be
+ * used to only accept traffic which has the correct four-tuple consisting of:
+ * source ip, source port, destination ip, destinatopn port
+ *
+ * Receive channels can be set to shape the types of traffic placed upon them.
+ * This interface allows one to determine how to shape incoming traffic on
+ * a specified channel. For example, if
+ * netdev_rx_flow.type = HWCH_RX_FLOW_PORT and
+ * netdev_rx_flow.rx_flow_val.port = 3260 identifies all standard iSCSI
+ * traffic. The API call bind_rx_channel() is used to take the contents of
+ * struct netdev_rx_flow and apply it to a given rx channel.
+ **/
+struct netdev_rx_flow {
+ netdev_hwchan_rx_flow_e type;
+ union rx_flow_val {
+ unsigned char macaddr[MAX_ADDR_LEN];/* HWCH_RX_FLOW_MACADDR */
+ unsigned short vlan_id; /* HWCH_RX_FLOW_VLAN_ID */
+ unsigned char vlan_qos; /* HWCH_RX_FLOW_VLAN_QOS */
+ unsigned short port; /* HWCH_RX_FLOW_PORT */
+ unsigned int session_id; /* HWCH_RX_FLOW_L4_HASH */
+ struct { /* HWCH_RX_FLOW_L4_SPDM */
+ uint32_t src_ip;
+ unsigned short src_port;
+ uint32_t dst_ip;
+ unsigned short dst_port;
+ } l4_4tuple;
+ } rx_flow_val;
+};
+
+/**
+ * (*netif_rx_hwchannel_cb) - function to be used for an rx channels callback.
+ * @skb: system network buffer to place next available packet from the channel
+ * @kernel_channelh: hardware rx channel handle to bind process
+ * @flow: specifies the type of traffic flow to examine for the given hardware
+ * rx channel
+ *
+ * By using this callback an application can harvest traffic from a specific
+ * hardware rx channel bypassing the kernel. This function is optional.
+ **/
+typedef int (*netif_rx_hwchannel_cb) (struct sk_buff *skb,
+ void *kernel_channelh,
+ struct netdev_rx_flow flow);
+
+/**************************************************************************
+ * 2. Kernel-provided Calls (optional).
+ * ----------------------------------
+ * "Channelized" alterations of the corresponding netif_() callbacks.
+ *************************************************************************/
+
+/**
+ * netif_rx_hwchannel - gives a received buffer from an rx channel to the
+ * linux stack.
+ * @skb: system network buffer to place next available packet from the channel
+ * @kernel_channelh: hardware rx channel handle to process
+ * @flow: specifies the type of traffic flow to examine for the given hardware
+ * rx channel
+ *
+ * Post a buffer received on a given Rx hardware channel to the stack.
+ * Used only if the channel callback is _not_ specified,
+ * see open_rx_hwchannel().
+ **/
+extern int netif_rx_hwchannel (struct sk_buff *skb,
+ void *kernel_channelh,
+ struct netdev_rx_flow flow);
+
+/*
+ * Start/Stop/Wakeup all traffic (flows) using a given Tx channel.
+ * The channel must be Tx, that is - it must be open with open_tx_hwchannel().
+ */
+extern void netif_start_queue_tx_hwchannel (void *kernel_channelh);
+extern void netif_stop_queue_tx_hwchannel (void *kernel_channelh);
+extern void netif_wakeup_queue_tx_hwchannel (void *kernel_channelh);
+extern void netif_queue_stopped (void *kernel_channelh);
+#endif /* CONFIG_NET_CHANNELS */
+
/*
* The DEVICE structure.
* Actually, this whole structure is a big mistake. It mixes I/O
@@ -502,6 +643,144 @@
/* class/net/name entry */
struct class_device class_dev;
+
+#ifdef CONFIG_NET_CHANNELS
+ /***************** NET DEVICE HW CHANNELS ******************
+ * 1. Low-level calls.
+ * Exposes uni-directional hardware-supported channel: hw_channelh.
+ * Provided by a multi-channel (driver + adapter).
+ *****************************************************************/
+
+ /**
+ * (*open_tx_hwchannel) - open a channel to be used for transmit
+ * @dev: net_device structure to associate with this channel
+ * @priority: the channel priority as to how it is processed relative
+ * to other channels
+ * @burst_size: size of the channel, number of descriptors, etc.
+ * @kernel_channelh: hardware channel to bind transmit traffic to
+ * @hw_channelh: pointer to a user handle for a given hardware channel
+ *
+ * Opens a transmit channel and binds it to the hw_channelh parameter.
+ * A hardware channel cannot be opened twice and cannot be used prior
+ * to openeing. Should any error occur, hw_channelh will point to
+ * NULL.
+ **/
+ int (*open_tx_hwchannel) (struct net_device *dev,
+ netdev_hwchan_priority_e priority,
+ int burst_size,
+ void *kernel_channelh,
+ void **hw_channelh);
+
+ /**
+ * (*open_rx_hwchannel) - open a channel to be used for receive
+ * @dev: net_device structure to associate with this channel
+ * @flow_type: the receive channel flow type to associate with this
+ * hardware channel
+ * @priority: the channel priority as to how it is processed relative
+ * to other channels
+ * @burst_size: size of the channel, number of descriptors, etc.
+ * @kernel_channelh: hardware channel to bind transimit traffic to
+ * @hw_channelh: pointer to a user handle for a given hardware channel
+ *
+ * Opens a receive channel and binds it to the hw_channelh parameter.
+ * A hardware channel cannot be opened twice and cannot be used prior
+ * to openeing. Should any error occur, hw_channelh will point to
+ * NULL.
+ * Note: open_rx_hwchannel is optional. If the callback is not
+ * specified the driver will use the regular netif_ API.
+ **/
+ int (*open_rx_hwchannel) (struct net_device *dev,
+ netdev_hwchan_rx_flow_e flow_type,
+ netdev_hwchan_priority_e priority,
+ int cpu,
+ int burst_size,
+ netif_rx_hwchannel_cb callback,
+ void *kernel_channelh,
+ void **hw_channelh);
+
+ /**
+ * (*close_hwchannel) - close a hardware channel.
+ * @hw_channelh - specifies the particular hardware channel to close.
+ *
+ * Closes down a hardware channel that has been opened. This applies
+ * to either a transmit or receive channel. Note in order to close
+ * down a channel link, both the transmit and receive channels have
+ * to be closed separately.
+ **/
+ int (*close_hwchannel) (void *hw_channelh);
+
+ /**
+ * (*hard_start_xmit_hwchannel) - post a buffer to a transmit channel
+ * @skb: network packet to add to the transmit channel
+ * @hw_channelh: transmit channel to append the packet
+ *
+ * Posts a packet into the next available slot on the given transmit
+ * channel. This call will fail if hw_channelh is not open or is
+ * not a transmit channel. Note that unlike receive there is no API
+ * to bind transmit traffic to a given channel.
+ **/
+ int (*hard_start_xmit_hwchannel) (struct sk_buff *skb,
+ void *hw_channelh);
+
+ /**
+ * (*bind_rx_hwchannel) - binds a given receive traffic flow to a
+ * receive channel
+ * @flow: specific receive flow pattern to match traffic against
+ * @hw_channelh: receive hardware channel to match traffic based upon
+ * the given flow
+ *
+ * Given a specific flow this function will bind that flow to the
+ * named receive hardware channel. The relationship between receive
+ * flows and receive hardware channels is one-to-many. This means
+ * several flows can be bound to the same receive hardware channel.
+ * The function call will fail if the channel is not a receive channel,
+ * if the channel is not opened, or if the specified flow does not
+ * correspond with the channel type applied to the channel during
+ * channel open.
+ **/
+ int (*bind_rx_hwchannel) (struct netdev_rx_flow flow, void *hw_channelh);
+
+ /**
+ * (*unbind_rx_hwchannel) - unbinds a given receive traffic flow to a
+ * receive channel
+ * @flow: specific receive flow pattern to match traffic against
+ * @hw_channelh: receive hardware channel to match traffic based upon
+ * the given flow
+ *
+ * Unbindes a certain flow from a receive hardware channel. The
+ * function will fail if the channel is not open, the channel is not
+ * a receive channel, or if the given flow has not been previously
+ * bound to the receive channel.
+ **/
+ int (*unbind_rx_hwchannel) (struct netdev_rx_flow flow, void *hw_channelh);
+
+ /*
+ * (*poll_hwchannel) - completion handler executed in a polling mode
+ * @hw_channel: hardware channel to poll
+ * @budget: number of completions "budgeted" for processing in this
+ * iteration
+ *
+ * Polls a hardware channel and tries to reap at least as many
+ * packets as contained in budgeted. This works for both transmit
+ * and receive channels. For transmit this function cleans up
+ * packets marked as completed by the hardware. For receive the
+ * packets are either passed up the netif_ stack or by the
+ * channel receive callback if one was given.
+ */
+ int (*poll_hwchannel) (int *budget, void *hw_channelh);
+
+ /**
+ * (*get_stats_hwchannel) - obtain statistics about a hardware channel
+ * @hw_channelh: specific transmit or receive hardware channel to
+ * query for statistics
+ *
+ * Returns the standard statistics about a given transmit or receive
+ * hardware channel. The statistics are stored in the usual
+ * struct net_device_stats format.
+ **/
+ struct net_device_stats* (*get_stats_hwchannel) (void *hw_channelh);
+
+#endif /* CONFIG_NET_CHANNELS */
};
#define NETDEV_ALIGN 32
^ permalink raw reply
* VJ Channel API - driver level (README)
From: Alex Aizman @ 2006-05-02 22:53 UTC (permalink / raw)
To: netdev
In-Reply-To: <4457CF53.7050000@stud.feec.vutbr.cz>
The following "soaks" on our side for a couple months now... Noticed [1][2] and
thought it'd make sense to add it to the mix.
Contents
======
* README (inlined below)
* netdevice.h patch with the preliminary/draft driver-level API (next message).
Introduction
========
Van Jacobson's Net Channels presentation at LCA2006 is available at [3] and
further discussed, for instance, at [4].
Within this context we defined the following goals for our implementation:
1) There are separate transport-neutral hardware supported channels for
transmit and receive traffic.
2) We are interested in a proof-of-concept, as well as an initial pass at a
concrete API.
The API introduces the concept of a unidirectional "flow" that can be "bound"
to a specific hardware supported channel. Within this framework TCP flow
is simply a special case where the transmit traffic flow is all the traffic
from a local TCP endpoint to a remote TCP endpoint and the receive
traffic flow is the exact opposite.
The API introduces - and is structured around - the following objects:
* hardware channel - hw_channelh
* kernel channel - kernel_channelh
* receive flow - netdev_rx_flow
Note:
More exactly, hw_channelh and kernel_channelh are opaque
(void*) handles to the corresponding stateful and
implementation-dependent objects. The rest of this text
talks about channels and denotes handles - for shortness sake
we'll now assume that the difference is clear enough.
Channels & Channel Handles
===================
Both the hardware and kernel channels (hw_channelh and kernel_channelh,
respectively) are strictly unidirectional. When a channel is opened it
is specified as a transmit or a receive channel. In order to create a
bi-directional send/receive channel there must be an additional API
which provides a higher level abstraction by using a pair
of uni-directional channels.
Hardware channel handle and kernel channel handle are opaque handles
designated to reference the corresponding stateful objects when used in an
appropriate context, i.e., driver and kernel, respectively.
Hardware channel handle (hw_channelh) is an opaque handles used to reference
the corresponding device driver-specific channel object. It is up to the
device driver developers to define the actual channel structures which work
best to their specific hardware. The API knows nothing about these except as
opaque pointers.
Similarly, kernel channel handle (kernel_channelh) is opaque, as far as
network drivers are concerned. There is a 1-to-1 correspondence between a
kernel channel and a hardware channel. This assists in separating domain
knowledge between the device driver and the kernel proper. It is assumed
that kernel developers will be able to make use of kernel_channelh by
casting it to the appropriate structure when, for instance, processing
frames received on a corresponding hardware channel (hw_channelh).
Receive Flow
=========
Receive flow (netdev_rx_flow) contains a criteria that allows to steer
a certain type of incoming packets (L2 frames, IP or UDP datagrams,
TCP segments, etc.) to a receive channel. For instance, a single channel
can be used to only receive traffic for a given MAC, or all traffic to TCP
port 80. Furthermore, several flows can be added (or more exactly, can be
"bound" via the corresponding bind_rx_hwchannel() API call) to the same
channel. This means, one can create a channel that accepts traffic for
destination MAC A and MAC B, or a channel used to transfer TCP packets with
destination port 80 and 8080, or a channel to for a number of TCP connections
defined by their respective 4-tuples.
For more discussion see Section "Neterion XFrame-II Specific Notes" below.
One can also assign a custom receive function to each separate receive channel.
If a callback function is specified, this function will be used to pass up
traffic instead of the netif_* API. This allows for a direct data path for
applications should they wish to use it. This callback function is entirely
optional and must be set per channel. If the function pointer is NULL the
standard netif_* API is used.
With respect to receive flow binding sequence, the last channel
that is bound to a specific flow is the one that "wins", i.e., gets the
traffic. In general, sharing of channels in a consistent fashion and
tracking of receive flows is currently considered outside of the scope
of this API.
System Scalability ("The Big Picture")
========================
The API has its place in the entire picture that, as per Van Jacobson,
includes "channelized" application, "channelized" socket, and "channelized"
driver. It is meant to provide a mechanism, which, if used correctly,
will ultimately allow to achieve system-level per-CPU scalability.
It is outside the scope of this API to provide an interface to automatically
place a transmit channel and the user-space application using it onto a given
CPU. But if the transmitting application is in fact bound to a CPU, and if the
kernel socket is "channel-aware", and if this particular channel is always
used with the same CPU - if all of the above is true, then the ultimate goal
of scalability can be reached.
Similarly, on the inbound, the API can be used to:
(1) channelize received traffic based on a number of available
receive flow classification mechanisms
(see netdev_hwchannel_rx_flow_e),
(2) process the per-channel MSI/MSI-X on a given CPU
specified at channel open time (see open_rx_hwchannel()).
It's outside of scope of this particular API what happens with the packets
received on a given channel after netif_rx*() callback hands the over to the
stack.
Neterion XFrame-II Specific Note
=====================
The API is (an attempt of) a generalized kernel <=> driver interface.
This section talks about Xframe-specific restrictions. We are assuming that
other multi-channel capable network adapters might have adapter-specific
restrictions; the idea however is not to propagate those restrictions on the
level of API, if possible.
The XFrame-II adapter supports multiple receive traffic flow types.
However, it is not possible to mix the receive flow types
(netdev_hwchannel_rx_flow_e) with the current Xframe hardware. In other
words, one cannot use a single hardware channel to receive, for instance,
all TCP traffic for destination port 80 and all L2 traffic for destination MAC A.
References
=======
[1] http://www.spinics.net/lists/netdev/msg03584.html
[2] http://www.spinics.net/lists/netdev/msg03583.html
[3] http://www.lemis.com/grog/Documentation/vj/lca06vj.pdf
[4] http://vger.kernel.org/~davem/cgi-bin/blog.cgi/2006/01/27
Thanks!
Neterion Team.
^ permalink raw reply
* [PATCH] ipg: removing more dead code
From: David Gómez @ 2006-05-02 22:30 UTC (permalink / raw)
To: Pekka Enberg; +Cc: Francois Romieu, David Vrabel, linux-kernel, netdev
In-Reply-To: <1146596687.13675.1.camel@localhost>
Hi Pekka,
On May 02 at 10:04:47, Pekka Enberg wrote:
> OK. David & David, would appreciate if either you could give the patch a
> spin with Francois' changes. Thanks.
I'll test it tomorrow ASAP. For now, here is another patch removing
more dead code. This code is never reached (NOTGRACE is not defined)
and the *fiber_detect functions are subsequently never used.
--- drivers/net/ipg.c.old 2006-05-03 00:16:47.000000000 +0200
+++ drivers/net/ipg.c 2006-05-03 00:28:02.000000000 +0200
@@ -461,43 +461,6 @@
return 0;
}
-#ifdef IPG_TMI_FIBER_DETECT
-static int ipg_sti_fiber_detect(struct net_device *dev)
-{
- /* Determine if NIC is fiber based by reading the PhyMedia
- * bit in the AsicCtrl register.
- */
-
- u32 asicctrl;
- void __iomem *ioaddr = ipg_ioaddr(dev);
-
- IPG_DEBUG_MSG("_sti_fiber_detect\n");
-
- asicctrl = ioread32(ioaddr + IPG_ASICCTRL);
-
- return asicctrl & IPG_AC_PHY_MEDIA;
-}
-
-static int ipg_tmi_fiber_detect(struct net_device *dev, int phyaddr)
-{
- /* Determine if NIC is fiber based by reading the ID register
- * of the PHY and the GMII address.
- */
-
- u16 phyid;
-
- IPG_DEBUG_MSG("_tmi_fiber_detect\n");
-
- phyid = read_phy_register(dev, phyaddr, GMII_PHY_ID_1);
-
- IPG_DEBUG_MSG("PHY ID = %x\n", phyid);
-
- /* We conclude the mode is fiber if the GMII address
- * is 0x1 and the PHY ID is 0x0000.
- */
- return (phyaddr == 0x1) && (phyid == 0x0000);
-}
-#endif
static int ipg_find_phyaddr(struct net_device *dev)
{
@@ -524,434 +487,6 @@
return -1;
}
-#ifdef NOTGRACE
-static int ipg_config_autoneg(struct net_device *dev)
-{
- /* Configure IPG based on result of IEEE 802.3 PHY
- * auto-negotiation.
- */
-
- int phyaddr = 0;
- u8 phyctrl;
- u32 asicctrl;
- void __iomem *ioaddr = ipg_ioaddr(dev);
- u16 status = 0;
- u16 advertisement;
- u16 linkpartner_ability;
- u16 gigadvertisement;
- u16 giglinkpartner_ability;
- u16 techabilities;
- int fiber;
- int gig;
- int fullduplex;
- int txflowcontrol;
- int rxflowcontrol;
- struct ipg_nic_private *sp = netdev_priv(dev);
-
- IPG_DEBUG_MSG("_config_autoneg\n");
-
- asicctrl = ioread32(ioaddr + IPG_ASICCTRL);
- phyctrl = ioread8(ioaddr + IPG_PHYCTRL);
-
- /* Set flags for use in resolving auto-negotation, assuming
- * non-1000Mbps, half duplex, no flow control.
- */
- fiber = 0;
- fullduplex = 0;
- txflowcontrol = 0;
- rxflowcontrol = 0;
- gig = 0;
-
- /* To accomodate a problem in 10Mbps operation,
- * set a global flag if PHY running in 10Mbps mode.
- */
- sp->tenmbpsmode = 0;
-
- printk("Link speed = ");
-
- /* Determine actual speed of operation. */
- switch (phyctrl & IPG_PC_LINK_SPEED) {
- case IPG_PC_LINK_SPEED_10MBPS:
- printk("10Mbps.\n");
- printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",
- dev->name);
- sp->tenmbpsmode = 1;
- break;
- case IPG_PC_LINK_SPEED_100MBPS:
- printk("100Mbps.\n");
- break;
- case IPG_PC_LINK_SPEED_1000MBPS:
- printk("1000Mbps.\n");
- gig = 1;
- break;
- default:
- printk("undefined!\n");
- }
-
-#ifndef IPG_TMI_FIBER_DETECT
- fiber = ipg_sti_fiber_detect(dev);
-
- /* Determine if auto-negotiation resolution is necessary.
- * First check for fiber based media 10/100 media.
- */
- if ((fiber == 1) && (asicctrl &
- (IPG_AC_PHY_SPEED10 | IPG_AC_PHY_SPEED100))) {
- printk(KERN_INFO
- "%s: Fiber based PHY, setting full duplex, no flow control.\n",
- dev->name);
- return -EILSEQ;
- iowrite32(IPG_MC_RSVD_MASK &
- ((ioread32(ioaddr + IPG_MACCTRL) |
- IPG_MC_DUPLEX_SELECT_FD) &
- ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
- ~IPG_MC_RX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
-
- return 0;
- }
-#endif
-
- /* Determine if PHY is auto-negotiation capable. */
- phyaddr = ipg_find_phyaddr(dev);
-
- if (phyaddr == -1) {
- printk(KERN_INFO
- "%s: Error on read to GMII/MII Status register.\n",
- dev->name);
- return -EILSEQ;
- }
-
- IPG_DEBUG_MSG("GMII/MII PHY address = %x\n", phyaddr);
-
- status = read_phy_register(dev, phyaddr, GMII_PHY_STATUS);
-
- printk("PHYStatus = %x \n", status);
- if ((status & GMII_PHY_STATUS_AUTONEG_ABILITY) == 0) {
- printk(KERN_INFO
- "%s: Error PHY unable to perform auto-negotiation.\n",
- dev->name);
- return -EILSEQ;
- }
-
- advertisement = read_phy_register(dev, phyaddr,
- GMII_PHY_AUTONEGADVERTISEMENT);
- linkpartner_ability = read_phy_register(dev, phyaddr,
- GMII_PHY_AUTONEGLINKPARTABILITY);
-
- printk("PHYadvertisement=%x LinkPartner=%x \n", advertisement,
- linkpartner_ability);
- if ((advertisement == 0xFFFF) || (linkpartner_ability == 0xFFFF)) {
- printk(KERN_INFO
- "%s: Error on read to GMII/MII registers 4 and/or 5.\n",
- dev->name);
- return -EILSEQ;
- }
-#ifdef IPG_TMI_FIBER_DETECT
- fiber = ipg_tmi_fiber_detect(dev, phyaddr);
-#endif
-
- /* Resolve full/half duplex if 1000BASE-X. */
- if ((gig == 1) && (fiber == 1)) {
- /* Compare the full duplex bits in the GMII registers
- * for the local device, and the link partner. If these
- * bits are logic 1 in both registers, configure the
- * IPG for full duplex operation.
- */
- if ((advertisement & GMII_PHY_ADV_FULL_DUPLEX) ==
- (linkpartner_ability & GMII_PHY_ADV_FULL_DUPLEX)) {
- fullduplex = 1;
-
- /* In 1000BASE-X using IPG's internal PCS
- * layer, so write to the GMII duplex bit.
- */
- write_phy_register(dev,
- phyaddr,
- GMII_PHY_CONTROL,
- read_phy_register
- (dev, phyaddr,
- GMII_PHY_CONTROL) |
- GMII_PHY_CONTROL_FULL_DUPLEX);
-
- } else {
- fullduplex = 0;
-
- /* In 1000BASE-X using IPG's internal PCS
- * layer, so write to the GMII duplex bit.
- */
- write_phy_register(dev,
- phyaddr,
- GMII_PHY_CONTROL,
- read_phy_register
- (dev, phyaddr,
- GMII_PHY_CONTROL) &
- ~GMII_PHY_CONTROL_FULL_DUPLEX);
- }
- }
-
- /* Resolve full/half duplex if 1000BASE-T. */
- if ((gig == 1) && (fiber == 0)) {
- /* Read the 1000BASE-T "Control" and "Status"
- * registers which represent the advertised and
- * link partner abilities exchanged via next page
- * transfers.
- */
- gigadvertisement = read_phy_register(dev,
- phyaddr,
- GMII_PHY_1000BASETCONTROL);
- giglinkpartner_ability = read_phy_register(dev,
- phyaddr,
- GMII_PHY_1000BASETSTATUS);
-
- /* Compare the full duplex bits in the 1000BASE-T GMII
- * registers for the local device, and the link partner.
- * If these bits are logic 1 in both registers, configure
- * the IPG for full duplex operation.
- */
- if ((gigadvertisement & GMII_PHY_1000BASETCONTROL_FULL_DUPLEX)
- && (giglinkpartner_ability &
- GMII_PHY_1000BASETSTATUS_FULL_DUPLEX)) {
- fullduplex = 1;
- } else {
- fullduplex = 0;
- }
- }
-
- /* Resolve full/half duplex for 10/100BASE-T. */
- if (gig == 0) {
- /* Autonegotiation Priority Resolution algorithm, as defined in
- * IEEE 802.3 Annex 28B.
- */
- if (((advertisement & MII_PHY_SELECTORFIELD) ==
- MII_PHY_SELECTOR_IEEE8023) &&
- ((linkpartner_ability & MII_PHY_SELECTORFIELD) ==
- MII_PHY_SELECTOR_IEEE8023)) {
- techabilities = (advertisement & linkpartner_ability &
- MII_PHY_TECHABILITYFIELD);
-
- fullduplex = 0;
-
- /* 10BASE-TX half duplex is lowest priority. */
- if (techabilities & MII_PHY_TECHABILITY_10BT) {
- fullduplex = 0;
- }
-
- if (techabilities & MII_PHY_TECHABILITY_10BTFD) {
- fullduplex = 1;
- }
-
- if (techabilities & MII_PHY_TECHABILITY_100BTX) {
- fullduplex = 0;
- }
-
- if (techabilities & MII_PHY_TECHABILITY_100BT4) {
- fullduplex = 0;
- }
-
- /* 100BASE-TX half duplex is highest priority. *///Sorbica full duplex ?
- if (techabilities & MII_PHY_TECHABILITY_100BTXFD) {
- fullduplex = 1;
- }
-
- if (fullduplex == 1) {
- /* If in full duplex mode, determine if PAUSE
- * functionality is supported by the local
- * device, and the link partner.
- */
- if (techabilities & MII_PHY_TECHABILITY_PAUSE) {
- txflowcontrol = 1;
- rxflowcontrol = 1;
- } else {
- txflowcontrol = 0;
- rxflowcontrol = 0;
- }
- }
- }
- }
-
- /* If in 1000Mbps, fiber, and full duplex mode, resolve
- * 1000BASE-X PAUSE capabilities. */
- if ((fullduplex == 1) && (fiber == 1) && (gig == 1)) {
- /* In full duplex mode, resolve PAUSE
- * functionality.
- */
- switch (((advertisement & GMII_PHY_ADV_PAUSE) >> 5) |
- ((linkpartner_ability & GMII_PHY_ADV_PAUSE) >> 7)) {
- case 0x7:
- txflowcontrol = 1;
- rxflowcontrol = 0;
- break;
-
- case 0xA:
- case 0xB:
- case 0xE:
- case 0xF:
- txflowcontrol = 1;
- rxflowcontrol = 1;
- break;
-
- case 0xD:
- txflowcontrol = 0;
- rxflowcontrol = 1;
- break;
-
- default:
- txflowcontrol = 0;
- rxflowcontrol = 0;
- }
- }
-
- /* If in 1000Mbps, non-fiber, full duplex mode, resolve
- * 1000BASE-T PAUSE capabilities. */
- if ((fullduplex == 1) && (fiber == 0) && (gig == 1)) {
- /* Make sure the PHY is advertising we are PAUSE
- * capable.
- */
- if (!(advertisement & (MII_PHY_TECHABILITY_PAUSE |
- MII_PHY_TECHABILITY_ASM_DIR))) {
- /* PAUSE is not being advertised. Advertise
- * PAUSE and restart auto-negotiation.
- */
- write_phy_register(dev,
- phyaddr,
- MII_PHY_AUTONEGADVERTISEMENT,
- (advertisement |
- MII_PHY_TECHABILITY_PAUSE |
- MII_PHY_TECHABILITY_ASM_DIR));
- write_phy_register(dev,
- phyaddr,
- MII_PHY_CONTROL,
- MII_PHY_CONTROL_RESTARTAN);
-
- return -EAGAIN;
- }
-
- /* In full duplex mode, resolve PAUSE
- * functionality.
- */
- switch (((advertisement &
- MII_PHY_TECHABILITY_PAUSE_FIELDS) >> 0x8) |
- ((linkpartner_ability &
- MII_PHY_TECHABILITY_PAUSE_FIELDS) >> 0xA)) {
- case 0x7:
- txflowcontrol = 1;
- rxflowcontrol = 0;
- break;
-
- case 0xA:
- case 0xB:
- case 0xE:
- case 0xF:
- txflowcontrol = 1;
- rxflowcontrol = 1;
- break;
-
- case 0xD:
- txflowcontrol = 0;
- rxflowcontrol = 1;
- break;
-
- default:
- txflowcontrol = 0;
- rxflowcontrol = 0;
- }
- }
-
- /* If in 10/100Mbps, non-fiber, full duplex mode, assure
- * 10/100BASE-T PAUSE capabilities are advertised. */
- if ((fullduplex == 1) && (fiber == 0) && (gig == 0)) {
- /* Make sure the PHY is advertising we are PAUSE
- * capable.
- */
- if (!(advertisement & (MII_PHY_TECHABILITY_PAUSE))) {
- /* PAUSE is not being advertised. Advertise
- * PAUSE and restart auto-negotiation.
- */
- write_phy_register(dev,
- phyaddr,
- MII_PHY_AUTONEGADVERTISEMENT,
- (advertisement |
- MII_PHY_TECHABILITY_PAUSE));
- write_phy_register(dev,
- phyaddr,
- MII_PHY_CONTROL,
- MII_PHY_CONTROL_RESTARTAN);
-
- return -EAGAIN;
- }
-
- }
-
- if (fiber == 1) {
- printk(KERN_INFO "%s: Fiber based PHY, ", dev->name);
- } else {
- printk(KERN_INFO "%s: Copper based PHY, ", dev->name);
- }
-
- /* Configure full duplex, and flow control. */
- if (fullduplex == 1) {
- /* Configure IPG for full duplex operation. */
- printk("setting full duplex, ");
-
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) |
- IPG_MC_DUPLEX_SELECT_FD), ioaddr + IPG_MACCTRL);
-
- if (txflowcontrol == 1) {
- printk("TX flow control");
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) |
- IPG_MC_TX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
- } else {
- printk("no TX flow control");
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) &
- ~IPG_MC_TX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
- }
-
- if (rxflowcontrol == 1) {
- printk(", RX flow control.");
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) |
- IPG_MC_RX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
- } else {
- printk(", no RX flow control.");
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) &
- ~IPG_MC_RX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
- }
-
- printk("\n");
- } else {
- /* Configure IPG for half duplex operation. */
- printk
- ("setting half duplex, no TX flow control, no RX flow control.\n");
-
- iowrite32(IPG_MC_RSVD_MASK &
- (ioread32(ioaddr + IPG_MACCTRL) &
- ~IPG_MC_DUPLEX_SELECT_FD &
- ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
- ~IPG_MC_RX_FLOW_CONTROL_ENABLE),
- ioaddr + IPG_MACCTRL);
- }
-
- IPG_DEBUG_MSG("G/MII reg 4 (advertisement) = %4.4x\n", advertisement);
- IPG_DEBUG_MSG("G/MII reg 5 (link partner) = %4.4x\n",
- linkpartner_ability);
- IPG_DEBUG_MSG("G/MII reg 9 (1000BASE-T control) = %4.4x\n",
- advertisement);
- IPG_DEBUG_MSG("G/MII reg 10 (1000BASE-T status) = %4.4x\n",
- linkpartner_ability);
-
- IPG_DEBUG_MSG("Auto-neg complete, MACCTRL = %8.8x\n",
- ioread32(ioaddr + IPG_MACCTRL));
-
- return 0;
-}
-#else
static int ipg_config_autoneg(struct net_device *dev)
{
/* Configure IPG based on result of IEEE 802.3 PHY
@@ -1072,7 +607,6 @@
return 0;
}
-#endif
static int ipg_io_config(struct net_device *dev)
{
^ permalink raw reply
* Re: [PATCH 2/2] ipg: redundancy with mii.h
From: Francois Romieu @ 2006-05-02 21:55 UTC (permalink / raw)
To: Pekka J Enberg; +Cc: David Vrabel, linux-kernel, netdev, david
In-Reply-To: <20060502214520.GC26357@electric-eye.fr.zoreil.com>
Btw the whole serie is available in branch 'netdev-ipg' at:
git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6.git
The interim steps may be useful if testing reveals something wrong
(especially if it happens in a few weeks/months).
$ git rev-list --pretty ebf34c9b6fcd22338ef764b039b3ac55ed0e297b..HEAD
commit 8a98963033425729158d48066a3380f811c711b3
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Tue May 2 23:25:44 2006 +0200
ipg: redundancy with mii.h
Replace a bunch of #define with their counterpart from mii.h
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
commit 291360d4000e0b93baf0fb97aa15af48677e46af
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Tue May 2 22:15:34 2006 +0200
ipg: sanitize the pci device table
- vendor id belong to include/linux/pci_id.h ;
- the pci table does not include all the devices in nics_supported ;
- qualify the pci table as __devinitdata ;
- kill 50 LOC.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
commit 8b534f66d6be247b9f0d341b0ae7acbf46f128fb
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Tue May 2 01:07:48 2006 +0200
ipg: plug leaks in the error path of ipg_nic_open
Added ipg_{rx/tx}_clear() to factor out some code.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
commit 87c8b13dceccc42439e7262f1b60c9cbb14d5440
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Tue May 2 00:15:54 2006 +0200
ipg: leaks in ipg_probe
The error paths are badly broken.
Bonus:
- remove duplicate initialization of sp;
- remove useless NULL initialization of dev;
- USE_IO_OPS is not used (and the driver does not seem to care about
posted writes, rejoice).
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
commit befd7e543fcdfb2d2c75de1748ae751fefdff58a
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Mon May 1 23:52:37 2006 +0200
ipg: removal of unreachable code
map/unmap is done in ipg_{probe/remove}
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
commit 17a9ce93ba6b6744489aa9168d757e9457158952
Author: Romieu Francois <romieu@fr.zoreil.com>
Date: Mon May 1 22:40:29 2006 +0200
ipg: speed-up access to the PHY registers
Reduce delays when reading/writing the PHY registers so we clock the
MII management interface at 2.5 MHz (the maximum according to the
datasheet) instead of 500 Hz.
Signed-off-by: David Vrabel <dvrabel@cantab.net>
commit e18c33d6fa62b735426b8fe5a0f1aa61c0b5d7f7
Author: David Vrabel <dvrabel@cantab.net>
Date: Mon May 1 21:34:19 2006 +0200
ipg: root_dev removal and PHY initialization
- Remove ether_crc_le() -- use crc32_le() instead.
- No more nonsense with root_dev -- ipg_remove() now works.
- Move PHY and MAC address initialization into the ipg_probe().
It was previously filling in the MAC address on open which breaks
some user space.
- Folded ipg_nic_init into ipg_probe since it was broke otherwise.
Signed-off-by: David Vrabel <dvrabel@cantab.net>
commit e99fcd4253f231b2c7a96e3be5067341de45ac2e
Author: David Vrabel <dvrabel@cantab.net>
Date: Mon May 1 13:20:49 2006 +0200
ipg: remove changelogs
Signed-off-by: David Vrabel <dvrabel@cantab.net>
commit 8fd59026a272d3132f096965985e907d655ee087
Author: Pekka Enberg <penberg@cs.helsinki.fi>
Date: Mon May 1 12:53:43 2006 +0200
ipg: initial inclusion of IC Plus IP1000 driver
This is a cleaned up fork of the IP1000A device driver:
<http://www.icplus.com.tw/driver-pp-IP1000A.html>
Open issues include but are not limited to:
- ipg_probe() looks really fishy and doesn't handle all errors
(e.g. ioremap failing).
- ipg_nic_do_ioctl() is playing games with user-space pointer.
We should use ethtool ioctl instead as suggested by Arjan.
- For multiple devices, the driver uses a global root_dev and
ipg_remove() play some tricks which look fishy.
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
^ permalink raw reply
* [PATCH 1/2] ipg: sanitize the pci device table
From: Francois Romieu @ 2006-05-02 21:44 UTC (permalink / raw)
To: Pekka J Enberg; +Cc: David Vrabel, linux-kernel, netdev, david
In-Reply-To: <Pine.LNX.4.58.0605020945010.4066@sbz-30.cs.Helsinki.FI>
- vendor id belong to include/linux/pci_id.h ;
- the pci table does not include all the devices in nics_supported ;
- qualify the pci table as __devinitdata ;
- kill 50 LOC.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
---
drivers/net/ipg.c | 46 ++++++--------------------------
drivers/net/ipg.h | 67 +++++++++++------------------------------------
include/linux/pci_ids.h | 2 +
3 files changed, 27 insertions(+), 88 deletions(-)
aa5b322a6f91ca12a580dfa7022fca1a088b4abd
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 393b617..ea7c1f8 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -32,40 +32,14 @@ MODULE_DESCRIPTION("IC Plus IP1000 Gigab
DrvVer);
MODULE_LICENSE("GPL");
-static struct pci_device_id ipg_pci_tbl[] = {
- {PCI_VENDOR_ID_ICPLUS,
- PCI_DEVICE_ID_IP1000,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0x020000,
- 0xFFFFFF,
- 0},
-
- {PCI_VENDOR_ID_SUNDANCE,
- PCI_DEVICE_ID_SUNDANCE_ST2021,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0x020000,
- 0xFFFFFF,
- 1},
-
- {PCI_VENDOR_ID_SUNDANCE,
- PCI_DEVICE_ID_TAMARACK_TC9020_9021,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0x020000,
- 0xFFFFFF,
- 2},
-
- {PCI_VENDOR_ID_DLINK,
- PCI_DEVICE_ID_DLINK_1002,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0x020000,
- 0xFFFFFF,
- 3},
-
- {0,}
+static struct pci_device_id ipg_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SUNDANCE, 0x1023), 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SUNDANCE, 0x2021), 0, 0, 1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SUNDANCE, 0x1021), 0, 0, 2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x9021), 0, 0, 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4000), 0, 0, 4 },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4020), 0, 0, 5 },
+ { 0, }
};
MODULE_DEVICE_TABLE(pci, ipg_pci_tbl);
@@ -2961,9 +2935,7 @@ static int __devinit ipg_probe(struct pc
if (rc < 0)
goto out;
- printk(KERN_INFO "%s found.\n", nics_supported[i].NICname);
- printk(KERN_INFO "Bus %x Slot %x\n",
- pdev->bus->number, PCI_SLOT(pdev->devfn));
+ printk(KERN_INFO "%s: %s\n", pci_name(pdev), nics_supported[i].name);
pci_set_master(pdev);
diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h
index ae3424a..03bc6f1 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ipg.h
@@ -589,34 +589,6 @@ #define IPG_RI_RXDMAWAIT_TIME
* Tune
*/
-#ifndef PCI_VENDOR_ID_ICPLUS
-# define PCI_VENDOR_ID_ICPLUS 0x13F0
-#endif
-#ifndef PCI_DEVICE_ID_IP1000
-# define PCI_DEVICE_ID_IP1000 0x1023
-#endif
-#ifndef PCI_VENDOR_ID_SUNDANCE
-# define PCI_VENDOR_ID_SUNDANCE 0x13F0
-#endif
-#ifndef PCI_DEVICE_ID_SUNDANCE_IPG
-# define PCI_DEVICE_ID_SUNDANCE_ST2021 0x2021
-#endif
-#ifndef PCI_DEVICE_ID_TAMARACK_TC9020_9021_ALT
-# define PCI_DEVICE_ID_TAMARACK_TC9020_9021_ALT 0x9021
-#endif
-#ifndef PCI_DEVICE_ID_TAMARACK_TC9020_9021
-# define PCI_DEVICE_ID_TAMARACK_TC9020_9021 0x1021
-#endif
-#ifndef PCI_VENDOR_ID_DLINK
-# define PCI_VENDOR_ID_DLINK 0x1186
-#endif
-#ifndef PCI_DEVICE_ID_DLINK_1002
-# define PCI_DEVICE_ID_DLINK_1002 0x4000
-#endif
-#ifndef PCI_DEVICE_ID_DLINK_IP1000A
-# define PCI_DEVICE_ID_DLINK_IP1000A 0x4020
-#endif
-
/* Miscellaneous Constants. */
#define TRUE 1
#define FALSE 0
@@ -990,32 +962,25 @@ #endif
};
struct nic_id {
- char *NICname;
- int vendorid;
- int deviceid;
+ char *name;
+ u32 vendor;
+ u32 device;
};
struct nic_id nics_supported[] = {
- {"IC PLUS IP1000 1000/100/10 based NIC",
- PCI_VENDOR_ID_ICPLUS,
- PCI_DEVICE_ID_IP1000},
- {"Sundance Technology ST2021 based NIC",
- PCI_VENDOR_ID_SUNDANCE,
- PCI_DEVICE_ID_SUNDANCE_ST2021},
- {"Tamarack Microelectronics TC9020/9021 based NIC",
- PCI_VENDOR_ID_SUNDANCE,
- PCI_DEVICE_ID_TAMARACK_TC9020_9021},
- {"Tamarack Microelectronics TC9020/9021 based NIC",
- PCI_VENDOR_ID_SUNDANCE,
- PCI_DEVICE_ID_TAMARACK_TC9020_9021_ALT},
- {"D-Link NIC",
- PCI_VENDOR_ID_DLINK,
- PCI_DEVICE_ID_DLINK_1002},
- {"D-Link NIC IP1000A",
- PCI_VENDOR_ID_DLINK,
- PCI_DEVICE_ID_DLINK_IP1000A},
-
- {"N/A", 0xFFFF, 0}
+ { "IC PLUS IP1000 1000/100/10 based NIC",
+ PCI_VENDOR_ID_SUNDANCE, 0x1023 },
+ { "Sundance Technology ST2021 based NIC",
+ PCI_VENDOR_ID_SUNDANCE, 0x2021 },
+ { "Tamarack Microelectronics TC9020/9021 based NIC",
+ PCI_VENDOR_ID_SUNDANCE, 0x1021 },
+ { "Tamarack Microelectronics TC9020/9021 based NIC",
+ PCI_VENDOR_ID_SUNDANCE, 0x9021 },
+ { "D-Link NIC",
+ PCI_VENDOR_ID_DLINK, 0x4000 },
+ { "D-Link NIC IP1000A",
+ PCI_VENDOR_ID_DLINK, 0x4020 },
+ { NULL, 0xffff, 0 }
};
//variable record -- index by leading revision/length
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d6fe048..b772f2b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1788,6 +1788,8 @@ #define PCI_DEVICE_ID_IOMEGA_BUZ 0x4231
#define PCI_VENDOR_ID_ABOCOM 0x13D1
#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1
+#define PCI_VENDOR_ID_SUNDANCE 0x13f0
+
#define PCI_VENDOR_ID_CMEDIA 0x13f6
#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
--
1.3.1
^ permalink raw reply related
* [PATCH 2/2] ipg: redundancy with mii.h
From: Francois Romieu @ 2006-05-02 21:45 UTC (permalink / raw)
To: Pekka J Enberg; +Cc: David Vrabel, linux-kernel, netdev, david
In-Reply-To: <Pine.LNX.4.58.0605020945010.4066@sbz-30.cs.Helsinki.FI>
Replace a bunch of #define with their counterpart from mii.h
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
---
drivers/net/ipg.c | 82 ++++++++++++++++++++++-------------------------------
drivers/net/ipg.h | 29 -------------------
2 files changed, 34 insertions(+), 77 deletions(-)
ea93e36c70b16ab91340e320ed96df1df14ea608
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index ea7c1f8..5be2af1 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -15,6 +15,7 @@
* craig_rich@sundanceti.com
*/
#include <linux/crc32.h>
+#include <linux/mii.h>
#define IPG_RX_RING_BYTES (sizeof(struct RFD) * IPG_RFDLIST_LENGTH)
#define IPG_TX_RING_BYTES (sizeof(struct TFD) * IPG_TFDLIST_LENGTH)
@@ -465,7 +466,7 @@ static int ipg_tmi_fiber_detect(struct n
IPG_DEBUG_MSG("_tmi_fiber_detect\n");
- phyid = read_phy_register(dev, phyaddr, GMII_PHY_ID_1);
+ phyid = read_phy_register(dev, phyaddr, MII_PHYSID1);
IPG_DEBUG_MSG("PHY ID = %x\n", phyid);
@@ -492,7 +493,7 @@ static int ipg_find_phyaddr(struct net_d
GMII_PHY_ID1
*/
- status = read_phy_register(dev, phyaddr, GMII_PHY_STATUS);
+ status = read_phy_register(dev, phyaddr, MII_BMSR);
if ((status != 0xFFFF) && (status != 0))
return phyaddr;
@@ -600,20 +601,18 @@ #endif
IPG_DEBUG_MSG("GMII/MII PHY address = %x\n", phyaddr);
- status = read_phy_register(dev, phyaddr, GMII_PHY_STATUS);
+ status = read_phy_register(dev, phyaddr, MII_BMSR);
printk("PHYStatus = %x \n", status);
- if ((status & GMII_PHY_STATUS_AUTONEG_ABILITY) == 0) {
+ if ((status & BMSR_ANEGCAPABLE) == 0) {
printk(KERN_INFO
"%s: Error PHY unable to perform auto-negotiation.\n",
dev->name);
return -EILSEQ;
}
- advertisement = read_phy_register(dev, phyaddr,
- GMII_PHY_AUTONEGADVERTISEMENT);
- linkpartner_ability = read_phy_register(dev, phyaddr,
- GMII_PHY_AUTONEGLINKPARTABILITY);
+ advertisement = read_phy_register(dev, phyaddr, MII_ADVERTISE);
+ linkpartner_ability = read_phy_register(dev, phyaddr, MII_LPA);
printk("PHYadvertisement=%x LinkPartner=%x \n", advertisement,
linkpartner_ability);
@@ -634,20 +633,16 @@ #endif
* bits are logic 1 in both registers, configure the
* IPG for full duplex operation.
*/
- if ((advertisement & GMII_PHY_ADV_FULL_DUPLEX) ==
- (linkpartner_ability & GMII_PHY_ADV_FULL_DUPLEX)) {
+ if ((advertisement & ADVERTISE_1000XFULL) ==
+ (linkpartner_ability & ADVERTISE_1000XFULL)) {
fullduplex = 1;
/* In 1000BASE-X using IPG's internal PCS
* layer, so write to the GMII duplex bit.
*/
- write_phy_register(dev,
- phyaddr,
- GMII_PHY_CONTROL,
- read_phy_register
- (dev, phyaddr,
- GMII_PHY_CONTROL) |
- GMII_PHY_CONTROL_FULL_DUPLEX);
+ write_phy_register(dev, phyaddr, MII_BMCR,
+ read_phy_register(dev, phyaddr, MII_BMCR) |
+ ADVERTISE_1000HALF); // Typo ?
} else {
fullduplex = 0;
@@ -655,13 +650,9 @@ #endif
/* In 1000BASE-X using IPG's internal PCS
* layer, so write to the GMII duplex bit.
*/
- write_phy_register(dev,
- phyaddr,
- GMII_PHY_CONTROL,
- read_phy_register
- (dev, phyaddr,
- GMII_PHY_CONTROL) &
- ~GMII_PHY_CONTROL_FULL_DUPLEX);
+ write_phy_register(dev, phyaddr, MII_BMCR,
+ read_phy_register(dev, phyaddr, MII_BMCR) &
+ ~ADVERTISE_1000HALF); // Typo ?
}
}
@@ -672,21 +663,18 @@ #endif
* link partner abilities exchanged via next page
* transfers.
*/
- gigadvertisement = read_phy_register(dev,
- phyaddr,
- GMII_PHY_1000BASETCONTROL);
- giglinkpartner_ability = read_phy_register(dev,
- phyaddr,
- GMII_PHY_1000BASETSTATUS);
+ gigadvertisement =
+ read_phy_register(dev, phyaddr, MII_CTRL1000);
+ giglinkpartner_ability =
+ read_phy_register(dev, phyaddr, MII_STAT1000);
/* Compare the full duplex bits in the 1000BASE-T GMII
* registers for the local device, and the link partner.
* If these bits are logic 1 in both registers, configure
* the IPG for full duplex operation.
*/
- if ((gigadvertisement & GMII_PHY_1000BASETCONTROL_FULL_DUPLEX)
- && (giglinkpartner_ability &
- GMII_PHY_1000BASETSTATUS_FULL_DUPLEX)) {
+ if ((gigadvertisement & ADVERTISE_1000FULL) &&
+ (giglinkpartner_ability & ADVERTISE_1000FULL)) {
fullduplex = 1;
} else {
fullduplex = 0;
@@ -751,8 +739,12 @@ #endif
/* In full duplex mode, resolve PAUSE
* functionality.
*/
- switch (((advertisement & GMII_PHY_ADV_PAUSE) >> 5) |
- ((linkpartner_ability & GMII_PHY_ADV_PAUSE) >> 7)) {
+ u8 flow_ctl;
+#define LPA_PAUSE_ANY (LPA_1000XPAUSE_ASYM | LPA_1000XPAUSE)
+
+ flow_ctl = (advertisement & LPA_PAUSE_ANY) >> 5;
+ flow_ctl |= (linkpartner_ability & LPA_PAUSE_ANY) >> 7;
+ switch (flow_ctl) {
case 0x7:
txflowcontrol = 1;
rxflowcontrol = 0;
@@ -2682,26 +2674,20 @@ static int ipg_hw_init(struct net_device
if (phyaddr != -1) {
u16 mii_phyctrl, mii_1000cr;
- mii_1000cr = read_phy_register(dev,
- phyaddr,
- GMII_PHY_1000BASETCONTROL);
- write_phy_register(dev, phyaddr,
- GMII_PHY_1000BASETCONTROL,
- mii_1000cr |
- GMII_PHY_1000BASETCONTROL_FULL_DUPLEX |
- GMII_PHY_1000BASETCONTROL_HALF_DUPLEX |
+ mii_1000cr =
+ read_phy_register(dev, phyaddr, MII_CTRL1000);
+ write_phy_register(dev, phyaddr, MII_CTRL1000,
+ mii_1000cr | ADVERTISE_1000FULL | ADVERTISE_1000HALF |
GMII_PHY_1000BASETCONTROL_PreferMaster);
- mii_phyctrl = read_phy_register(dev, phyaddr, GMII_PHY_CONTROL);
+ mii_phyctrl = read_phy_register(dev, phyaddr, MII_BMCR);
/* Set default phyparam */
pci_read_config_byte(sp->pdev, PCI_REVISION_ID, &revisionid);
ipg_set_phy_default_param(revisionid, dev, phyaddr);
/* reset Phy */
- write_phy_register(dev,
- phyaddr, GMII_PHY_CONTROL,
- (mii_phyctrl | GMII_PHY_CONTROL_RESET |
- MII_PHY_CONTROL_RESTARTAN));
+ write_phy_register(dev, phyaddr, MII_BMCR,
+ (mii_phyctrl | BMCR_RESET | BMCR_ANRESTART));
}
diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h
index 03bc6f1..cb51b2b 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ipg.h
@@ -86,38 +86,9 @@ #define MII_PHY_TECHABILITY_ASM_
#define MII_PHY_TECHABILITY_RSVD2 0x1000
#define MII_PHY_STATUS_AUTONEG_ABILITY 0x0008
-/* NIC Physical Layer Device GMII register addresses. */
-#define GMII_PHY_CONTROL 0x00
-#define GMII_PHY_STATUS 0x01
-#define GMII_PHY_ID_1 0x02
-#define GMII_PHY_AUTONEGADVERTISEMENT 0x04
-#define GMII_PHY_AUTONEGLINKPARTABILITY 0x05
-#define GMII_PHY_AUTONEGEXPANSION 0x06
-#define GMII_PHY_AUTONEGNEXTPAGE 0x07
-#define GMII_PHY_AUTONEGLINKPARTNEXTPAGE 0x08
-#define GMII_PHY_EXTENDEDSTATUS 0x0F
-
-#define GMII_PHY_1000BASETCONTROL 0x09
-#define GMII_PHY_1000BASETSTATUS 0x0A
-
/* GMII_PHY_1000 need to set to prefer master */
#define GMII_PHY_1000BASETCONTROL_PreferMaster 0x0400
-#define GMII_PHY_1000BASETCONTROL_FULL_DUPLEX 0x0200
-#define GMII_PHY_1000BASETCONTROL_HALF_DUPLEX 0x0100
-#define GMII_PHY_1000BASETSTATUS_FULL_DUPLEX 0x0800
-#define GMII_PHY_1000BASETSTATUS_HALF_DUPLEX 0x0400
-
-/* NIC Physical Layer Device GMII register Fields. */
-#define GMII_PHY_CONTROL_RESET 0x8000
-#define GMII_PHY_CONTROL_FULL_DUPLEX 0x0100
-#define GMII_PHY_STATUS_AUTONEG_ABILITY 0x0008
-#define GMII_PHY_ADV_FULL_DUPLEX 0x0020
-#define GMII_PHY_ADV_HALF_DUPLEX 0x0040
-#define GMII_PHY_ADV_PAUSE 0x0180
-#define GMII_PHY_ADV_PAUSE_PS1 0x0080
-#define GMII_PHY_ADV_ASM_DIR_PS2 0x0100
-
/* NIC Physical Layer Device GMII constants. */
#define GMII_PREAMBLE 0xFFFFFFFF
#define GMII_ST 0x1
--
1.3.1
^ permalink raw reply related
* Re: [PATCH] wireless/airo: minimal WPA awareness
From: Michal Schmidt @ 2006-05-02 21:29 UTC (permalink / raw)
To: Dan Williams
Cc: netdev, John W. Linville, matthieu castet, Javier Achirica,
Jean Tourrilhes
In-Reply-To: <1145118379.2324.18.camel@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 937 bytes --]
Dan Williams wrote:
> airo cards with firmware versions of 5.30.17 and higher support WPA.
> This patch recognizes WPA-capable firmware versions and adds support for
> retrieving the WPA and RSN information elements from the card's scan
> results. The JOB and FLAG fields are now independent, since there was
> no space left in the FLAG field for FLAG_WPA_CAPABLE.
>
> Signed-off-by: matthieu castet <castet.matthieu@free.fr>
> Signed-off-by: Dan Williams <dcbw@redhat.com>
Running Linux 2.6.17-rc3-mm1 which has this patch included I get this
interesting message:
airo(eth0): WPA unsupported (only firmware versions 5.30.17 and greater
support WPA. Detected 5.30.17)
airo_test_wpa_capable assumes that the softSubVer part of the firmware
version number is coded in BCD. Apparently, that's not true.
I have firmware version 5.30.17 and cap_rid.softSubVer is 0x11==17.
Signed-off-by: Michal Schmidt <xschmi00@stud.feec.vutbr.cz>
[-- Attachment #2: airo-fix-firmware-version-compare.diff --]
[-- Type: text/plain, Size: 641 bytes --]
diff -Nurp -X linux-mich/Documentation/dontdiff linux-mm/drivers/net/wireless/airo.c linux-mich/drivers/net/wireless/airo.c
--- linux-mm/drivers/net/wireless/airo.c 2006-05-02 20:20:37.000000000 +0200
+++ linux-mich/drivers/net/wireless/airo.c 2006-05-02 23:16:59.000000000 +0200
@@ -2768,7 +2768,7 @@ static int airo_test_wpa_capable(struct
/* Only firmware versions 5.30.17 or better can do WPA */
if ((cap_rid.softVer > 0x530)
- || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 0x17))) {
+ || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
airo_print_info(name, "WPA is supported.");
return 1;
}
^ permalink raw reply
* [PATCH wireless-dev] d80211: Add support for user space client MLME
From: Jouni Malinen @ 2006-05-02 21:18 UTC (permalink / raw)
To: John W. Linville; +Cc: netdev, jkmaline
Add a configuration option for disabling client MLME in kernel
code. This is used to enable user space MLME for client mode (e.g.,
with wpa_supplicant). The kernel MLME implementation is unmodified,
but it could be removed or at least made optional in build
configuration in the future.
Signed-off-by: Jouni Malinen <jkm@devicescape.com>
Index: wireless-dev/net/d80211/hostapd_ioctl.h
===================================================================
--- wireless-dev.orig/net/d80211/hostapd_ioctl.h
+++ wireless-dev/net/d80211/hostapd_ioctl.h
@@ -91,6 +91,7 @@ enum {
PRISM2_PARAM_KEY_MGMT = 1040,
PRISM2_PARAM_RADAR_DETECT = 1043,
PRISM2_PARAM_SPECTRUM_MGMT = 1044,
+ PRISM2_PARAM_USER_SPACE_MLME = 1045,
/* NOTE: Please try to coordinate with other active development
* branches before allocating new param numbers so that each new param
* will be unique within all branches and the allocated number will not
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
--- wireless-dev.orig/net/d80211/ieee80211.c
+++ wireless-dev/net/d80211/ieee80211.c
@@ -3116,8 +3116,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
{
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
- if (sdata->type == IEEE80211_IF_TYPE_STA ||
- sdata->type == IEEE80211_IF_TYPE_IBSS) {
+ if ((sdata->type == IEEE80211_IF_TYPE_STA ||
+ sdata->type == IEEE80211_IF_TYPE_IBSS) &&
+ !rx->local->user_space_mlme) {
ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
} else {
/* Management frames are sent to hostapd for processing */
Index: wireless-dev/net/d80211/ieee80211_ioctl.c
===================================================================
--- wireless-dev.orig/net/d80211/ieee80211_ioctl.c
+++ wireless-dev/net/d80211/ieee80211_ioctl.c
@@ -1048,10 +1048,14 @@ static int ieee80211_ioctl_scan_req(stru
struct prism2_hostapd_param *param,
int param_len)
{
+ struct ieee80211_local *local = dev->priv;
u8 *pos = param->u.scan_req.ssid;
int left = param_len - ((u8 *) pos - (u8 *) param);
int len = param->u.scan_req.ssid_len;
+ if (local->user_space_mlme)
+ return -EOPNOTSUPP;
+
if (left < len || len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
@@ -1076,8 +1080,12 @@ static int ieee80211_ioctl_sta_get_state
static int ieee80211_ioctl_mlme(struct net_device *dev,
struct prism2_hostapd_param *param)
{
+ struct ieee80211_local *local = dev->priv;
struct ieee80211_sub_if_data *sdata;
+ if (local->user_space_mlme)
+ return -EOPNOTSUPP;
+
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
@@ -1136,6 +1144,10 @@ static int ieee80211_ioctl_set_sta_vlan(
static int ieee80211_set_gen_ie(struct net_device *dev, u8 *ie, size_t len)
{
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_local *local = dev->priv;
+
+ if (local->user_space_mlme)
+ return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_STA ||
@@ -1745,6 +1757,7 @@ static int ieee80211_ioctl_siwessid(stru
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
+ struct ieee80211_local *local = dev->priv;
struct ieee80211_sub_if_data *sdata;
size_t len = data->length;
@@ -1754,8 +1767,16 @@ static int ieee80211_ioctl_siwessid(stru
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_STA ||
- sdata->type == IEEE80211_IF_TYPE_IBSS)
+ sdata->type == IEEE80211_IF_TYPE_IBSS) {
+ if (local->user_space_mlme) {
+ if (len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
+ memcpy(sdata->u.sta.ssid, ssid, len);
+ sdata->u.sta.ssid_len = len;
+ return 0;
+ }
return ieee80211_sta_set_ssid(dev, ssid, len);
+ }
if (sdata->type == IEEE80211_IF_TYPE_AP) {
memcpy(sdata->u.ap.ssid, ssid, len);
@@ -1804,11 +1825,17 @@ static int ieee80211_ioctl_siwap(struct
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra)
{
+ struct ieee80211_local *local = dev->priv;
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
+ if (local->user_space_mlme) {
+ memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+ ETH_ALEN);
+ return 0;
+ }
return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
@@ -2469,6 +2496,9 @@ static int ieee80211_ioctl_prism2_param(
case PRISM2_PARAM_SPECTRUM_MGMT:
local->conf.spect_mgmt = value;
break;
+ case PRISM2_PARAM_USER_SPACE_MLME:
+ local->user_space_mlme = value;
+ break;
default:
ret = -EOPNOTSUPP;
break;
@@ -2651,6 +2681,9 @@ static int ieee80211_ioctl_get_prism2_pa
else
*param = !!sdata->u.sta.wmm_enabled;
break;
+ case PRISM2_PARAM_USER_SPACE_MLME:
+ *param = local->user_space_mlme;
+ break;
default:
ret = -EOPNOTSUPP;
Index: wireless-dev/net/d80211/ieee80211_i.h
===================================================================
--- wireless-dev.orig/net/d80211/ieee80211_i.h
+++ wireless-dev/net/d80211/ieee80211_i.h
@@ -502,6 +502,8 @@ struct ieee80211_local {
unsigned int hw_modes; /* bitfield of allowed hardware modes;
* (1 << MODE_*) */
+
+ int user_space_mlme;
};
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* Re: Fw: Bug: PPP dropouts in >=2.6.16
From: Nuri Jawad @ 2006-05-02 20:55 UTC (permalink / raw)
To: netdev; +Cc: akpm
In-Reply-To: <Pine.LNX.4.64.0604301520030.5512@pc>
Good evening,
Bugzilla entry on this is now here:
http://bugzilla.kernel.org/show_bug.cgi?id=6484
Note the interesting fact that kernel mode PPPoE is not affected. Thus it
could also be a bug in Roaring Penguin's PPPoE program. The problem is
that all other user space implementations seem to be quite outdated
(made for 2.2 kernels).
I still did observe around 500 packets being lost after a night of pinging
this machine, compared to around 30 with 2.6.15.7 user mode pppoe and
700-1100 with >=2.6.16 user mode. I made a little perl script that
generates a histogram from ping's output and there were only single
packets lost.
However, just when I was about to test kernel mode with 2.6.15.7 tonight,
this effect disappeared. Might have been my ISP after all.
Thus, for the time being, kernel mode PPPoE seems to be a viable
workaround.
The whole matter is a bit strange to me. I would have expected that the
kernel only communicates with pppd which then utilizes a process
encapsulating the packts in ethernet frames. That's why I didn't
think this bug was a pure pppoe issue, which it seems to be.
Regards, Nuri
^ permalink raw reply
* Re: [PATCH] au1000_eth.c: use ether_crc() from <linux/crc32.h>
From: Ralf Baechle @ 2006-05-02 20:34 UTC (permalink / raw)
To: Herbert Valerio Riedel; +Cc: jgarzik, netdev, linux-mips, sshtylyov
In-Reply-To: <E1FaYil-0007A8-HB@fencepost.gnu.org>
On Mon, May 01, 2006 at 01:46:42PM +0000, Herbert Valerio Riedel wrote:
> since the au1000 driver already selects the CRC32 routines, simply replace
> the internal ether_crc() implementation with the semantically equivalent
> one from <linux/crc32.h>
>
> Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org>
Looks good to me.
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Ralf
^ permalink raw reply
* Re: forcedeth driver NAPI?
From: Francois Romieu @ 2006-05-02 20:06 UTC (permalink / raw)
To: Andi Kleen; +Cc: Stephen Hemminger, Ingo Oeser, Manfred Spraul, netdev
In-Reply-To: <200605022135.53580.ak@suse.de>
Andi Kleen <ak@suse.de> :
> On Tuesday 02 May 2006 21:11, Stephen Hemminger wrote:
[napi for forcedeth]
> Making it support netpoll would be nice too.
<wishlist>
Disable/resume the device with something less gross than
http://bugzilla.kernel.org/show_bug.cgi?id=6398
</wishlist>
--
Ueimor
^ permalink raw reply
* Question on e1000 patch, rx-copy-break related.
From: Ben Greear @ 2006-05-02 19:56 UTC (permalink / raw)
To: NetDev; +Cc: jeffrey.t.kirsher
In commit: a292ca6efbc1f259ddfb9c902367f2588e0e8b0f
to e1000_main.c, there is the change below.
I am curious why the skb_put no longer subtracts ETHERNET_FCS_SIZE
from the length. Is the idea that we will now always include the
FCS at the end of the skb?
It also seems that the skb_put for the else clause is missing here, but
I think it is fixed in some later patch.
The main reason I ask is that I have a patch that enabled reception of the
FCS in 2.6.13. It used a flag to determine whether to subtract the ETHERNET_FCS_SIZE
from length (or not, if we are capturing FCS). I am trying to figure out if this
is still needed in the later releases.
Thanks,
Ben
@@ -3613,17 +3618,40 @@ #endif
}
}
- /* Good Receive */
- skb_put(skb, length - ETHERNET_FCS_SIZE);
+ /* code added for copybreak, this should improve
+ * performance for small packets with large amounts
+ * of reassembly being done in the stack */
+#define E1000_CB_LENGTH 256
+ if ((length < E1000_CB_LENGTH) &&
+ !rx_ring->rx_skb_top &&
+ /* or maybe (status & E1000_RXD_STAT_EOP) && */
+ !multi_descriptor) {
+ struct sk_buff *new_skb =
+ dev_alloc_skb(length + NET_IP_ALIGN);
+ if (new_skb) {
+ skb_reserve(new_skb, NET_IP_ALIGN);
+ new_skb->dev = netdev;
+ memcpy(new_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ length + NET_IP_ALIGN);
+ /* save the skb in buffer_info as good */
+ buffer_info->skb = skb;
+ skb = new_skb;
+ skb_put(skb, length);
+ }
+ }
+
+ /* end copybreak code */
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: forcedeth driver NAPI?
From: Andi Kleen @ 2006-05-02 19:35 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Ingo Oeser, Manfred Spraul, netdev
In-Reply-To: <20060502121151.63786a86@localhost.localdomain>
On Tuesday 02 May 2006 21:11, Stephen Hemminger wrote:
> Has anyone looked into making this driver use NAPI? This would fix
> the IRQ overload problem and a number of other DoS risks.
> Also, if done right the device lock could be reduced to just
> a transmit lock.
Making it support netpoll would be nice too.
-Andi
^ permalink raw reply
* [git patches] net driver fixes
From: Jeff Garzik @ 2006-05-02 19:30 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: netdev, linux-kernel, Stephen Hemminger
This is the last net driver push from me until May 12th.
Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
to receive the following updates:
drivers/net/forcedeth.c | 312 +++++++++++++++++++++++++++++++++-------------
drivers/net/mv643xx_eth.c | 2
drivers/net/via-rhine.c | 6
3 files changed, 236 insertions(+), 84 deletions(-)
Ayaz Abdulla:
forcedeth: fix multi irq issues
Craig Brind:
via-rhine: zero pad short packets on Rhine I ethernet cards
Olaf Hering:
mv643xx_eth: provide sysfs class device symlink
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 9788b1e..f7235c9 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -106,6 +106,7 @@
* 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
* 0.52: 20 Jan 2006: Add MSI/MSIX support.
* 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
+ * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -117,7 +118,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.53"
+#define FORCEDETH_VERSION "0.54"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -710,6 +711,72 @@ static void setup_hw_rings(struct net_de
}
}
+static int using_multi_irqs(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+ ((np->msi_flags & NV_MSI_X_ENABLED) &&
+ ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1)))
+ return 0;
+ else
+ return 1;
+}
+
+static void nv_enable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
+ } else {
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+static void nv_disable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
+ } else {
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+/* In MSIX mode, a write to irqmask behaves as XOR */
+static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ u8 __iomem *base = get_hwbase(dev);
+
+ writel(mask, base + NvRegIrqMask);
+}
+
+static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ writel(mask, base + NvRegIrqMask);
+ } else {
+ if (np->msi_flags & NV_MSI_ENABLED)
+ writel(0, base + NvRegMSIIrqMask);
+ writel(0, base + NvRegIrqMask);
+ }
+}
+
#define MII_READ (-1)
/* mii_rw: read/write a register on the PHY.
*
@@ -1019,24 +1086,25 @@ static void nv_do_rx_refill(unsigned lon
struct net_device *dev = (struct net_device *) data;
struct fe_priv *np = netdev_priv(dev);
-
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
} else {
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
@@ -1668,15 +1736,7 @@ static int nv_change_mtu(struct net_devi
* guessed, there is probably a simpler approach.
* Changing the MTU is a rare event, it shouldn't matter.
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
- } else {
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
spin_lock(&np->lock);
/* stop engines */
@@ -1709,15 +1769,7 @@ static int nv_change_mtu(struct net_devi
nv_start_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
- } else {
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_enable_irq(dev);
}
return 0;
}
@@ -2108,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo
if (!(events & np->irqmask))
break;
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_tx_done(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
if (events & (NVREG_IRQ_TX_ERR)) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2127,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2157,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo
nv_rx_process(dev);
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2174,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2203,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int
break;
if (events & NVREG_IRQ_LINK) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_link_irq(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_linkchange(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
np->link_timeout = jiffies + LINK_TIMEOUT;
}
if (events & (NVREG_IRQ_UNKNOWN)) {
@@ -2218,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
pci_push(base);
@@ -2228,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2251,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long
* nv_nic_irq because that may decide to do otherwise
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
@@ -2277,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long
writel(mask, base + NvRegIrqMask);
pci_push(base);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+ if (!using_multi_irqs(dev)) {
nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
- enable_irq(dev->irq);
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL);
@@ -2628,6 +2682,113 @@ static void set_msix_vector_map(struct n
writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
}
+static int nv_request_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ int ret = 1;
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_CAPABLE) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ np->msi_x_entry[i].entry = i;
+ }
+ if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+ np->msi_flags |= NV_MSI_X_ENABLED;
+ if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
+ /* Request irq for rx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+ /* Request irq for tx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_rx;
+ }
+ /* Request irq for link and timer handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_tx;
+ }
+ /* map interrupts to their respective vector */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+ } else {
+ /* Request irq for all interrupts */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ }
+ }
+ }
+ if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+ if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+ np->msi_flags |= NV_MSI_ENABLED;
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIMap0);
+ writel(0, base + NvRegMSIMap1);
+ /* enable msi vector 0 */
+ writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+ }
+ }
+ if (ret != 0) {
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
+ goto out_err;
+ }
+
+ return 0;
+out_free_tx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
+out_free_rx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
+out_err:
+ return 1;
+}
+
+static void nv_free_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ free_irq(np->msi_x_entry[i].vector, dev);
+ }
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ } else {
+ free_irq(np->pci_dev->irq, dev);
+ if (np->msi_flags & NV_MSI_ENABLED) {
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ }
+ }
+}
+
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -2720,12 +2881,16 @@ static int nv_open(struct net_device *de
udelay(10);
writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
- writel(0, base + NvRegIrqMask);
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
pci_push(base);
+ if (nv_request_irq(dev)) {
+ goto out_drain;
+ }
+
if (np->msi_flags & NV_MSI_X_CAPABLE) {
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
np->msi_x_entry[i].entry = i;
@@ -2799,7 +2964,7 @@ static int nv_open(struct net_device *de
}
/* ask for interrupts */
- writel(np->irqmask, base + NvRegIrqMask);
+ nv_enable_hw_interrupts(dev, np->irqmask);
spin_lock_irq(&np->lock);
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
@@ -2843,7 +3008,6 @@ static int nv_close(struct net_device *d
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base;
- int i;
spin_lock_irq(&np->lock);
np->in_shutdown = 1;
@@ -2861,31 +3025,13 @@ static int nv_close(struct net_device *d
/* disable interrupts on the nic or we will lock up */
base = get_hwbase(dev);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- writel(np->irqmask, base + NvRegIrqMask);
- } else {
- if (np->msi_flags & NV_MSI_ENABLED)
- writel(0, base + NvRegMSIIrqMask);
- writel(0, base + NvRegIrqMask);
- }
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
spin_unlock_irq(&np->lock);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
- free_irq(np->msi_x_entry[i].vector, dev);
- }
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- } else {
- free_irq(np->pci_dev->irq, dev);
- if (np->msi_flags & NV_MSI_ENABLED) {
- pci_disable_msi(np->pci_dev);
- np->msi_flags &= ~NV_MSI_ENABLED;
- }
- }
+ nv_free_irq(dev);
drain_ring(dev);
@@ -2974,20 +3120,18 @@ static int __devinit nv_probe(struct pci
if (id->driver_data & DEV_HAS_HIGH_DMA) {
/* packet format 3: supports 40-bit addressing */
np->desc_ver = DESC_VER_3;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
} else {
- if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
- printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
- pci_name(pci_dev));
- goto out_relreg;
- } else {
- dev->features |= NETIF_F_HIGHDMA;
- printk(KERN_INFO "forcedeth: using HIGHDMA\n");
- }
+ dev->features |= NETIF_F_HIGHDMA;
+ printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+ }
+ if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
+ pci_name(pci_dev));
}
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
/* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index ea62a3e..411f4d8 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1419,6 +1419,8 @@ #endif
mv643xx_eth_update_pscr(dev, &cmd);
mv643xx_set_settings(dev, &cmd);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
err = register_netdev(dev);
if (err)
goto out;
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 6a23964..a6dc53b 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -129,6 +129,7 @@
- Massive clean-up
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
- Fix Tx engine race for good
+ - Craig Brind: Zero padded aligned buffers for short packets.
*/
@@ -1326,7 +1327,12 @@ static int rhine_start_tx(struct sk_buff
rp->stats.tx_dropped++;
return 0;
}
+
+ /* Padding is not copied and so must be redone. */
skb_copy_and_csum_dev(skb, rp->tx_buf[entry]);
+ if (skb->len < ETH_ZLEN)
+ memset(rp->tx_buf[entry] + skb->len, 0,
+ ETH_ZLEN - skb->len);
rp->tx_skbuff_dma[entry] = 0;
rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma +
(rp->tx_buf[entry] -
^ permalink raw reply related
* Re: [patch 1/5] s2io driver updates
From: Jeff Garzik @ 2006-05-02 19:16 UTC (permalink / raw)
To: Ananda Raju
Cc: netdev, leonid.grossman, ravinandan.arakali, rapuru.sriram,
alicia.pena
In-Reply-To: <Pine.GSO.4.10.10604211900320.15266-100000@guinness>
Ananda Raju wrote:
> hi,
> This patch contains all the changes that were done to improve
> performance of s2io driver. one line description of the changes
> are
>
> 1. For Non NAPI case the rx interrupt handler is being called
> unconditionally
> 2. code optimization and adding prefetch skb->data
> 3. Remove modulo operations in fast path
> 4. Enable Group Reads and set backoff interval to 0x1000
> 5. correct PIC_CNTL_SHARED_SPLITS macro definition, and reduce
> pause parameter
> 6. Corrected logic of identifying rx buffer level in rx_buffer_level()
> 7. fix DMA map and unmap done with different sizes in 1-buf mode
> 8. Removed forcible disabling of ERO
> 9. Send up the packets with transfer code = 0x5
>
> Signed-off-by: Ananda Raju <ananda.raju@neterion.com>
applied 1-5 to #upstream
^ permalink raw reply
* forcedeth driver NAPI?
From: Stephen Hemminger @ 2006-05-02 19:11 UTC (permalink / raw)
To: Ingo Oeser; +Cc: Manfred Spraul, netdev
In-Reply-To: <200605021549.47719.netdev@axxeo.de>
Has anyone looked into making this driver use NAPI? This would fix
the IRQ overload problem and a number of other DoS risks.
Also, if done right the device lock could be reduced to just
a transmit lock.
^ permalink raw reply
* Re: [PATCH 2/3] ipg: leaks in ipg_probe
From: Pekka Enberg @ 2006-05-02 19:04 UTC (permalink / raw)
To: Francois Romieu; +Cc: David Vrabel, linux-kernel, netdev, david
In-Reply-To: <20060502183313.GA26357@electric-eye.fr.zoreil.com>
Pekka J Enberg <penberg@cs.Helsinki.FI> :
> [...]
> > Is this tested with hardware?
On Tue, 2006-05-02 at 20:33 +0200, Francois Romieu wrote:
> No.
On Tue, 2006-05-02 at 20:33 +0200, Francois Romieu wrote:
> > Alignment of the start address looks bogus for sure, but any idea
> > why they had it in the first place?
Pekka J Enberg <penberg@cs.Helsinki.FI> :
> No clear idea but it matches the significant part of the BAR register
> for the 256 bytes of I/O space that the device uses.
OK. David & David, would appreciate if either you could give the patch a
spin with Francois' changes. Thanks.
Pekka
^ permalink raw reply
* net/d80211 and management interface (wmaster0ap)
From: Jouni Malinen @ 2006-05-02 18:39 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev
It looks like one of your patches in wireless-dev.git broke management
interface. I'm not completely sure about how this was supposed to work,
but are the low-level drivers now expected to accept
IEEE80211_IF_TYPE_MGMT in add_interface handler or should ieee80211.c be
modified to accept wmaster0ap to be set UP without asking the low-level
driver? The patch below does the former by modifying bcm43xx_main.c to
have a special case for IEEE80211_IF_TYPE_MGMT. This interface itself
does not require additional functionality from the low-level driver.
In addition to this, it looked like sending packets from wmaster0ap did
not work. The packets were being dropped since originating device
(wmaster0ap) did not match in is_ieee80211_device(). This function
seemed to use wireless_handlers pointer for recognizing interfaces which
(like to comment says) is not that nice. wireless_handlers were not set
for apdev, so the patch below adds it to make TX work through
wmaster0ap.
Does these match with your understanding of how the management interface
is supposed to work now after your patches went in?
Allow management interface (wmaster0ap) to be set UP with bcm43xx and
allow frames to be sent through it by making sure that
is_ieee80211_device(apdev) returns 1.
Signed-off-by: Jouni Malinen <jkm@devicescape.com>
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
--- wireless-dev.orig/net/d80211/ieee80211.c
+++ wireless-dev/net/d80211/ieee80211.c
@@ -4115,6 +4115,8 @@ struct net_device *ieee80211_alloc_hw(si
ether_setup(apdev);
apdev->priv = local;
apdev->hard_start_xmit = ieee80211_mgmt_start_xmit;
+ apdev->wireless_handlers =
+ (struct iw_handler_def *) &ieee80211_iw_handler_def;
apdev->change_mtu = ieee80211_change_mtu_apdev;
apdev->get_stats = ieee80211_get_stats;
apdev->open = ieee80211_open;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -4195,6 +4195,9 @@ static int bcm43xx_add_interface(struct
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ if (conf->type == IEEE80211_IF_TYPE_MGMT)
+ return 0;
+
if (bcm->interfaces > 0)
return -ENOBUFS;
if (conf->type == IEEE80211_IF_TYPE_MNTR) {
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* Re: [PATCH 2/3] ipg: leaks in ipg_probe
From: Francois Romieu @ 2006-05-02 18:33 UTC (permalink / raw)
To: Pekka J Enberg; +Cc: David Vrabel, linux-kernel, netdev, david
In-Reply-To: <Pine.LNX.4.58.0605020936420.4066@sbz-30.cs.Helsinki.FI>
Pekka J Enberg <penberg@cs.Helsinki.FI> :
[...]
> Is this tested with hardware?
No.
> Alignment of the start address looks bogus for sure, but any idea
> why they had it in the first place?
No clear idea but it matches the significant part of the BAR register
for the 256 bytes of I/O space that the device uses.
--
Ueimor
^ permalink raw reply
* Re: [PATCH 001/100] TCP congestion module: add TCP-LP supporting for 2.6.16
From: Stephen Hemminger @ 2006-05-02 17:23 UTC (permalink / raw)
To: Wong Edison; +Cc: netdev, linux-kernel
In-Reply-To: <3feffd230605010305o6e3b1511of1f75b17f2797e66@mail.gmail.com>
> +/**
> + * struct lp
> + * @flag: TCP-LP state flag
> + * @sowd: smoothed OWD << 3
> + * @owd_min: min OWD
> + * @owd_max: max OWD
> + * @owd_max_rsv: resrved max owd
> + * @RHZ: estimated remote HZ
> + * @remote_ref_time: remote reference time
> + * @local_ref_time: local reference time
> + * @last_drop: time for last active drop
> + * @inference: current inference
> + *
> + * TCP-LP's private struct.
> + * We get the idea from original TCP-LP implementation where only left those we
> + * found are really useful.
> + */
> +struct lp {
> + u32 flag;
> + u32 sowd;
> + u32 owd_min;
> + u32 owd_max;
> + u32 owd_max_rsv;
> + u32 RHZ;
> + u32 remote_ref_time;
> + u32 local_ref_time;
> + u32 last_drop;
> + u32 inference;
> +};
It is best to keep structure element names lower case.
s/RHZ/rhz/
or use remote_hz
^ permalink raw reply
* Re: [PATCH 001/100] TCP congestion module: add TCP-LP supporting for 2.6.16
From: Stephen Hemminger @ 2006-05-02 17:16 UTC (permalink / raw)
To: Wong Edison; +Cc: netdev
In-Reply-To: <3feffd230605010305o6e3b1511of1f75b17f2797e66@mail.gmail.com>
On Mon, 1 May 2006 18:05:52 +0800
"Wong Edison" <hswong3i@gmail.com> wrote:
> TCP Low Priority is a distributed algorithm whose goal is to utilize only
> the excess network bandwidth as compared to the ``fair share`` of
> bandwidth as targeted by TCP. Available from:
> http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
>
> See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation.
> Our group take the following changes from
> the original TCP-LP implementation:
> o We use newReno in most core CA handling. Only add some checking
> within cong_avoid.
> o Error correcting in remote HZ, therefore remote HZ will be keeped
> on checking and updating.
> o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne
> OWD have a similar meaning as RTT. Also correct the buggy formular.
> o Handle reaction for Early Congestion Indication (ECI) within
> pkts_acked, as mentioned within pseudo code.
> o OWD is handled in relative format, where local time stamp will in
> tcp_time_stamp format.
>
> Port from 2.4.19 to 2.6.16 as module by:
> Wong Hoi Sing Edison <hswong3i@gmail.com>
> Hung Hing Lun <hlhung3i@gmail.com>
>
> Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
>
Is this all of it? Your subject line says there are a 99 more pieces.
That seems huge.
^ permalink raw reply
* Re: Van Jacobson's net channels and real-time
From: Andi Kleen @ 2006-05-02 15:58 UTC (permalink / raw)
To: Vojtech Pavlik
Cc: linux-os (Dick Johnson), Auke Kok, Auke Kok, Ingo Oeser,
Jörn Engel, Ingo Oeser, David S. Miller, simlo, linux-kernel,
mingo, netdev
In-Reply-To: <20060502124131.GA13160@suse.cz>
On Tuesday 02 May 2006 14:41, Vojtech Pavlik wrote:
> You seem to be missing the fact that most of todays interrupts are
> delivered through the APIC bus, which isn't fast at all.
You mean slow right? Modern x86s (anything newer than a P3) generally don't
have an separate APIC bus anymore but just send messages over their main
processor connection.
-Andi
^ permalink raw reply
* Re: Disabling "TCP Treason uncloaked"
From: Andi Kleen @ 2006-05-02 16:02 UTC (permalink / raw)
To: Just Marc; +Cc: netdev
In-Reply-To: <44578691.4020402@corky.net>
On Tuesday 02 May 2006 18:19, Just Marc wrote:
> I thought that maybe it's time to either set TCP_DEBUG to 0 or
> alternatively allow an admin to toggle the printing of this message
> off/on? On a few busy web servers running usually latest versions of
> 2.6 I have this message displaying hundreds (if not more) times a day,
You're talking to a lot of broken TCP clients then.
> completely clogging the kernel log and making it harder to see if there
> are more interesting messages being printed. TCP_DEBUG is being used
> in one more place that may also not require it anymore and or have it
> always enabled.
It's better to use run time switches for these kind of things.
> So, is it time to disable this print altogether? Is it time to allow an
> admin to toggle printing of this thing off?
If it's disabled there should be probably a netstat counter for the condition instead.
It might be a reasonable simple beginner project for someone:
- Convert all NETDEBUGs/TCP_DEBUG to a single netdebug sysctl
- Then perhaps make a CONFIG to change its default: 0 or 1
- Add statistics counters for all of these conditions
-Andi
^ permalink raw reply
* Disabling "TCP Treason uncloaked"
From: Just Marc @ 2006-05-02 16:19 UTC (permalink / raw)
To: netdev
Hi everyone,
Looking at mailing list archives there has been much talk of this print
in the past, given the fact that this check/print is surrounded by an
#ifdef TCP_DEBUG
#ifdef TCP_DEBUG
if (net_ratelimit()) {
struct inet_sock *inet = inet_sk(sk);
printk(KERN_DEBUG "TCP: Treason uncloaked! Peer
%u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
NIPQUAD(inet->daddr), htons(inet->dport),
inet->num, tp->snd_una, tp->snd_nxt);
}
#endif
I thought that maybe it's time to either set TCP_DEBUG to 0 or
alternatively allow an admin to toggle the printing of this message
off/on? On a few busy web servers running usually latest versions of
2.6 I have this message displaying hundreds (if not more) times a day,
completely clogging the kernel log and making it harder to see if there
are more interesting messages being printed. TCP_DEBUG is being used
in one more place that may also not require it anymore and or have it
always enabled.
So, is it time to disable this print altogether? Is it time to allow an
admin to toggle printing of this thing off?
Thanks for your time
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox