* Re: [PATCH 1/1] Defer skb allocation for both mergeable buffers and big packets in virtio_net
From: Michael S. Tsirkin @ 2009-11-25 9:15 UTC (permalink / raw)
To: Rusty Russell
Cc: Shirley Ma, Eric Dumazet, Avi Kivity, netdev, kvm, linux-kernel,
Hollis Blanchard
In-Reply-To: <200911251042.06368.rusty@rustcorp.com.au>
On Wed, Nov 25, 2009 at 10:42:06AM +1030, Rusty Russell wrote:
> On Tue, 24 Nov 2009 10:07:54 pm Michael S. Tsirkin wrote:
> > On Tue, Nov 24, 2009 at 08:54:23AM +1030, Rusty Russell wrote:
> > > On Tue, 24 Nov 2009 02:37:01 am Shirley Ma wrote:
> > > > > > + skb = (struct sk_buff *)buf;
> > > > > This cast is unnecessary, but a comment would be nice:
> > > >
> > > > Without this cast there is a compile warning.
> > >
> > > Hi Shirley,
> > >
> > > Looks like buf is a void *, so no cast should be necessary. But I could
> > > be reading the patch wrong.
> > >
> > > > > However, I question whether making it 16 byte is the right thing: the
> > > > > ethernet header is 14 bytes long, so don't we want 8 bytes of padding?
> > > >
> > > > Because in QEMU it requires 10 bytes header in a separately, so one page
> > > > is used to share between virtio_net_hdr header which is 10 bytes head
> > > > and rest of data. So I put 6 bytes offset here between two buffers. I
> > > > didn't look at the reason why a seperate buf is used for virtio_net_hdr
> > > > in QEMU.
> > >
> > > It's a qemu bug. It insists the header be an element in the scatterlist by
> > > itself. Unfortunately we have to accommodate it.
> >
> > We do? Let's just fix this?
> > All we have to do is replace memcpy with proper iovec walk, correct?
> > Something like the followng (untested) patch? It's probably not too
> > late to put this in the next qemu release...
>
> You might want to implement a more generic helper which does:
>
> /* Return pointer into iovec if we can, otherwise copy into buf */
> void *pull_iovec(struct iovec *iov, int iovcnt, void *buf, size_t len)
> {
> unsigned int i;
> void *p;
>
> if (likely(iov_cnt && iov[0].iov_len >= len)) {
> /* Nice contiguous chunk. */
> void *p = iov[0].iov_base;
> iov[i].iov_base += len;
> iov[i].iov_len -= len;
> return p;
> }
>
> p = buf;
> for (i = 0; i < iov_cnt; i++) {
> size_t this_len = min(len, iov[i].iov_len);
> memcpy(p, iov[i].iov_base, this_len);
> len -= this_len;
> iov[i].iov_base += len;
> iov[i].iov_len -= len;
> if (len == 0)
> return buf;
> }
> /* BTW, we screwed your iovec. */
> return NULL;
> }
>
> Then use it in all the virtio drivers...
Hmm, is it really worth it to save a header copy if it's linear? We are
going to access it anyway, and it fits into one cacheline nicely. On
the other hand we have more code making life harder for compiler and
processor.
> Thanks!
> Rusty.
^ permalink raw reply
* Re: [tproxy] [HELP] Tproxy server Can't receive any client packet
From: KOVACS Krisztian @ 2009-11-25 8:30 UTC (permalink / raw)
To: 박제호
Cc: tproxy, netfilter-announce, netfilter, netdev, rnd, dylee
In-Reply-To: <d5cf4b4f0911222251u1589c66ar78810d5b9d87cb5e@mail.gmail.com>
Hi,
On Mon, 2009-11-23 at 15:51 +0900, 박제호 wrote:
> i have a problem in my transparent proxy test,
> i recently made up the testbed as below to run the tproxy patched
> apache proxy [mod_proxy],
> and i applied all iptables and routing rules with referencing the
> readme file [http://www.balabit.com/downloads/files/tproxy/README.txt,
> http://www.mjmwired.net/kernel/Documentation/networking/tproxy.txt]
> the proxy server listening the port 3128 and i checked there were no problem.
> but when the client tried to connect the web server,
> the packets reached to the box and i found the usage counts of filter
> rules in the mangle table incresed
> but my tproxy server could not receive any corresponding packet from the socket
>
> I want to know why my proxy server can't receive any packet through the socket,
> Do i need some more DNAT rules ?
Would you mind testing the setup with an unpatched upstream kernel, that
has tproxy built-in? (2.6.31, for example)
Also, please download the latest iptables from netfilter.org and try
using that. (No need for patching, tproxy support is in upstream.)
That would help a lot in identifying the source of the issue. Thanks in
advance.
Cheers,
Krisztian
^ permalink raw reply
* Re: [tproxy] [HELP] Tproxy server Can't receive any client packet
From: linuxpark @ 2009-11-25 8:54 UTC (permalink / raw)
To: KOVACS Krisztian
Cc: tproxy, netfilter-announce, netfilter, netdev, rnd, dylee
In-Reply-To: <1259137840.9191.7.camel@nienna.balabit>
Thanks your reply ~
i succeed in tproxy function of the apache server
--
kernel 2.6.31 (vannilla kernel)
iptables 1.4.3 (no patched)
apache 2.2.9 + patches (main socket routine of the apache, mod_tproxy.c)
--
KOVACS Krisztian 쓴 글:
> Hi,
>
> On Mon, 2009-11-23 at 15:51 +0900, 박제호 wrote:
>
>> i have a problem in my transparent proxy test,
>> i recently made up the testbed as below to run the tproxy patched
>> apache proxy [mod_proxy],
>> and i applied all iptables and routing rules with referencing the
>> readme file [http://www.balabit.com/downloads/files/tproxy/README.txt,
>> http://www.mjmwired.net/kernel/Documentation/networking/tproxy.txt]
>> the proxy server listening the port 3128 and i checked there were no problem.
>> but when the client tried to connect the web server,
>> the packets reached to the box and i found the usage counts of filter
>> rules in the mangle table incresed
>> but my tproxy server could not receive any corresponding packet from the socket
>>
>> I want to know why my proxy server can't receive any packet through the socket,
>> Do i need some more DNAT rules ?
>>
>
> Would you mind testing the setup with an unpatched upstream kernel, that
> has tproxy built-in? (2.6.31, for example)
>
> Also, please download the latest iptables from netfilter.org and try
> using that. (No need for patching, tproxy support is in upstream.)
>
> That would help a lot in identifying the source of the issue. Thanks in
> advance.
>
> Cheers,
> Krisztian
>
>
>
^ permalink raw reply
* Re: [patch]USB autosuspend for cdc-ether
From: Oliver Neukum @ 2009-11-25 8:39 UTC (permalink / raw)
To: Steve.Glendinning-sdUf+H5yV5I
Cc: David S. Miller, David Brownell, linux-usb-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz, Torgny Johansson
In-Reply-To: <OFCBC12A15.7006C53A-ON80257678.00524557-80257678.005373C0-sdUf+H5yV5I@public.gmane.org>
Am Dienstag, 24. November 2009 16:11:28 schrieb Steve.Glendinning-sdUf+H5yV5I@public.gmane.org:
> Interesting patch, I'm going to try and add support for this
> to smsc95xx.
>
> A few things I noticed:
>
Hi,
this version should fix what you mentioned.
Regards
Oliver
Signed-off-by: Oliver Neukum <oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
--
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 21e1ba1..ed55024 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -411,6 +411,12 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
return 0;
}
+static int cdc_manage_power(struct usbnet *dev, int on)
+{
+ dev->intf->needs_remote_wakeup = on;
+ return 0;
+}
+
static const struct driver_info cdc_info = {
.description = "CDC Ethernet Device",
.flags = FLAG_ETHER,
@@ -418,6 +424,7 @@ static const struct driver_info cdc_info = {
.bind = cdc_bind,
.unbind = usbnet_cdc_unbind,
.status = cdc_status,
+ .manage_power = cdc_manage_power,
};
/*-------------------------------------------------------------------------*/
@@ -610,6 +617,7 @@ static struct usb_driver cdc_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .supports_autosuspend = 1,
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ca5ca5a..50a48e2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -353,7 +353,8 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
- && !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ && !test_bit (EVENT_RX_HALT, &dev->flags)
+ && !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) {
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
@@ -611,15 +612,39 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
/*-------------------------------------------------------------------------*/
// precondition: never called in_interrupt
+static void usbnet_terminate_urbs(struct usbnet *dev)
+{
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);
+ DECLARE_WAITQUEUE (wait, current);
+ int temp;
+
+ /* ensure there are no more active urbs */
+ add_wait_queue(&unlink_wakeup, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ dev->wait = &unlink_wakeup;
+ temp = unlink_urbs(dev, &dev->txq) +
+ unlink_urbs(dev, &dev->rxq);
+
+ /* maybe wait for deletions to finish. */
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
+ schedule_timeout(UNLINK_TIMEOUT_MS);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (netif_msg_ifdown(dev))
+ devdbg(dev, "waited for %d urb completions",
+ temp);
+ }
+ set_current_state(TASK_RUNNING);
+ dev->wait = NULL;
+ remove_wait_queue(&unlink_wakeup, &wait);
+}
int usbnet_stop (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
struct driver_info *info = dev->driver_info;
- int temp;
int retval;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);
- DECLARE_WAITQUEUE (wait, current);
netif_stop_queue (net);
@@ -641,25 +666,8 @@ int usbnet_stop (struct net_device *net)
info->description);
}
- if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
- /* ensure there are no more active urbs */
- add_wait_queue(&unlink_wakeup, &wait);
- dev->wait = &unlink_wakeup;
- temp = unlink_urbs(dev, &dev->txq) +
- unlink_urbs(dev, &dev->rxq);
-
- /* maybe wait for deletions to finish. */
- while (!skb_queue_empty(&dev->rxq)
- && !skb_queue_empty(&dev->txq)
- && !skb_queue_empty(&dev->done)) {
- msleep(UNLINK_TIMEOUT_MS);
- if (netif_msg_ifdown(dev))
- devdbg(dev, "waited for %d urb completions",
- temp);
- }
- dev->wait = NULL;
- remove_wait_queue(&unlink_wakeup, &wait);
- }
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS))
+ usbnet_terminate_urbs(dev);
usb_kill_urb(dev->interrupt);
@@ -672,7 +680,10 @@ int usbnet_stop (struct net_device *net)
dev->flags = 0;
del_timer_sync (&dev->delay);
tasklet_kill (&dev->bh);
- usb_autopm_put_interface(dev->intf);
+ if (info->manage_power)
+ info->manage_power(dev, 0);
+ else
+ usb_autopm_put_interface(dev->intf);
return 0;
}
@@ -753,6 +764,12 @@ int usbnet_open (struct net_device *net)
// delay posting reads until we're fully open
tasklet_schedule (&dev->bh);
+ if (info->manage_power) {
+ retval = info->manage_power(dev, 1);
+ if (retval < 0)
+ goto done;
+ usb_autopm_put_interface(dev->intf);
+ }
return retval;
done:
usb_autopm_put_interface(dev->intf);
@@ -881,11 +898,16 @@ kevent (struct work_struct *work)
/* usb_clear_halt() needs a thread context */
if (test_bit (EVENT_TX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->txq);
+ status = usb_autopm_get_interface(dev->intf);
+ if (status < 0)
+ goto fail_pipe;
status = usb_clear_halt (dev->udev, dev->out);
+ usb_autopm_put_interface(dev->intf);
if (status < 0
&& status != -EPIPE
&& status != -ESHUTDOWN) {
if (netif_msg_tx_err (dev))
+fail_pipe:
deverr (dev, "can't clear tx halt, status %d",
status);
} else {
@@ -896,11 +918,16 @@ kevent (struct work_struct *work)
}
if (test_bit (EVENT_RX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->rxq);
+ status = usb_autopm_get_interface(dev->intf);
+ if (status < 0)
+ goto fail_halt;
status = usb_clear_halt (dev->udev, dev->in);
+ usb_autopm_put_interface(dev->intf);
if (status < 0
&& status != -EPIPE
&& status != -ESHUTDOWN) {
if (netif_msg_rx_err (dev))
+fail_halt:
deverr (dev, "can't clear rx halt, status %d",
status);
} else {
@@ -919,7 +946,12 @@ kevent (struct work_struct *work)
clear_bit (EVENT_RX_MEMORY, &dev->flags);
if (urb != NULL) {
clear_bit (EVENT_RX_MEMORY, &dev->flags);
+ status = usb_autopm_get_interface(dev->intf);
+ if (status < 0)
+ goto fail_lowmem;
rx_submit (dev, urb, GFP_KERNEL);
+ usb_autopm_put_interface(dev->intf);
+fail_lowmem:
tasklet_schedule (&dev->bh);
}
}
@@ -929,11 +961,18 @@ kevent (struct work_struct *work)
int retval = 0;
clear_bit (EVENT_LINK_RESET, &dev->flags);
+ status = usb_autopm_get_interface(dev->intf);
+ if (status < 0)
+ goto skip_reset;
if(info->link_reset && (retval = info->link_reset(dev)) < 0) {
+ usb_autopm_put_interface(dev->intf);
+skip_reset:
devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s",
retval,
dev->udev->bus->bus_name, dev->udev->devpath,
info->description);
+ } else {
+ usb_autopm_put_interface(dev->intf);
}
}
@@ -971,6 +1010,7 @@ static void tx_complete (struct urb *urb)
case -EPROTO:
case -ETIME:
case -EILSEQ:
+ usb_mark_last_busy(dev->udev);
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay,
jiffies + THROTTLE_JIFFIES);
@@ -987,6 +1027,7 @@ static void tx_complete (struct urb *urb)
}
}
+ usb_autopm_put_interface_async(dev->intf);
urb->dev = NULL;
entry->state = tx_done;
defer_bh(dev, skb, &dev->txq);
@@ -1058,13 +1099,33 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
}
spin_lock_irqsave (&dev->txq.lock, flags);
+ retval = usb_autopm_get_interface_async(dev->intf);
+ if (retval < 0) {
+ spin_unlock_irqrestore (&dev->txq.lock, flags);
+ goto drop;
+ }
+
+#ifdef CONFIG_PM
+ /* if this triggers the device is still a sleep */
+ if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) {
+ /* transmission will be done in resume */
+ usb_anchor_urb(urb, &dev->deferred);
+ /* no use to process more packets */
+ netif_stop_queue(net);
+ spin_unlock_irqrestore(&dev->txq.lock, flags);
+ devdbg(dev, "Delaying transmission for resumption");
+ goto deferred;
+ }
+#endif
switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) {
case -EPIPE:
netif_stop_queue (net);
usbnet_defer_kevent (dev, EVENT_TX_HALT);
+ usb_autopm_put_interface_async(dev->intf);
break;
default:
+ usb_autopm_put_interface_async(dev->intf);
if (netif_msg_tx_err (dev))
devdbg (dev, "tx: submit urb err %d", retval);
break;
@@ -1088,6 +1149,7 @@ drop:
devdbg (dev, "> tx, len %d, type 0x%x",
length, skb->protocol);
}
+deferred:
return NETDEV_TX_OK;
}
EXPORT_SYMBOL_GPL(usbnet_start_xmit);
@@ -1255,6 +1317,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->bh.func = usbnet_bh;
dev->bh.data = (unsigned long) dev;
INIT_WORK (&dev->kevent, kevent);
+ init_usb_anchor(&dev->deferred);
dev->delay.function = usbnet_bh;
dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay);
@@ -1363,13 +1426,23 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
struct usbnet *dev = usb_get_intfdata(intf);
if (!dev->suspend_count++) {
+ spin_lock_irq(&dev->txq.lock);
+ /* don't autosuspend while transmitting */
+ if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) {
+ spin_unlock_irq(&dev->txq.lock);
+ return -EBUSY;
+ } else {
+ set_bit(EVENT_DEV_ASLEEP, &dev->flags);
+ spin_unlock_irq(&dev->txq.lock);
+ }
/*
* accelerate emptying of the rx and queues, to avoid
* having everything error out.
*/
netif_device_detach (dev->net);
- (void) unlink_urbs (dev, &dev->rxq);
- (void) unlink_urbs (dev, &dev->txq);
+ usbnet_terminate_urbs(dev);
+ usb_kill_urb(dev->interrupt);
+
/*
* reattach so runtime management can use and
* wake the device
@@ -1383,10 +1456,34 @@ EXPORT_SYMBOL_GPL(usbnet_suspend);
int usbnet_resume (struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
+ struct sk_buff *skb;
+ struct urb *res;
+ int retval;
+
+ if (!--dev->suspend_count) {
+ spin_lock_irq(&dev->txq.lock);
+ while ((res = usb_get_from_anchor(&dev->deferred))) {
+
+ printk(KERN_INFO"Called %s with delayed data\n", __func__);
+ skb = (struct sk_buff *)res->context;
+ retval = usb_submit_urb(res, GFP_ATOMIC);
+ if (retval < 0) {
+ dev_kfree_skb_any(skb);
+ usb_free_urb(res);
+ usb_autopm_put_interface_async(dev->intf);
+ } else {
+ dev->net->trans_start = jiffies;
+ __skb_queue_tail (&dev->txq, skb);
+ }
+ }
- if (!--dev->suspend_count)
+ smp_mb();
+ clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
+ spin_unlock_irq(&dev->txq.lock);
+ if (!(dev->txq.qlen >= TX_QLEN(dev)))
+ netif_start_queue(dev->net);
tasklet_schedule (&dev->bh);
-
+ }
return 0;
}
EXPORT_SYMBOL_GPL(usbnet_resume);
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index f814730..e75ba0e 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -55,6 +55,7 @@ struct usbnet {
struct sk_buff_head done;
struct sk_buff_head rxq_pause;
struct urb *interrupt;
+ struct usb_anchor deferred;
struct tasklet_struct bh;
struct work_struct kevent;
@@ -65,6 +66,8 @@ struct usbnet {
# define EVENT_STS_SPLIT 3
# define EVENT_LINK_RESET 4
# define EVENT_RX_PAUSED 5
+# define EVENT_DEV_WAKING 6
+# define EVENT_DEV_ASLEEP 7
};
static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -107,6 +110,9 @@ struct driver_info {
/* see if peer is connected ... can sleep */
int (*check_connect)(struct usbnet *);
+ /* (dis)activate runtime power management */
+ int (*manage_power)(struct usbnet *, int);
+
/* for status polling */
void (*status)(struct usbnet *, struct urb *);
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 5/7] via-velocity: Re-enable transmit scatter-gather support
From: Simon Kagstrom @ 2009-11-25 8:22 UTC (permalink / raw)
To: davem; +Cc: netdev, davej, shemminger, romieu
In-Reply-To: <20091123153133.2237b04c@marrow.netinsight.se>
The velocity hardware can handle up to 7 memory segments. This can be
turned on and off via ethtool. The support was removed in commit
83c98a8cd04dd0f848574370594886ba3bf56750
but is re-enabled and cleaned up here. It's off by default.
Signed-off-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
---
ChangeLog:
* (David Miller) return NETDEV_TX_OK from the velocity_xmit
function. I'm still a bit unsure on what to actually return in
these cases (they are error cases), but other drivers seem to
return NETDEV_TX_OK, so that's what I went with.
drivers/net/via-velocity.c | 88 +++++++++++++++++++++++++++++---------------
1 files changed, 58 insertions(+), 30 deletions(-)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 06a6d80..2ad25a9 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -9,7 +9,6 @@
*
* TODO
* rx_copybreak/alignment
- * Scatter gather
* More testing
*
* The changes are (c) Copyright 2004, Red Hat Inc. <alan@lxorguk.ukuu.org.uk>
@@ -1656,12 +1655,10 @@ out:
*/
static int velocity_init_td_ring(struct velocity_info *vptr)
{
- dma_addr_t curr;
int j;
/* Init the TD ring entries */
for (j = 0; j < vptr->tx.numq; j++) {
- curr = vptr->tx.pool_dma[j];
vptr->tx.infos[j] = kcalloc(vptr->options.numtx,
sizeof(struct velocity_td_info),
@@ -1727,21 +1724,27 @@ err_free_dma_rings_0:
* Release an transmit buffer. If the buffer was preallocated then
* recycle it, if not then unmap the buffer.
*/
-static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo)
+static void velocity_free_tx_buf(struct velocity_info *vptr,
+ struct velocity_td_info *tdinfo, struct tx_desc *td)
{
struct sk_buff *skb = tdinfo->skb;
- int i;
- int pktlen;
/*
* Don't unmap the pre-allocated tx_bufs
*/
if (tdinfo->skb_dma) {
+ int i;
- pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
for (i = 0; i < tdinfo->nskb_dma; i++) {
- pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE);
- tdinfo->skb_dma[i] = 0;
+ size_t pktlen = max_t(size_t, skb->len, ETH_ZLEN);
+
+ /* For scatter-gather */
+ if (skb_shinfo(skb)->nr_frags > 0)
+ pktlen = max_t(size_t, pktlen,
+ td->td_buf[i].size & ~TD_QUEUE);
+
+ pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i],
+ le16_to_cpu(pktlen), PCI_DMA_TODEVICE);
}
}
dev_kfree_skb_irq(skb);
@@ -1943,7 +1946,7 @@ static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
stats->tx_packets++;
stats->tx_bytes += tdinfo->skb->len;
}
- velocity_free_tx_buf(vptr, tdinfo);
+ velocity_free_tx_buf(vptr, tdinfo, td);
vptr->tx.used[qnum]--;
}
vptr->tx.tail[qnum] = idx;
@@ -2543,14 +2546,27 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
struct velocity_td_info *tdinfo;
unsigned long flags;
int pktlen;
- __le16 len;
- int index;
+ int index, prev;
+ int i = 0;
if (skb_padto(skb, ETH_ZLEN))
goto out;
- pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
- len = cpu_to_le16(pktlen);
+ /* The hardware can handle at most 7 memory segments, so merge
+ * the skb if there are more */
+ if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ /* If it's still above 6 we can't do anything */
+ if (skb_shinfo(skb)->nr_frags > 6) {
+ dev_err(&vptr->pdev->dev,
+ "via-velocity: more than 6 frags, can't send.\n");
+ return NETDEV_TX_OK;
+ }
+ pktlen = skb_shinfo(skb)->nr_frags == 0 ?
+ max_t(unsigned int, skb->len, ETH_ZLEN) :
+ skb_headlen(skb);
spin_lock_irqsave(&vptr->lock, flags);
@@ -2567,11 +2583,24 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
*/
tdinfo->skb = skb;
tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
- td_ptr->tdesc0.len = len;
+ td_ptr->tdesc0.len = cpu_to_le16(pktlen);
td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
td_ptr->td_buf[0].pa_high = 0;
- td_ptr->td_buf[0].size = len;
- tdinfo->nskb_dma = 1;
+ td_ptr->td_buf[0].size = cpu_to_le16(pktlen);
+
+ /* Handle fragments */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ tdinfo->skb_dma[i + 1] = pci_map_page(vptr->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+
+ td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
+ td_ptr->td_buf[i + 1].pa_high = 0;
+ td_ptr->td_buf[i + 1].size = cpu_to_le16(frag->size);
+ }
+ tdinfo->nskb_dma = i + 1;
td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
@@ -2592,23 +2621,21 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
td_ptr->tdesc1.TCR |= (TCR0_UDPCK);
td_ptr->tdesc1.TCR |= TCR0_IPCK;
}
- {
- int prev = index - 1;
+ prev = index - 1;
+ if (prev < 0)
+ prev = vptr->options.numtx - 1;
+ td_ptr->tdesc0.len |= OWNED_BY_NIC;
+ vptr->tx.used[qnum]++;
+ vptr->tx.curr[qnum] = (index + 1) % vptr->options.numtx;
- if (prev < 0)
- prev = vptr->options.numtx - 1;
- td_ptr->tdesc0.len |= OWNED_BY_NIC;
- vptr->tx.used[qnum]++;
- vptr->tx.curr[qnum] = (index + 1) % vptr->options.numtx;
+ if (AVAIL_TD(vptr, qnum) < 1)
+ netif_stop_queue(dev);
- if (AVAIL_TD(vptr, qnum) < 1)
- netif_stop_queue(dev);
+ td_ptr = &(vptr->tx.rings[qnum][prev]);
+ td_ptr->td_buf[0].size |= TD_QUEUE;
+ mac_tx_queue_wake(vptr->mac_regs, qnum);
- td_ptr = &(vptr->tx.rings[qnum][prev]);
- td_ptr->td_buf[0].size |= TD_QUEUE;
- mac_tx_queue_wake(vptr->mac_regs, qnum);
- }
dev->trans_start = jiffies;
spin_unlock_irqrestore(&vptr->lock, flags);
out:
@@ -3398,6 +3425,7 @@ static const struct ethtool_ops velocity_ethtool_ops = {
.set_wol = velocity_ethtool_set_wol,
.get_msglevel = velocity_get_msglevel,
.set_msglevel = velocity_set_msglevel,
+ .set_sg = ethtool_op_set_sg,
.get_link = velocity_get_link,
.get_coalesce = velocity_get_coalesce,
.set_coalesce = velocity_set_coalesce,
--
1.6.0.4
^ permalink raw reply related
* Re: Diagnostic Monitoring Interface Monitoring (DOM) PATCH 0/5 for net-next-2.6
From: Jeff Kirsher @ 2009-11-25 8:18 UTC (permalink / raw)
To: Robert Olsson; +Cc: David Miller, netdev
In-Reply-To: <19211.4244.135603.458550@gargle.gargle.HOWL>
On Mon, Nov 23, 2009 at 14:45, Robert Olsson <robert@herjulf.net> wrote:
>
> Here are basic support to bring Diagnostic Monitoring Interface Monitoring (DOM)
> to Linux this is more or less mandatory when building optical networks.
>
> Optical modules as SFP, SFP+, XFP, GBIC etc holds transceiver and link diagnostic
> data needed to monitor and troubleshoot optical links, Talks to networks cards
> via the I2C-bus (DOM lives in memory page 0xA2).
>
> In essential:
>
> Usage example: ethtool -D eth5
>
> Ext-Calbr: Avr RX-Power: Alarm & Warn: RX_LOS: Wavelength: 1310 nm
> Alarms, warnings in beginning of line, Ie. AH = Alarm High, WL == Warn Low etc
> Temp: 35.9 C Thresh: Lo: -12.0/-8.0 Hi: 103.0/110.0 C
> Vcc: 3.33 V Thresh: Lo: 3.0/3.0 Hi: 3.7/4.0 V
> Tx-Bias: 13.4 mA Thresh: Lo: 2.0/4.0 Hi: 70.0/84.0 mA
> ALWL TX-pwr: -5.9 dBm ( 0.26 mW) Thresh: Lo: -4.0/-2.0 Hi: 7.0/8.2 dBm
> AHWH RX-pwr: -5.0 dBm ( 0.31 mW) Thresh: Lo: -35.2/-28.0 Hi: -8.2/-6.0 dBm
>
> Read more in Documentation/networking/dom.txt
>
> It's tested with the igb driver, there is also a patch for the ixgbe driver but I
> haven't any SFP+ with DOM support yet.
>
>
> There are room for improvements an clean-ups.
>
> Cheers
> --ro
>
Robert, to help get more eyes on this I have added it to my tree for
internal testing and review.
--
Cheers,
Jeff
^ permalink raw reply
* Re: linux-next: manual merge of the net tree with the net-current tree
From: Jeff Kirsher @ 2009-11-25 7:52 UTC (permalink / raw)
To: Stephen Rothwell
Cc: David Miller, netdev, linux-next, linux-kernel, Bruce Allan
In-Reply-To: <20091124141122.63e81c55.sfr@canb.auug.org.au>
On Mon, Nov 23, 2009 at 19:11, Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> Hi all,
>
> Today's linux-next merge of the net tree got a conflict in
> drivers/net/e1000e/ich8lan.c between commit
> 818f33313caab9be2a10458500dbed4a88c1b334 ("e1000e: do not initiate
> autonegotiation during OEM configuration") from the net-current tree and
> commit 94d8186a693284344ee5cb9734086c7a2370241a ("e1000e: cleanup ops
> function pointers") from the net tree.
>
> Just context changes. I fixed it up (see below) and can carry the fix for
> a while.
> --
> Cheers,
> Stephen Rothwell sfr@canb.auug.org.au
>
I am checking your merge changes to e1000e now, sorry for the delayed response.
--
Cheers,
Jeff
^ permalink raw reply
* [PATCH] net: convert /proc/net/rt_acct to seq_file
From: Alexey Dobriyan @ 2009-11-25 7:45 UTC (permalink / raw)
To: davem; +Cc: netdev
Rewrite statistics accumulation to be in terms of structure fields,
not raw u32 additions. Keep them in same order, though.
This is the last user of create_proc_read_entry() in net/,
please NAK all new ones as well as all new ->write_proc, ->read_proc and
create_proc_entry() users. Cc me if there are problems. :-)
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/ipv4/route.c | 68 ++++++++++++++++++++++++++-----------------------------
1 file changed, 33 insertions(+), 35 deletions(-)
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -513,43 +513,42 @@ static const struct file_operations rt_cpu_seq_fops = {
};
#ifdef CONFIG_NET_CLS_ROUTE
-static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
-{
- unsigned int i;
-
- if ((offset & 3) || (length & 3))
- return -EIO;
-
- if (offset >= sizeof(struct ip_rt_acct) * 256) {
- *eof = 1;
- return 0;
- }
-
- if (offset + length >= sizeof(struct ip_rt_acct) * 256) {
- length = sizeof(struct ip_rt_acct) * 256 - offset;
- *eof = 1;
+static int rt_acct_proc_show(struct seq_file *m, void *v)
+{
+ struct ip_rt_acct *dst, *src;
+ unsigned int i, j;
+
+ dst = kcalloc(256, sizeof(struct ip_rt_acct), GFP_KERNEL);
+ if (!dst)
+ return -ENOMEM;
+
+ for_each_possible_cpu(i) {
+ src = (struct ip_rt_acct *)per_cpu_ptr(ip_rt_acct, i);
+ for (j = 0; j < 256; j++) {
+ dst[j].o_bytes += src[j].o_bytes;
+ dst[j].o_packets += src[j].o_packets;
+ dst[j].i_bytes += src[j].i_bytes;
+ dst[j].i_packets += src[j].i_packets;
+ }
}
- offset /= sizeof(u32);
-
- if (length > 0) {
- u32 *dst = (u32 *) buffer;
-
- *start = buffer;
- memset(dst, 0, length);
-
- for_each_possible_cpu(i) {
- unsigned int j;
- u32 *src;
+ seq_write(m, dst, 256 * sizeof(struct ip_rt_acct));
+ kfree(dst);
+ return 0;
+}
- src = ((u32 *) per_cpu_ptr(ip_rt_acct, i)) + offset;
- for (j = 0; j < length/4; j++)
- dst[j] += src[j];
- }
- }
- return length;
+static int rt_acct_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rt_acct_proc_show, NULL);
}
+
+static const struct file_operations rt_acct_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = rt_acct_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif
static int __net_init ip_rt_do_proc_init(struct net *net)
@@ -567,8 +566,7 @@ static int __net_init ip_rt_do_proc_init(struct net *net)
goto err2;
#ifdef CONFIG_NET_CLS_ROUTE
- pde = create_proc_read_entry("rt_acct", 0, net->proc_net,
- ip_rt_acct_read, NULL);
+ pde = proc_create("rt_acct", 0, net->proc_net, &rt_acct_proc_fops);
if (!pde)
goto err3;
#endif
^ permalink raw reply
* Re: [rfc 1/3 v2] [E1000-devel] [rfc 1/4] igb: Add igb_cleanup_vf()
From: Jeff Kirsher @ 2009-11-25 7:40 UTC (permalink / raw)
To: Simon Horman; +Cc: e1000-devel, netdev, Arnd Bergmann, Alexander Duyck
In-Reply-To: <20091125063530.796967189@vergenet.net>
On Tue, Nov 24, 2009 at 22:32, Simon Horman <horms@verge.net.au> wrote:
> Move virtual finction cleanup code into igb_cleanup_vf() and for the sake
> of symmetry rename igb_probe_vfs() as igb_init_vf().
>
> Although these functions aren't entirely symmetrical it should aid
> maintenance by making the relationship between initialisation and cleanup
> more obvious.
>
> Note that there appears to be no way for adapter->vfs_allocated_count to be
> non-zero for the case where CONFIG_PCI_IOV is not set, so reseting this
> value was moved to inside the relvant #ifdef.
>
> Signed-off-by: Simon Horman <horms@verge.net.au>
>
> ---
> Thu, 05 Nov 2009 11:58:48 +1100
> * Initial post
>
> Wed, 25 Nov 2009 15:43:45 +1100
> * Actually remove adapter->vfs_allocated_count = 0 from outside of
> igb_cleanup_vf()
> * Up-port to current net-next
Thanks Simon and congrats on the new addition! I have added this
three patch series to my tree for review and testing.
--
Cheers,
Jeff
^ permalink raw reply
* Re: [PATCH v2 0/7] via-velocity performance fixes
From: Simon Kagstrom @ 2009-11-25 7:39 UTC (permalink / raw)
To: David Miller; +Cc: netdev, davej, shemminger, romieu
In-Reply-To: <20091124.121339.226248026.davem@davemloft.net>
On Tue, 24 Nov 2009 12:13:39 -0800 (PST)
David Miller <davem@davemloft.net> wrote:
> Simon I'm still waiting for you to fix the transmit function return
> value problems I pointed out in patch #5.
>
> Please get to this so I can apply your patches.
Sorry, I missed that comment. I only subscribed to netdev after having
sent out the patches, so I didn't get that reply. I've looked it up now
(and I'm subscribed now!), so I'll send out a new version.
Thanks,
// Simon
^ permalink raw reply
* Re: [PATCH net-next-2.6] ixgbe: Fix TX stats accounting
From: Jeff Kirsher @ 2009-11-25 7:38 UTC (permalink / raw)
To: Eric Dumazet
Cc: Peter P Waskiewicz Jr, robert@herjulf.net, Jesper Dangaard Brouer,
Linux Netdev List, David S. Miller
In-Reply-To: <4B0BDE3E.2020406@gmail.com>
On Tue, Nov 24, 2009 at 05:23, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Here is an updated version, because ixgbe_get_ethtool_stats()
> needs to call dev_get_stats() or "ethtool -S" wont give
> correct tx_bytes/tx_packets values.
>
> [PATCH net-next-2.6] ixgbe: Fix TX stats accounting
>
> Several cpus can update netdev->stats.tx_bytes & netdev->stats.tx_packets
> in parallel. In this case, TX stats are under estimated and false sharing
> takes place.
>
> After a pktgen session sending exactly 200000000 packets :
> # ifconfig fiber0 | grep TX
> TX packets:198501982 errors:0 dropped:0 overruns:0 carrier:0
>
>
> Multi queue devices should instead use txq->tx_bytes & txq->tx_packets
> in their xmit() method (appropriate txq lock already held by caller, no
> cache line miss), or use appropriate locking.
>
> After patch, same pktgen session gives :
>
> # ifconfig fiber0 | grep TX
> TX packets:200000000 errors:0 dropped:0 overruns:0 carrier:0
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> ---
> drivers/net/ixgbe/ixgbe_ethtool.c | 1 +
> drivers/net/ixgbe/ixgbe_main.c | 20 ++++----------------
> 2 files changed, 5 insertions(+), 16 deletions(-)
>
Thanks Eric. I have added the patch to my tree for testing and review.
--
Cheers,
Jeff
^ permalink raw reply
* [rfc 3/3 v2] [E1000-devel] [rfc 4/4] igb: expose 82576 bandiwidth allocation
From: Simon Horman @ 2009-11-25 6:32 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091125063213.203372240@vergenet.net>
[-- Attachment #1: igb-expose-82576-bandwidth-allocation-2.patch --]
[-- Type: text/plain, Size: 12266 bytes --]
The 82576 has support for bandwidth allocation to VFs.
Contrary to the documentation in the 82576 datasheet v2.41 this
appears to work as follows:
* The ratio supplied is always proportional to 1Gbit/s,
regardless of if the link speed.
* The ratio supplied is an upper-bound on bandwidth available
to the VF, not a minimun guarantee
This patch exposes bandwidth control to userspace through a simple
per-device (PF) sysfs file, bandwidth_allocation.
* The file contains a whitespace delimited list of values, one per VF.
* The first value corresponds to the first VF and so on.
* Valid values are integers from 0 to 1000
* A value of 0 indicates that bandwidth_allocation is disabled.
* Other values indicate the allocated bandwidth, in 1/1000ths of a gigabit/s
e.g. The following for a PF with 4 VFs allocates ~20Mbits/ to VF 1,
~100Mbit/s to VF 2, and leave the other 2 VFs with no allocation.
echo "20 100 0 0" > /sys/class/net/eth3/device/bandwidth_allocation
This interface is intended to allow testing of the hardware feature.
There are ongoing discussions about how to expose this feature
to user-space in a more generic way.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:51 +1100
* Initial post
Wed, 25 Nov 2009 16:58:23 +1100
* Refresh for changes to proceeding patches in series
* Up-port to latest net-next
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-25 17:05:44.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-25 17:06:51.000000000 +1100
@@ -47,6 +47,9 @@
#ifdef CONFIG_IGB_DCA
#include <linux/dca.h>
#endif
+#ifdef CONFIG_PCI_IOV
+#include <linux/ctype.h>
+#endif
#include "igb.h"
#define DRV_VERSION "2.1.0-k2"
@@ -157,6 +160,15 @@ static unsigned int max_vfs = 0;
module_param(max_vfs, uint, 0);
MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
"per physical function");
+
+static ssize_t igb_set_bandwidth_allocation(struct device *,
+ struct device_attribute *,
+ const char *, size_t);
+static ssize_t igb_show_bandwidth_allocation(struct device *,
+ struct device_attribute *,
+ char *);
+DEVICE_ATTR(bandwidth_allocation, S_IRUGO | S_IWUSR,
+ igb_show_bandwidth_allocation, igb_set_bandwidth_allocation);
#endif /* CONFIG_PCI_IOV */
static pci_ers_result_t igb_io_error_detected(struct pci_dev *,
@@ -1771,6 +1783,19 @@ static void __devinit igb_init_vf(struct
if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
goto err_free;
+ if (device_create_file(&pdev->dev, &dev_attr_bandwidth_allocation))
+ goto err_sriov;
+
+ adapter->bandwidth_allocation = kcalloc(adapter->vfs_allocated_count,
+ sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!adapter->bandwidth_allocation)
+ goto err_file;
+ memset(adapter->bandwidth_allocation,
+ adapter->vfs_allocated_count * sizeof(unsigned int), 0);
+
+ spin_lock_init(&adapter->bandwidth_allocation_lock);
+
dev_info(&pdev->dev, "%d vfs allocated\n",
adapter->vfs_allocated_count);
for (i = 0; i < adapter->vfs_allocated_count; i++) {
@@ -1779,6 +1804,10 @@ static void __devinit igb_init_vf(struct
}
return;
+err_file:
+ device_remove_file(&pdev->dev, &dev_attr_bandwidth_allocation);
+err_sriov:
+ pci_disable_sriov(pdev);
err_free:
kfree(adapter->vf_data);
err_zero:
@@ -1903,6 +1932,7 @@ static void igb_init_hw_timer(struct igb
static void igb_cleanup_vf(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
+ struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
if (!adapter->vf_data)
@@ -1919,6 +1949,9 @@ static void igb_cleanup_vf(struct igb_ad
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
msleep(100);
dev_info(&adapter->pdev->dev, "IOV Disabled\n");
+
+ device_remove_file(&pdev->dev, &dev_attr_bandwidth_allocation);
+ kfree(adapter->bandwidth_allocation);
#endif
}
@@ -2227,6 +2260,123 @@ void igb_configure_tx_ring(struct igb_ad
wr32(E1000_TXDCTL(reg_idx), txdctl);
}
+#ifdef CONFIG_PCI_IOV
+static void igb_disable_bandwidth_allocation_vf(struct e1000_hw *hw, int vf)
+{
+ wr32(E1000_VMBASEL, vf);
+ wr32(E1000_VMBAC, 0);
+}
+
+static void igb_disable_bandwidth_allocation(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ int i;
+
+ for (i = 0; i < adapter->vfs_allocated_count; i++)
+ igb_disable_bandwidth_allocation_vf(hw, i);
+}
+
+static void igb_enable_bandwidth_allocation_vf(struct e1000_hw *hw, int vf,
+ unsigned int allocation)
+{
+ u32 rq;
+
+ /* Allocation is expressed as 1000ths of link speed [+]
+ *
+ * rq is calcualted as 1 / (allocation / 1000) = 1000 / allocation
+ *
+ * E1000_VMBAC_RF_INT_SHIFT and E1000_VMBAC_RF_MASK are used
+ * to marshal the result into the desired format: 23 bits of
+ * which 14 are to the right of the decimal point.
+ *
+ * [+] According to the the 82576 v2.41 datasheet rq should
+ * be a ratio of the link speed, however, empirically
+ * it appears to always be a ration of to 1Gbit/s,
+ * even when the link is 100Mbit/s.
+ */
+ rq = ((1000 << E1000_VMBAC_RF_INT_SHIFT) / allocation) &
+ E1000_VMBAC_RF_MASK;
+
+ wr32(E1000_VMBASEL, vf);
+ wr32(E1000_VMBAC, rq|E1000_VMBAC_RC_ENA);
+}
+
+static void igb_enable_bandwidth_allocation(struct igb_adapter *adapter)
+{
+ u32 i, reg;
+ struct e1000_hw *hw = &adapter->hw;
+
+ /* Only enable bandwidth_allocation if it has been set
+ * and the link speed is 100Mbit/s or 1Gbit/s */
+ if (!adapter->bandwidth_allocation ||
+ (adapter->link_speed != SPEED_100 &&
+ adapter->link_speed != SPEED_1000)) {
+ igb_disable_bandwidth_allocation(adapter);
+ return;
+ }
+
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ wr32(E1000_VMBASEL, i);
+ if (adapter->bandwidth_allocation[i])
+ igb_enable_bandwidth_allocation_vf(hw, i,
+ adapter->bandwidth_allocation[i]);
+ else
+ igb_disable_bandwidth_allocation_vf(hw, i);
+
+ /* XXX:
+ *
+ * The 82576 datasheet, section 4.5.11.1.5.1 "Configuring Tx
+ * Bandwidth to VMs" states that the desired setting is:
+ * VMBAMMW.MMW_SIZE = 16 * MSS
+ *
+ * But isn't MSS a property of skbs that are using tso
+ * rather than adapters?
+ *
+ * If so, should we use the maximum value here? */
+ /* XXX: Should this go inside or outside the for loop ? */
+ reg = 64 * 16;
+ wr32(E1000_VMBAMMW, reg);
+ }
+}
+#endif
+
+static void igb_check_bandwidth_allocation(struct igb_adapter *adapter)
+{
+#ifdef CONFIG_PCI_IOV
+ u32 vmbacs;
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (!adapter->vf_data)
+ return;
+
+ /* The 82576 datasheet, section 4.5.11.1.5.2 "Link Speed Change
+ * Procedure" describes the sequence below. However the
+ * SPEED_CHG never seems to be set.
+ */
+ vmbacs = rd32(E1000_VMBACS);
+ if (vmbacs & E1000_VMBACS_SPEED_CHG) {
+ /* XXX: Never seem to get here */
+ int err = 0;
+
+ if (vmbacs & E1000_VMBACS_VMBA_SET) {
+ igb_disable_bandwidth_allocation(adapter);
+ err = 1;
+ }
+
+ vmbacs &= ~E1000_VMBACS_SPEED_CHG;
+ wr32(E1000_VMBACS, vmbacs);
+
+ if (err)
+ return;
+ }
+
+ spin_lock(&adapter->bandwidth_allocation_lock);
+ igb_enable_bandwidth_allocation(adapter);
+ spin_unlock(&adapter->bandwidth_allocation_lock);
+#endif
+ return;
+}
+
/**
* igb_configure_tx - Configure transmit Unit after Reset
* @adapter: board private structure
@@ -3111,6 +3261,8 @@ static void igb_watchdog_task(struct wor
break;
}
+ igb_check_bandwidth_allocation(adapter);
+
netif_carrier_on(netdev);
igb_ping_all_vfs(adapter);
@@ -6010,4 +6162,101 @@ static void igb_vmm_control(struct igb_a
}
}
+#ifdef CONFIG_PCI_IOV
+static ssize_t igb_show_bandwidth_allocation(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ if (!adapter->vf_data)
+ return -ENOENT;
+
+ *buf = '\0';
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ if (i > 0)
+ strcat(buf, " ");
+ sprintf(buf + strlen(buf), "%i",
+ adapter->bandwidth_allocation[i]);
+ }
+ strcat(buf, "\n");
+
+ return strlen(buf);
+}
+
+static unsigned long igb_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ const char *orig = cp;
+ unsigned long x;
+
+ while (isspace(*cp))
+ cp++;
+
+ x = simple_strtoul(cp, endp, base);
+ if (cp == *endp)
+ *endp = (char *)orig;
+
+ return x;
+}
+
+static ssize_t igb_set_bandwidth_allocation(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
+ size_t len;
+ ssize_t status = -ENOENT;
+ unsigned int *new, total;
+ unsigned long x;
+ const char *p;
+ char *next_p;
+
+ if (!adapter->vf_data)
+ return -ENOENT;
+
+ len = adapter->vfs_allocated_count * sizeof(unsigned int);
+
+ new = kmalloc(len, GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ p = buf;
+ total = 0;
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ x = igb_strtoul(p, &next_p, 10);
+ if (p == next_p) {
+ dev_err(dev, "not enough values\n");
+ goto err;
+ }
+ if (x > 1000) {
+ dev_err(dev, "value is too large\n");
+ goto err;
+ }
+ new[i] = x;
+ total += x;
+ p = next_p;
+ }
+
+ /* Check for trailing rubbish */
+ igb_strtoul(p, &next_p, 10);
+ if (p != next_p) {
+ dev_err(dev, "trailing rubbish\n");
+ goto err;
+ }
+
+ spin_lock(&adapter->bandwidth_allocation_lock);
+ memcpy(adapter->bandwidth_allocation, new, len);
+ igb_enable_bandwidth_allocation(adapter);
+ spin_unlock(&adapter->bandwidth_allocation_lock);
+
+ status = count;
+err:
+ kfree(new);
+ return status;
+}
+#endif /* CONFIG_PCI_IOV */
/* igb_main.c */
Index: net-next-2.6/drivers/net/igb/e1000_regs.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_regs.h 2009-11-25 16:59:19.000000000 +1100
+++ net-next-2.6/drivers/net/igb/e1000_regs.h 2009-11-25 17:06:51.000000000 +1100
@@ -311,6 +311,16 @@
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
* Filter - RW */
+/* Tx Bandwidth Allocation to VM Registers */
+#define E1000_VMBACS 0x03600 /* VM Bandwidth Allocation
+ * Control & Status - RW */
+#define E1000_VMBAMMW 0x03670 /* VM Bandwidth Allocation
+ * Max Memory Window - RW */
+#define E1000_VMBASEL 0x03604 /* VM Bandwidth Allocation
+ * Select - RW */
+#define E1000_VMBAC 0x03608 /* VM Bandwidth Allocation
+ * Config - RW */
+
#define wr32(reg, value) (writel(value, hw->hw_addr + reg))
#define rd32(reg) (readl(hw->hw_addr + reg))
#define wrfl() ((void)rd32(E1000_STATUS))
Index: net-next-2.6/drivers/net/igb/e1000_defines.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_defines.h 2009-11-25 16:59:18.000000000 +1100
+++ net-next-2.6/drivers/net/igb/e1000_defines.h 2009-11-25 17:06:51.000000000 +1100
@@ -724,4 +724,13 @@
#define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based
on DMA coal */
+/* VM Bandwidth Allocation Control & Status */
+#define E1000_VMBACS_VMBA_SET 0x00001000
+#define E1000_VMBACS_SPEED_CHG 0x80000000
+
+/* VM Bandwidth Allocation Config */
+#define E1000_VMBAC_RF_INT_SHIFT 14
+#define E1000_VMBAC_RF_MASK ((1<<23)-1) /* RF_DEC and RF_INT */
+#define E1000_VMBAC_RC_ENA 0x80000000
+
#endif
Index: net-next-2.6/drivers/net/igb/igb.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb.h 2009-11-25 16:59:19.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb.h 2009-11-25 17:06:51.000000000 +1100
@@ -312,6 +312,10 @@ struct igb_adapter {
unsigned int vfs_allocated_count;
struct vf_data_storage *vf_data;
u32 rss_queues;
+#ifdef CONFIG_PCI_IOV
+ unsigned int *bandwidth_allocation;
+ spinlock_t bandwidth_allocation_lock;
+#endif
};
#define IGB_FLAG_HAS_MSI (1 << 0)
^ permalink raw reply
* [rfc 2/3 v2] [E1000-devel] [rfc 3/4] igb: Common error path in igb_init_vfs()
From: Simon Horman @ 2009-11-25 6:32 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091125063213.203372240@vergenet.net>
[-- Attachment #1: igb-common-error-path-in-igb_init_vfs.2.patch --]
[-- Type: text/plain, Size: 2968 bytes --]
Drop out into an error path on error.
This is a bit superfluous as things stand, though arguably
it already makes the code cleaner. But it should help things a lot
if igb_init_vfs() has a several things to unwind on error.
This patch eliminates resetting adapter->vfs_allocated_count to 0
in the case where CONFIG_PCI_IOV is not set, because in that
case adapter->vfs_allocated_count can never be non-zero.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:50 +1100
* Initial post
Wed, 25 Nov 2009 16:44:15 +1100
* Merged with " Initialise adapter->vfs_allocated_count in igb_init_vf()",
however the initialisation of adapter->vfs_allocated_count is no
longer moved into igb_init_vf() as doing so results in a panic.
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-25 17:05:43.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-25 17:05:44.000000000 +1100
@@ -1753,38 +1753,37 @@ static void __devinit igb_init_vf(struct
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
+ unsigned char mac_addr[ETH_ALEN];
+ int i;
if (adapter->vfs_allocated_count > 7)
adapter->vfs_allocated_count = 7;
- if (adapter->vfs_allocated_count) {
- adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
- sizeof(struct vf_data_storage),
- GFP_KERNEL);
- /* if allocation failed then we do not support SR-IOV */
- if (!adapter->vf_data) {
- adapter->vfs_allocated_count = 0;
- dev_err(&pdev->dev, "Unable to allocate memory for VF "
- "Data Storage\n");
- }
+ adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
+ sizeof(struct vf_data_storage), GFP_KERNEL);
+ /* if allocation failed then we do not support SR-IOV */
+ if (!adapter->vf_data) {
+ dev_err(&pdev->dev, "Unable to allocate memory for VF "
+ "Data Storage\n");
+ goto err_zero;
}
- if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
-#endif /* CONFIG_PCI_IOV */
- adapter->vfs_allocated_count = 0;
-#ifdef CONFIG_PCI_IOV
- } else {
- unsigned char mac_addr[ETH_ALEN];
- int i;
- dev_info(&pdev->dev, "%d vfs allocated\n",
- adapter->vfs_allocated_count);
- for (i = 0; i < adapter->vfs_allocated_count; i++) {
- random_ether_addr(mac_addr);
- igb_set_vf_mac(adapter, i, mac_addr);
- }
+ if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
+ goto err_free;
+
+ dev_info(&pdev->dev, "%d vfs allocated\n",
+ adapter->vfs_allocated_count);
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ random_ether_addr(mac_addr);
+ igb_set_vf_mac(adapter, i, mac_addr);
}
+
+ return;
+err_free:
+ kfree(adapter->vf_data);
+err_zero:
+ adapter->vf_data = NULL;
+ adapter->vfs_allocated_count = 0;
#endif /* CONFIG_PCI_IOV */
}
^ permalink raw reply
* [rfc 1/3 v2] [E1000-devel] [rfc 1/4] igb: Add igb_cleanup_vf()
From: Simon Horman @ 2009-11-25 6:32 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091125063213.203372240@vergenet.net>
[-- Attachment #1: igb-add-igb_cleanup-vf.patch --]
[-- Type: text/plain, Size: 4087 bytes --]
Move virtual finction cleanup code into igb_cleanup_vf() and for the sake
of symmetry rename igb_probe_vfs() as igb_init_vf().
Although these functions aren't entirely symmetrical it should aid
maintenance by making the relationship between initialisation and cleanup
more obvious.
Note that there appears to be no way for adapter->vfs_allocated_count to be
non-zero for the case where CONFIG_PCI_IOV is not set, so reseting this
value was moved to inside the relvant #ifdef.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:48 +1100
* Initial post
Wed, 25 Nov 2009 15:43:45 +1100
* Actually remove adapter->vfs_allocated_count = 0 from outside of
igb_cleanup_vf()
* Up-port to current net-next
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-25 16:59:19.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-25 17:05:03.000000000 +1100
@@ -92,6 +92,7 @@ void igb_update_stats(struct igb_adapter
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
static int igb_sw_init(struct igb_adapter *);
+static void igb_cleanup_vf(struct igb_adapter * adapter);
static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
static void igb_configure_tx(struct igb_adapter *);
@@ -701,22 +702,7 @@ static void igb_set_interrupt_capability
/* If we can't do MSI-X, try MSI */
msi_only:
-#ifdef CONFIG_PCI_IOV
- /* disable SR-IOV for non MSI-X configurations */
- if (adapter->vf_data) {
- struct e1000_hw *hw = &adapter->hw;
- /* disable iov and allow time for transactions to clear */
- pci_disable_sriov(adapter->pdev);
- msleep(500);
-
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
- wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
- msleep(100);
- dev_info(&adapter->pdev->dev, "IOV Disabled\n");
- }
-#endif
- adapter->vfs_allocated_count = 0;
+ igb_cleanup_vf(adapter);
adapter->rss_queues = 1;
adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
adapter->num_rx_queues = 1;
@@ -1755,7 +1741,7 @@ static void __devexit igb_remove(struct
}
/**
- * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space
+ * igb_init_vf - Initialize vf data storage and add VFs to pci config space
* @adapter: board private structure to initialize
*
* This function initializes the vf specific data storage and then attempts to
@@ -1763,7 +1749,7 @@ static void __devexit igb_remove(struct
* mor expensive time wise to disable SR-IOV than it is to allocate and free
* the memory for the VFs.
**/
-static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+static void __devinit igb_init_vf(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
@@ -1909,6 +1895,35 @@ static void igb_init_hw_timer(struct igb
}
/**
+ * igb_cleanup_vf - Clean up vf data and remove vfs from pci config space
+ * @adapter: board private structure to initialize
+ *
+ * This function cleans-up the vf specific data storage and then attempts to
+ * deallocate the VFs.
+ **/
+static void igb_cleanup_vf(struct igb_adapter * adapter)
+{
+#ifdef CONFIG_PCI_IOV
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (!adapter->vf_data)
+ return;
+
+ /* disable iov and allow time for transactions to clear */
+ pci_disable_sriov(adapter->pdev);
+ msleep(500);
+
+ kfree(adapter->vf_data);
+ adapter->vf_data = NULL;
+ adapter->vfs_allocated_count = 0;
+
+ wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
+ msleep(100);
+ dev_info(&adapter->pdev->dev, "IOV Disabled\n");
+#endif
+}
+
+/**
* igb_sw_init - Initialize general software structures (struct igb_adapter)
* @adapter: board private structure to initialize
*
@@ -1955,7 +1970,7 @@ static int __devinit igb_sw_init(struct
}
igb_init_hw_timer(adapter);
- igb_probe_vfs(adapter);
+ igb_init_vf(adapter);
/* Explicitly disable IRQ since the NIC can be in any state. */
igb_irq_disable(adapter);
^ permalink raw reply
* [rfc 0/3 v2] igb: bandwidth allocation
From: Simon Horman @ 2009-11-25 6:32 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
this series of patches exposes the bandwidth allocation hardware support of
the Intel 82576. It does so through a rather hackish sysfs entry. That
interface is just intended for testing so that the exposed hardware feature
can be exercised. I would like to find a generic way to expose this feature
to user-space.
v2 of the removes patch "Initialise adapter->vfs_allocated_count in
igb_init_vf()" as it causes a panic.
^ permalink raw reply
* Re: [rfc 0/4] igb: bandwidth allocation
From: Simon Horman @ 2009-11-25 6:31 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: e1000-devel, netdev, Alexander Duyck, Arnd Bergmann
In-Reply-To: <9929d2390911140001t2938271ep7455de5874ee0144@mail.gmail.com>
On Sat, Nov 14, 2009 at 12:01:32AM -0800, Jeff Kirsher wrote:
> On Wed, Nov 4, 2009 at 18:21, Simon Horman <horms@verge.net.au> wrote:
> > On Wed, Nov 04, 2009 at 05:46:50PM -0800, Jeff Kirsher wrote:
> >> On Wed, Nov 4, 2009 at 16:58, Simon Horman <horms@verge.net.au> wrote:
> >> > Hi,
> >> >
> >> > this series of patches exposes the bandwidth allocation
> >> > hardware support of the Intel 82576. It does so through
> >> > a rather hackish sysfs entry. That interface is just intended
> >> > for testing so that the exposed hardware feature can
> >> > be exercised. I would like to find a generic way to expose
> >> > this feature to user-space.
> >> >
> >>
> >> Thanks Simon. I have add the 4 patch series to my tree for testing.
> >
> > Thanks. I wanted to get the code out rather than sitting on it
> > for lack of a better user-space interface. Although there
> > is a lot of fluff the actual register twiddling for
> > bandwidth allocation turned out to be quite simple.
> >
>
> Simon -
> After doing some testing on the series of patches, we are getting a
> panic with these patches applied to net-next. I have provided below
> the panic we saw, right now we have a large patch load so a bisect
> will have to wait. Hopefully with time permitting, we will be able to
> revisit these patches soon.
Hi Jeff,
sorry for not getting back to you earlier, I've been caught up with
family matters for the past few weeks (my wife had a baby!).
It seems that the problem was caused by the second patch in the series
moving the initialisation of adapter->vfs_allocated_count.
I will submit a fresh patch series to resolve this and some
other minor problems.
^ permalink raw reply
* Re: dmfe/tulip device id overlap
From: Brandon Philips @ 2009-11-25 4:49 UTC (permalink / raw)
To: Tobias Ringstrom, Grant Grundler, Kyle McMartin, davem; +Cc: netdev
In-Reply-To: <20091125043603.GK14043@jenkins.home.ifup.org>
Adding Tobias and Grant under (hopefully) working email addresses.
Can you please submit patches to update MAINTAINERS with your
preferred email?
On 20:36 Tue 24 Nov 2009, Brandon Philips wrote:
> Hello All-
>
> dmfe and tulip have an overlap of device IDs and it has been discussed
> before without resolution[1][2].
>
> The device ID in particular is:
>
> { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
> { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
>
> Users of Fedora[3] and openSUSE[4] are feeling pain from this but
> Ubuntu users are avoiding the issue do to the patch below.
>
> This patch comes almost directly from the discussion on the
> linux-sparc thread[2]. So, can we merge that patch? Or can one of the
> maintainers come up with a less hacky solution (e.g. fix tulip)?
>
> Cheers,
>
> Brandon
>
> [1] http://www.mail-archive.com/debian-sparc@lists.debian.org/msg21647.html
> [2] http://marc.info/?l=linux-sparc&m=123698905214250&w=2
> [3] https://bugzilla.redhat.com/show_bug.cgi?id=277731
> [4] https://bugzilla.novell.com/show_bug.cgi?id=537016
>
> From: Ben Collins <bcollins@ubuntu.com>
> Date: Wed, 18 Jul 2007 17:48:25 +0000 (-0400)
> Subject: UBUNTU: SAUCE: tulip: Let dmfe handle davicom on non-sparc
> X-Git-Tag: Ubuntu-2.6.31-10.31~680
> X-Git-Url: http://kernel.ubuntu.com/git?p=ubuntu%2Fubuntu-karmic.git;a=commitdiff_plain;h=886595ab493b5c5fcf23b55b3ebf46bfe219a5d0
>
> UBUNTU: SAUCE: tulip: Let dmfe handle davicom on non-sparc
>
> Signed-off-by: Ben Collins <ben.collins@canonical.com>
> ---
>
> diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
> index 4cf9a65..b75f65c 100644
> --- a/drivers/net/tulip/tulip_core.c
> +++ b/drivers/net/tulip/tulip_core.c
> @@ -228,8 +228,12 @@ static struct pci_device_id tulip_pci_tbl[] = {
> { 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
> { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
> { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
> + /* Ubuntu: On non-sparc, this seems to be handled better by the
> + * dmfe driver. */
> +#ifdef __sparc__
> { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
> { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
> +#endif
> { 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
> { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
> { 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
^ permalink raw reply
* [net-next-2.6 PATCH 4/4] ixgbe: Fix Receive Address Register (RAR) cleaning and accounting
From: Jeff Kirsher @ 2009-11-25 4:52 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Shannon Nelson, Peter P Waskiewicz Jr,
Jeff Kirsher
In-Reply-To: <20091125045059.23932.10997.stgit@localhost.localdomain>
From: Shannon Nelson <shannon.nelson@intel.com>
This fixes an issue when clearing out the RAR entries. If RAR[0]
is the only address in use, don't clear the others.
Signed-off-by: Shannon Nelson <shannon.nelson@intel.com>
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_common.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 79533e2..688b8ca 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1382,10 +1382,10 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
hw->addr_ctrl.overflow_promisc = 0;
/* Zero out the other receive addresses */
- hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use);
- for (i = 1; i <= uc_addr_in_use; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+ hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use + 1);
+ for (i = 0; i < uc_addr_in_use; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
}
/* Add the new addresses */
^ permalink raw reply related
* [net-next-2.6 PATCH 3/4] ixgbe: LINKS2 is not a valid register for 82598
From: Jeff Kirsher @ 2009-11-25 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Don Skidmore, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20091125045059.23932.10997.stgit@localhost.localdomain>
From: Don Skidmore <donald.c.skidmore@intel.com>
82598 shouldn't try and access LINKS2 while configuring
link and flow control. This is an 82599-only register.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
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_common.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index f42a954..79533e2 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1755,17 +1755,24 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
/*
* On backplane, bail out if
* - backplane autoneg was not completed, or if
- * - link partner is not AN enabled
+ * - we are 82599 and link partner is not AN enabled
*/
if (hw->phy.media_type == ixgbe_media_type_backplane) {
links = IXGBE_READ_REG(hw, IXGBE_LINKS);
- links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
- if (((links & IXGBE_LINKS_KX_AN_COMP) == 0) ||
- ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)) {
+ if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
hw->fc.fc_was_autonegged = false;
hw->fc.current_mode = hw->fc.requested_mode;
goto out;
}
+
+ if (hw->mac.type == ixgbe_mac_82599EB) {
+ links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+ if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+ }
}
/*
^ permalink raw reply related
* [net-next-2.6 PATCH 2/4] ixgbe: Disable Flow Control for certain devices
From: Jeff Kirsher @ 2009-11-25 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20091125045059.23932.10997.stgit@localhost.localdomain>
From: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
Flow Control autoneg should be disabled for certain adapters
that don't support autonegotiation of Flow Control at 10 gigabit.
These interfaces are the 10GBASE-T devices, CX4, and SFP+, all
running at 10 gigabit only. 1 gigabit is fine.
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_common.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 40ff120..f42a954 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1784,6 +1784,20 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
}
/*
+ * Bail out on
+ * - copper or CX4 adapters
+ * - fiber adapters running at 10gig
+ */
+ if ((hw->phy.media_type == ixgbe_media_type_copper) ||
+ (hw->phy.media_type == ixgbe_media_type_cx4) ||
+ ((hw->phy.media_type == ixgbe_media_type_fiber) &&
+ (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+
+ /*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
^ permalink raw reply related
* [net-next-2.6 PATCH 1/4] ixgbe: handle parameters for tx and rx EITR, no div0
From: Jeff Kirsher @ 2009-11-25 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Jesse Brandeburg, Shannon Nelson, Jeff Kirsher
From: Shannon Nelson <shannon.nelson@intel.com>
The driver was doing a divide by zero when adjusting tx-usecs.
This patch removes the divide by zero code and changes the logic slightly
to ignore tx-usecs in the case of shared TxRx vectors.
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Shannon Nelson <shannon.nelson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_ethtool.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 84ab4db..a5ca289 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1972,6 +1972,10 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
break;
}
+ /* if in mixed tx/rx queues per vector mode, report only rx settings */
+ if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+ return 0;
+
/* only valid if in constant ITR mode */
switch (adapter->tx_itr_setting) {
case 0:
@@ -1997,12 +2001,9 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct ixgbe_q_vector *q_vector;
int i;
- /*
- * don't accept tx specific changes if we've got mixed RxTx vectors
- * test and jump out here if needed before changing the rx numbers
- */
- if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
- adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+ /* 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
+ && ec->tx_coalesce_usecs)
return -EINVAL;
if (ec->tx_max_coalesced_frames_irq)
^ permalink raw reply related
* dmfe/tulip device id overlap
From: Brandon Philips @ 2009-11-25 4:36 UTC (permalink / raw)
To: Tobias Ringstrom, Grant Grundler, Kyle McMartin, davem; +Cc: netdev
Hello All-
dmfe and tulip have an overlap of device IDs and it has been discussed
before without resolution[1][2].
The device ID in particular is:
{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
Users of Fedora[3] and openSUSE[4] are feeling pain from this but
Ubuntu users are avoiding the issue do to the patch below.
This patch comes almost directly from the discussion on the
linux-sparc thread[2]. So, can we merge that patch? Or can one of the
maintainers come up with a less hacky solution (e.g. fix tulip)?
Cheers,
Brandon
[1] http://www.mail-archive.com/debian-sparc@lists.debian.org/msg21647.html
[2] http://marc.info/?l=linux-sparc&m=123698905214250&w=2
[3] https://bugzilla.redhat.com/show_bug.cgi?id=277731
[4] https://bugzilla.novell.com/show_bug.cgi?id=537016
From: Ben Collins <bcollins@ubuntu.com>
Date: Wed, 18 Jul 2007 17:48:25 +0000 (-0400)
Subject: UBUNTU: SAUCE: tulip: Let dmfe handle davicom on non-sparc
X-Git-Tag: Ubuntu-2.6.31-10.31~680
X-Git-Url: http://kernel.ubuntu.com/git?p=ubuntu%2Fubuntu-karmic.git;a=commitdiff_plain;h=886595ab493b5c5fcf23b55b3ebf46bfe219a5d0
UBUNTU: SAUCE: tulip: Let dmfe handle davicom on non-sparc
Signed-off-by: Ben Collins <ben.collins@canonical.com>
---
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 4cf9a65..b75f65c 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -228,8 +228,12 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
{ 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
+ /* Ubuntu: On non-sparc, this seems to be handled better by the
+ * dmfe driver. */
+#ifdef __sparc__
{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
+#endif
{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
^ permalink raw reply related
* Re: [PATCH net-next-2.6] igb and ixgbe: DOM support cleanups
From: Joe Perches @ 2009-11-25 4:30 UTC (permalink / raw)
To: robert; +Cc: David Miller, netdev
In-Reply-To: <1259121454.29779.17.camel@Joe-Laptop.home>
On Tue, 2009-11-24 at 19:57 -0800, Joe Perches wrote:
> + if (eo & DOM_EO_AW) {
> + for (i = 0; i < ARRAY_SIZE(basic); i++) {
> + res = read_phy_diag(hw, 0x1, aw[i].reg,
> + (u16 *)((char *)pd + aw[i].offset));
> + if (res)
> + goto out;
> + }
[]
> + if (eo & DOM_EO_AW) {
> + for (i = 0; i < ARRAY_SIZE(basic); i++) {
> + res = read_phy_diag(hw, 0x1, aw[i].reg,
> + (u16 *)((char *)pd + aw[i].offset));
> + if (res)
> + goto out;
> + }
> + }
Rotten patches. These should be ARRAY_SIZE(aw).
^ permalink raw reply
* TCP sockets stalling - help! (long)
From: Asdo @ 2009-11-25 4:25 UTC (permalink / raw)
To: netdev, e1000-devel
Hi netdev and e1000 people,
I have a weird problem here.
We have a Linux "Storage" server acting as a Samba, SCP and SFTP
fileserver. All clients are Windows: XP and Vista, 32 and 64 bits. The
building has gigabit network. We transfer up to many TB at a time.
I have tried from many clients to the same Server and there is always
the same problem: after hours that a transfer is running the TCP socket
suddenly stalls: 0 bytes/sec. It doesn't slow down, it stalls suddenly.
It never disconnects though.
From that moment onward, the TCP socket stays in a stalling condition
forever (I saw myself at least 10 hours) and both sides see it
Established forever. This is in case of no other networking activity on
the same network card.
In case of other networking activity someone told me that he did see the
transfer restart (=continue) by itself (it was an SFTP that time). I
think I saw this phenomenon myself once during the tcpdump at the bottom
of this email.
This problem happens on every protocol (Samba, SCP, SFTP) and apparently
any client (for sure I tested on at least 1 Vista 64bit and 1 XP 32bit).
Also happens in the middle of transferring one file, so not necessarily
at file change. The files are being pushed from the clients to the linux
Server.
The gigabit switch between the machines was changed 2 times (the brands
also were different) without results.
I was able to obtain apparently reliable nonstop transfer if I performed
6 simultaneous transfers with Samba from the same client to the same
server. OTOH with just 1 - 3 simultaneous transfers only all of them
will eventually stall. Note that with 2 transfers the speed of each one
is already smaller than the speed of a single transfer (approx
40+40MB/sec vs 60MB/sec) however with 6 transfers it's obviously much
smaller (approx 6x12MB/sec). The bug looks like some kind of a race
condition to me.
On Samba another strange fact is that if there are multiple transfers
(i.e. 2) from the same client to the same server (please note that in
this case with Samba all transfers pass through the same TCP socket) the
two transfers stall *independently* one to the other. First after a
random time you see one stalling, and eventually after another random
time also the other one stalls. This tells that the socket actually
kinda works... I can even stop one stalled transfer from the client (the
stop operation *works* and gets a reply from the Samba server: I see
messages sniffing the Ethernet), and start it again and it would run,
and the TCP socket is always the same when I restart the transfer.
I obtained apparently reliable transfers with Samba if I introduced rate
limiting on our SMC 8024L2 gigabit switch . Even if the rate limiting
was set so high (930Mbps) that the transfer speed was actually not
influenced, the Samba transfer (1 single transfer, not multiple)
apparently worked reliably. Maybe this helps with the race condition by
separating packets better. The SFTP protocol hanged anyway though, even
on rate limiting, however consider that SFTP from windows goes very slow
at 15Mbps due to a problem of encryption performance of WinSCP, so that
one is really way lower than the rate limit and its packets might not
get separated.
The server is a linux Ubuntu 9.10 with kernel ubuntu 2.6.31-14-server .
The ethernets are two integrated Intels (I tested both ethernet ports):
Ethernet controller: Intel Corporation 80003ES2LAN Gigabit Ethernet
Controller (Copper) (rev 01)
the driver is kernel's e1000
This is the stack trace of server processes (Server side) during an SFTP
stall:
root 327 [CUT] \_ sshd: myuser [priv]
1011 380 [CUT] \_ sshd: myuser
1011 382 [CUT] \_ /usr/lib/openssh/sftp-server
root@mystorage:/proc# cat /proc/327/stack (this is sshd)
[<ffffffff814b428a>] unix_stream_data_wait+0xaa/0x110
[<ffffffff814b50cd>] unix_stream_recvmsg+0x36d/0x570
[<ffffffff81426399>] sock_aio_read+0x149/0x150
[<ffffffff8111e232>] do_sync_read+0xf2/0x130
[<ffffffff8111e8e1>] vfs_read+0x181/0x1a0
[<ffffffff8111edec>] sys_read+0x4c/0x80
[<ffffffff81011fc2>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
root@mystorage:/proc# cat /proc/380/stack (this is the second sshd)
[<ffffffff8112e644>] poll_schedule_timeout+0x34/0x50
[<ffffffff8112ef4f>] do_select+0x58f/0x6b0
[<ffffffff8112f8b5>] core_sys_select+0x185/0x2b0
[<ffffffff8112fc32>] sys_select+0x42/0x110
[<ffffffff81011fc2>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
root@mystorage:/proc# cat /proc/382/stack (this is sftp-server)
[<ffffffff8112e644>] poll_schedule_timeout+0x34/0x50
[<ffffffff8112ef4f>] do_select+0x58f/0x6b0
[<ffffffff8112f8b5>] core_sys_select+0x185/0x2b0
[<ffffffff8112fc32>] sys_select+0x42/0x110
[<ffffffff81011fc2>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
so everything seems normal, it just seems the socket is waiting for data...
I am really puzzled because... I don't know how the Samba protocol
works, but for SFTP which I believe is a simple protocol, I believe the
client is just pushing raw bytes onto a simple TCP socket so it should
keep doing that while it receives Acks. OTOH if it does not receive Acks
the socket would disconnect. However in my case during a stall the
socket stays Established (I checked at BOTH sides!) but the client stops
pushing bytes to the server. (That's for a stall in the middle of a file
on SFTP protocol, which *does* happen) How on earth can that be??
(update: see tcpdump below, it might explain)
I am also thinking at a hardware problem. The server is running on a
Tyan mainboard S5396WA2NRF and we had another problem with this computer
(mobo?), apparently hardware related, with 3ware disk controllers, same
problem as this guy also running another Tyan:
http://www.webhostingtalk.com/archive/index.php/t-449670.html
which I thought might be reconducible to a lost interrupt. Even on a
lost interrupt I can't understand how to solve the Ack puzzle... this is
not a TOE network card!
This is what I did try up to now (and didn't help):
Changed some Samba parameters trying various values (clearly not useful
for SFTP btw). I ended up with a pretty common configuration, which
anyway didn't help:
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=8192
SO_SNDBUF=8192
read raw = yes
write raw = yes
kernel oplocks = yes
max xmit = 2048
getwd cache = yes
Changed the following parameters in /proc/sys/net:
1 -> 0 > ipv6/bindv6only (for Samba but it was bound already and I
couldn't reboot. SFTP tests were done in IPv4 though)
1 -> 0 > tcp_sack
1 -> 0 > tcp_dsack
0 -> 1 > tcp_low_latency
2 -> 0 > tcp_frto
cubic -> reno > tcp_congestion_control
3 -> 6 > tcp_retries1
3 -> 10 > tcp_tso_win_divisor
1 -> 0 > tcp_slow_start_after_idle
Then I disabled the following offloads using ethtool:
rx-checksumming on --> off
tx-checksumming on --> off
scatter-gather on --> off
tcp-segmentation-offload: on --> off
generic-segmentation-offload: on --> off
Nothing helped.
This is the SFTP socket when it's running (Server side):
# cat /proc/net/tcp
2: 0F12A8C0:0016 2612A8C0:C0C6 01 00000000:00000000 02:000AB698
00000000 0 0 267816 4 ffff88084b1e6180 24 4 1 11 -1
Later on, when it has been stuck for a while:
# cat /proc/net/tcp
2: 0F12A8C0:0016 2612A8C0:C0C6 01 00000000:00000000 02:0002AC6B
00000000 0 0 267816 2 ffff88084b1e6180 27 4 1 21 -1
(numbers reference:
http://www.mjmwired.net/kernel/Documentation/networking/proc_net_tcp.txt )
as you can see from the last values, the timeout and window have
enlarged a bit, but nothing dramatic. Apparently they are very similar.
This is another SFTP stall after I disabled the offloading via ethtool:
(different transfer, different socket from above)
2: 0F12A8C0:0016 2512A8C0:09BC 01 00000000:00000000 02:000602F4
00000000 0 0 5301100 2 ffff88084ac02080 28 4 0 13 -1
so the values are similar again, apart the ack.pingpong which has become
0 (something to do with offloading?)
This night I decided to actually tcpdump some traffic at the server
side. This dump has a chance of being incorrect/misleading because the
client I could use was already transferring other stuff to the server
via Samba. I used SFTP protocol for this test but due to the
simultaneous Samba transfer I could not obtain a long SFTP hangup. The
longest hangup I obtained is 1 minute. I hope this is really a
manifestation of the bug in question, and not a simple temporary
starvation at server side.
Here is the relevant excerpt:
00:54:36.303031 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 12309129:12309229, ack 997119732, win 65535, length 100
00:54:36.303216 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 997119732:997120040, ack 12309229, win 64871, length 308
00:54:36.303450 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 12309229:12309297, ack 997120040, win 65535, length 68
00:54:36.303566 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 997120040:997120228, ack 12309297, win 64803, length 188
00:54:36.303645 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 12309297:12309365, ack 997120228, win 65535, length 68
00:54:36.304414 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 997120228:997120432, ack 12309365, win 64735, length 204
00:54:36.345583 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
997120432, win 65535, length 0 *** PROBLEM IS HERE ***
00:55:27.171687 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 12309365:12309425, ack 997120432, win 65535, length 60
00:55:27.342682 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 997120432:997120944, ack 12309425, win 64675, length 512
00:55:27.342726 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
997120944, win 65535, length 0
00:55:27.342775 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [.], seq
997120944:997122404, ack 12309425, win 64675, length 1460
00:55:27.342787 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
997122404, win 65535, length 0
00:55:27.342792 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 997122404:997122612, ack 12309425, win 64675, length 208
00:55:27.342795 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
997122612, win 65535, length 0
It seems to me the TCP stack at the Server returns an ack to the client
but waits 1 minutes before being able to give the further 60 bytes to
the client (these are application-generated bytes, right?) which are
probably needed at client-side for the functioning of the SFTP protocol.
I suspect the SFTP-server application receives the last client data just
at the end of the minute of delay (at 00:55:27.1something)
Probably if the dump was made without concomitant Samba activity, the
sftp-server application would have never received such last client bytes
and that's why the hangup lasts forever.
However the TCP socket remains established because the TCP stack works
and acks are sent properly
Could this be a good interpretation of the bug?
I don't know what are those 60 bytes though, can you confirm is it a
part of the SFTP or SSH protocol?
I observed other similar micro-hangups:
...
00:50:59.210115 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
3346661444, win 65535, length 0
00:51:14.137978 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 7757313:7757457, ack 3346661444, win 65535, length 144
...
00:52:02.495785 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 8612969:8613037, ack 3711382248, win 65535, length 68
00:52:02.507752 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 3711382248:3711382452, ack 8613037, win 65399, length 204
00:52:02.545585 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
3711382452, win 65535, length 0
00:52:14.568489 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 8613037:8613097, ack 3711382452, win 65535, length 60
00:52:14.572162 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [P.],
seq 3711382452:3711382964, ack 8613097, win 65339, length 512
00:52:14.572184 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
3711382964, win 65535, length 0
00:52:14.572312 IP 192.168.18.37.3418 > 192.168.18.15.22: Flags [.], seq
3711382964:3711384424, ack 8613097, win 65339, length 1460
...
00:55:30.464957 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
1040635920, win 65535, length 0
00:55:32.230205 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 12410749:12410809, ack 1040635920, win 65535, length 60
...
00:55:54.404027 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
1362376840, win 65535, length 0
00:56:08.349224 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 13157437:13157497, ack 1362376840, win 65535, length 60
...
00:56:28.494333 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [.], ack
1424904580, win 65535, length 0
00:56:31.450352 IP 192.168.18.15.22 > 192.168.18.37.3418: Flags [P.],
seq 13307333:13307393, ack 1424904580, win 65535, length 60
Update: actually I just found a disk performance problem at Server side
so that the disks couldn't go faster than 70MB/sec (stripe_cache_size
was too low and readahead was too low), and I'm thinking if this could
be the reason for indeed triggering the bug: if there was a starvation
of the TCP/IP stack or network card driver at the wrong time (because
i.e. the CPUs are doing something else like accessing the disks), could
that prevent the 60-bytes packet from ever being transmitted...? (in
case of no other incoming ethernet packets which can give the TCPIP or
e1000 driver a second chance to run)
Thanks for your help
Asdo
^ permalink raw reply
* [PATCH net-next-2.6] igb and ixgbe: DOM support cleanups
From: Joe Perches @ 2009-11-25 3:57 UTC (permalink / raw)
To: robert; +Cc: David Miller, netdev
In-Reply-To: <19212.8726.367568.937773@gargle.gargle.HOWL>
On Tue, 2009-11-24 at 19:12 +0100, robert@herjulf.net wrote:
> Joe Perches writes:
> > Can you run ./scripts/checkpatch.pl on your patches please?
> Yes there were many objections... but my linux quantum is for over for now
> > > + if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
> > > + goto out;
> > [etc...]
> > > + if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
> > > + goto out;
> >
> > perhaps this is clearer as:
> >
> > if (read_phy_diag(hw, 0x1, reg, loc) ||
> > read_phy_diag(hw, 0x1, reg2, loc2) ||
> > ...
> > read_phy_diag(hw, 0x1, regN, locN))
> > goto out;
> Feel free to attack it...
Checkpatch cleanup and make code smaller after
git apply --whitespace=fix <your original patches 1-4>
was:
$ size drivers/net/igb/igb_ethtool.o drivers/net/ixgbe/ixgbe_ethtool.o
text data bss dec hex filename
26466 1544 8584 36594 8ef2 drivers/net/igb/igb_ethtool.o
31726 2980 9128 43834 ab3a drivers/net/ixgbe/ixgbe_ethtool.o
is:
$ size drivers/net/igb/igb_ethtool.o drivers/net/ixgbe/ixgbe_ethtool.o
text data bss dec hex filename
24606 1544 8000 34150 8566 drivers/net/igb/igb_ethtool.o
29886 2980 8552 41418 a1ca drivers/net/ixgbe/ixgbe_ethtool.o
Signed-off-by: Joe Perches <joe@perches.com>
drivers/net/igb/igb_ethtool.c | 264 +++++++++++++++--------------------
drivers/net/ixgbe/ixgbe_ethtool.c | 280 ++++++++++++++++---------------------
include/linux/ethtool.h | 4 +-
3 files changed, 238 insertions(+), 310 deletions(-)
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 8fa7b98..b96661a 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -2080,8 +2080,9 @@ static s32 read_phy_diag(struct e1000_hw *hw, u8 page, u8 offset,
* PHY to retrieve the desired data.
*/
- i2ccmd = (E1000_I2CCMD_OPCODE_READ) | (page << E1000_I2CCMD_PHY_ADDR_SHIFT) |
- ( offset << E1000_I2CCMD_REG_ADDR_SHIFT);
+ i2ccmd = (E1000_I2CCMD_OPCODE_READ) |
+ (page << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+ (offset << E1000_I2CCMD_REG_ADDR_SHIFT);
wr32(E1000_I2CCMD, i2ccmd);
@@ -2107,186 +2108,147 @@ static s32 read_phy_diag(struct e1000_hw *hw, u8 page, u8 offset,
return 0;
}
+static s32 read_phy_diag_u32(struct e1000_hw *hw, u8 page, u8 offset, u32 *data)
+{
+ u16 p1;
+ u16 p2;
+ u32 res;
+
+ res = read_phy_diag(hw, page, offset, &p1);
+ if (res)
+ goto out;
+
+ res = read_phy_diag(hw, page, offset + 2, &p2);
+ if (res)
+ goto out;
+
+ *data = ((u32)p1) << 16 | p2;
+
+out:
+ return res;
+}
+
+struct reg_offset {
+ int reg;
+ size_t offset;
+};
+
+#define REG_OFFSET(a, b) \
+ { .reg = a, .offset = offsetof(struct ethtool_phy_diag, b) }
+
int igb_get_phy_diag(struct net_device *netdev, struct ethtool_phy_diag *pd)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u16 p1, p2;
int res;
u8 type, eo;
+ int i;
- if((res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type)))
+ static const struct reg_offset basic[] = {
+ REG_OFFSET(DOM_A2_TEMP, temp),
+ REG_OFFSET(DOM_A2_TEMP_SLOPE, temp_slope),
+ REG_OFFSET(DOM_A2_TEMP_OFFSET, temp_offset),
+ REG_OFFSET(DOM_A2_VCC, vcc),
+ REG_OFFSET(DOM_A2_VCC_SLOPE, vcc_slope),
+ REG_OFFSET(DOM_A2_VCC_OFFSET, vcc_offset),
+ REG_OFFSET(DOM_A2_TX_BIAS, tx_bias),
+ REG_OFFSET(DOM_A2_TX_I_SLOPE, tx_bias_slope),
+ REG_OFFSET(DOM_A2_TX_I_OFFSET, tx_bias_offset),
+ REG_OFFSET(DOM_A2_TX_PWR, tx_pwr),
+ REG_OFFSET(DOM_A2_TX_PWR_SLOPE, tx_pwr_slope),
+ REG_OFFSET(DOM_A2_TX_PWR_OFFSET, tx_pwr_offset),
+ REG_OFFSET(DOM_A2_RX_PWR, rx_pwr),
+ };
+
+ static const struct reg_offset power[] = {
+ REG_OFFSET(DOM_A2_RX_PWR_0, rx_pwr_cal[0]),
+ REG_OFFSET(DOM_A2_RX_PWR_1, rx_pwr_cal[1]),
+ REG_OFFSET(DOM_A2_RX_PWR_2, rx_pwr_cal[2]),
+ REG_OFFSET(DOM_A2_RX_PWR_3, rx_pwr_cal[3]),
+ REG_OFFSET(DOM_A2_RX_PWR_4, rx_pwr_cal[4]),
+ };
+
+ static const struct reg_offset aw[] = {
+ REG_OFFSET(DOM_A2_TEMP_AHT, temp_aht),
+ REG_OFFSET(DOM_A2_TEMP_ALT, temp_alt),
+ REG_OFFSET(DOM_A2_TEMP_WHT, temp_wht),
+ REG_OFFSET(DOM_A2_TEMP_WLT, temp_wlt),
+ REG_OFFSET(DOM_A2_VCC_AHT, vcc_aht),
+ REG_OFFSET(DOM_A2_VCC_ALT, vcc_alt),
+ REG_OFFSET(DOM_A2_VCC_WHT, vcc_wht),
+ REG_OFFSET(DOM_A2_VCC_WLT, vcc_wlt),
+ REG_OFFSET(DOM_A2_TX_BIAS_AHT, tx_bias_aht),
+ REG_OFFSET(DOM_A2_TX_BIAS_ALT, tx_bias_alt),
+ REG_OFFSET(DOM_A2_TX_BIAS_WHT, tx_bias_wht),
+ REG_OFFSET(DOM_A2_TX_BIAS_WLT, tx_bias_wlt),
+ REG_OFFSET(DOM_A2_TX_PWR_AHT, tx_pwr_aht),
+ REG_OFFSET(DOM_A2_TX_PWR_ALT, tx_pwr_alt),
+ REG_OFFSET(DOM_A2_TX_PWR_WHT, tx_pwr_wht),
+ REG_OFFSET(DOM_A2_TX_PWR_WLT, tx_pwr_wlt),
+ REG_OFFSET(DOM_A2_RX_PWR_AHT, rx_pwr_aht),
+ REG_OFFSET(DOM_A2_RX_PWR_ALT, rx_pwr_alt),
+ REG_OFFSET(DOM_A2_RX_PWR_WHT, rx_pwr_wht),
+ REG_OFFSET(DOM_A2_RX_PWR_WLT, rx_pwr_wlt),
+ };
+
+ res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type);
+ if (res)
goto out;
- type = pd->type >> 8;
+ type = pd->type >> 8;
- if( ~(type) & DOM_TYPE_DOM || type & DOM_TYPE_LEGAGY_DOM)
+ if ((~(type) & DOM_TYPE_DOM) || (type & DOM_TYPE_LEGAGY_DOM))
goto out;
- if( type& DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
+ if (type & DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
hw_dbg("DOM module not supported (Address change)\n");
goto out;
}
eo = pd->type & 0xFF;
- if((res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength)))
+
+ res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength);
+ if (res)
goto out;
/* If supported. Read alarms and Warnings first*/
- if( eo & DOM_EO_AW) {
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm)))
+ if (eo & DOM_EO_AW) {
+ res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm);
+ if (res)
goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning)))
+ res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning);
+ if (res)
goto out;
}
/* Basic diag */
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP, &pd->temp)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_OFFSET, &pd->temp_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC, &pd->vcc)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_SLOPE, &pd->vcc_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_OFFSET, &pd->vcc_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS, &pd->tx_bias)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_SLOPE, &pd->tx_bias_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR, &pd->tx_pwr)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_SLOPE, &pd->tx_pwr_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_OFFSET, &pd->tx_pwr_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR, &pd->rx_pwr)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[0] = (p1<<16) + p2;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[1] = (p1<<16) + p2;
-
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[2] = (p1<<16) + p2;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[3] = (p1<<16) + p2;
+ for (i = 0; i < ARRAY_SIZE(basic); i++) {
+ res = read_phy_diag(hw, 0x1, basic[i].reg,
+ (u16 *)((char *)pd + basic[i].offset));
+ if (res)
+ goto out;
+ }
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4, &p1)))
- goto out;
+ /* Power */
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[4] = (p1<<16) + p2;
+ for (i = 0; i < ARRAY_SIZE(power); i++) {
+ res = read_phy_diag_u32(hw, 0x1, power[i].reg,
+ (u32 *)((char *)pd + power[i].offset));
+ if (res)
+ goto out;
+ }
/* Thresholds for Alarms and Warnings */
- if( !(eo & DOM_EO_AW))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_AHT, &pd->temp_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_ALT, &pd->temp_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WHT, &pd->temp_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WLT, &pd->temp_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_AHT, &pd->vcc_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_ALT, &pd->vcc_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WHT, &pd->vcc_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WLT, &pd->vcc_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_AHT, &pd->tx_bias_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_ALT, &pd->tx_bias_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WHT, &pd->tx_bias_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WLT, &pd->tx_bias_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_AHT, &pd->tx_pwr_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_ALT, &pd->tx_pwr_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WHT, &pd->tx_pwr_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WLT, &pd->tx_pwr_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_AHT, &pd->rx_pwr_aht)))
- goto out;
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_ALT, &pd->rx_pwr_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WHT, &pd->rx_pwr_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WLT, &pd->rx_pwr_wlt)))
- goto out;
+ if (eo & DOM_EO_AW) {
+ for (i = 0; i < ARRAY_SIZE(basic); i++) {
+ res = read_phy_diag(hw, 0x1, aw[i].reg,
+ (u16 *)((char *)pd + aw[i].offset));
+ if (res)
+ goto out;
+ }
+ }
out:
return res;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 6276e17..322b613 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2108,201 +2108,167 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
}
-static s32 read_phy_diag(struct ixgbe_hw *hw, u8 page, u8 offset,
- u16 *data)
+static s32 read_phy_diag(struct ixgbe_hw *hw, u8 page, u8 offset, u16 *data)
{
- s32 status = 0;
- u8 tmp [2];
+ s32 status;
+ u8 hi, lo;
- status = ixgbe_read_i2c_byte_generic(hw, page, offset, &tmp[0]);
- if(status != 0)
- goto err;
+ status = ixgbe_read_i2c_byte_generic(hw, page, offset, &hi);
+ if (status)
+ goto out;
+
+ status = ixgbe_read_i2c_byte_generic(hw, page, offset, &lo);
+ if (status)
+ goto out;
+
+ *data = (((u16)hi) << 8) | lo;
- status = ixgbe_read_i2c_byte_generic(hw, page, offset, &tmp[1]);
- *data = (tmp[0]<<8) | tmp[1];
-err:
+out:
return status;
}
+static s32 read_phy_diag_u32(struct ixgbe_hw *hw, u8 page, u8 offset, u32 *data)
+{
+ u16 p1;
+ u16 p2;
+ u32 res;
+
+ res = read_phy_diag(hw, page, offset, &p1);
+ if (res)
+ goto out;
+
+ res = read_phy_diag(hw, page, offset + 2, &p2);
+ if (res)
+ goto out;
+
+ *data = ((u32)p1) << 16 | p2;
+
+out:
+ return res;
+}
+
+struct reg_offset {
+ int reg;
+ size_t offset;
+};
+
+#define REG_OFFSET(a, b) \
+ { .reg = a, .offset = offsetof(struct ethtool_phy_diag, b) }
+
int ixgb_get_phy_diag(struct net_device *netdev, struct ethtool_phy_diag *pd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- u16 p1, p2;
int res;
u8 type, eo;
+ int i;
- if((res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type)))
+ static const struct reg_offset basic[] = {
+ REG_OFFSET(DOM_A2_TEMP, temp),
+ REG_OFFSET(DOM_A2_TEMP_SLOPE, temp_slope),
+ REG_OFFSET(DOM_A2_TEMP_OFFSET, temp_offset),
+ REG_OFFSET(DOM_A2_VCC, vcc),
+ REG_OFFSET(DOM_A2_VCC_SLOPE, vcc_slope),
+ REG_OFFSET(DOM_A2_VCC_OFFSET, vcc_offset),
+ REG_OFFSET(DOM_A2_TX_BIAS, tx_bias),
+ REG_OFFSET(DOM_A2_TX_I_SLOPE, tx_bias_slope),
+ REG_OFFSET(DOM_A2_TX_I_OFFSET, tx_bias_offset),
+ REG_OFFSET(DOM_A2_TX_PWR, tx_pwr),
+ REG_OFFSET(DOM_A2_TX_PWR_SLOPE, tx_pwr_slope),
+ REG_OFFSET(DOM_A2_TX_PWR_OFFSET, tx_pwr_offset),
+ REG_OFFSET(DOM_A2_RX_PWR, rx_pwr),
+ };
+
+ static const struct reg_offset power[] = {
+ REG_OFFSET(DOM_A2_RX_PWR_0, rx_pwr_cal[0]),
+ REG_OFFSET(DOM_A2_RX_PWR_1, rx_pwr_cal[1]),
+ REG_OFFSET(DOM_A2_RX_PWR_2, rx_pwr_cal[2]),
+ REG_OFFSET(DOM_A2_RX_PWR_3, rx_pwr_cal[3]),
+ REG_OFFSET(DOM_A2_RX_PWR_4, rx_pwr_cal[4]),
+ };
+
+ static const struct reg_offset aw[] = {
+ REG_OFFSET(DOM_A2_TEMP_AHT, temp_aht),
+ REG_OFFSET(DOM_A2_TEMP_ALT, temp_alt),
+ REG_OFFSET(DOM_A2_TEMP_WHT, temp_wht),
+ REG_OFFSET(DOM_A2_TEMP_WLT, temp_wlt),
+ REG_OFFSET(DOM_A2_VCC_AHT, vcc_aht),
+ REG_OFFSET(DOM_A2_VCC_ALT, vcc_alt),
+ REG_OFFSET(DOM_A2_VCC_WHT, vcc_wht),
+ REG_OFFSET(DOM_A2_VCC_WLT, vcc_wlt),
+ REG_OFFSET(DOM_A2_TX_BIAS_AHT, tx_bias_aht),
+ REG_OFFSET(DOM_A2_TX_BIAS_ALT, tx_bias_alt),
+ REG_OFFSET(DOM_A2_TX_BIAS_WHT, tx_bias_wht),
+ REG_OFFSET(DOM_A2_TX_BIAS_WLT, tx_bias_wlt),
+ REG_OFFSET(DOM_A2_TX_PWR_AHT, tx_pwr_aht),
+ REG_OFFSET(DOM_A2_TX_PWR_ALT, tx_pwr_alt),
+ REG_OFFSET(DOM_A2_TX_PWR_WHT, tx_pwr_wht),
+ REG_OFFSET(DOM_A2_TX_PWR_WLT, tx_pwr_wlt),
+ REG_OFFSET(DOM_A2_RX_PWR_AHT, rx_pwr_aht),
+ REG_OFFSET(DOM_A2_RX_PWR_ALT, rx_pwr_alt),
+ REG_OFFSET(DOM_A2_RX_PWR_WHT, rx_pwr_wht),
+ REG_OFFSET(DOM_A2_RX_PWR_WLT, rx_pwr_wlt),
+ };
+
+ res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type);
+ if (res)
goto out;
- type = pd->type >> 8;
+ type = pd->type >> 8;
- if( ~(type) & DOM_TYPE_DOM || type & DOM_TYPE_LEGAGY_DOM)
+ if ((~(type) & DOM_TYPE_DOM) || (type & DOM_TYPE_LEGAGY_DOM))
goto out;
- if( type& DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
+ if (type & DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
hw_dbg(hw, "DOM module not supported (Address change)\n");
goto out;
}
eo = pd->type & 0xFF;
- if((res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength)))
+
+ res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength);
+ if (res)
goto out;
/* If supported. Read alarms and Warnings first*/
- if( eo & DOM_EO_AW) {
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm)))
+ if (eo & DOM_EO_AW) {
+ res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm);
+ if (res)
goto out;
- if((res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning)))
+ res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning);
+ if (res)
goto out;
}
/* Basic diag */
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP, &pd->temp)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_OFFSET, &pd->temp_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC, &pd->vcc)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_SLOPE, &pd->vcc_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_OFFSET, &pd->vcc_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS, &pd->tx_bias)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_SLOPE, &pd->tx_bias_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR, &pd->tx_pwr)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_SLOPE, &pd->tx_pwr_slope)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_OFFSET, &pd->tx_pwr_offset)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR, &pd->rx_pwr)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[0] = (p1<<16) + p2;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[1] = (p1<<16) + p2;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2+2, &p2)))
- goto out;
-
- pd->rx_pwr_cal[2] = (p1<<16) + p2;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3, &p1)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3+2, &p2)))
- goto out;
- pd->rx_pwr_cal[3] = (p1<<16) + p2;
-
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4, &p1)))
- goto out;
+ for (i = 0; i < ARRAY_SIZE(basic); i++) {
+ res = read_phy_diag(hw, 0x1, basic[i].reg,
+ (u16 *)((char *)pd + basic[i].offset));
+ if (res)
+ goto out;
+ }
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4+2, &p2)))
- goto out;
+ /* Power */
- pd->rx_pwr_cal[4] = (p1<<16) + p2;
+ for (i = 0; i < ARRAY_SIZE(power); i++) {
+ res = read_phy_diag_u32(hw, 0x1, power[i].reg,
+ (u32 *)((char *)pd + power[i].offset));
+ if (res)
+ goto out;
+ }
/* Thresholds for Alarms and Warnings */
- if( !(eo & DOM_EO_AW))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_AHT, &pd->temp_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_ALT, &pd->temp_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WHT, &pd->temp_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WLT, &pd->temp_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_AHT, &pd->vcc_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_ALT, &pd->vcc_alt)))
- goto out;
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WHT, &pd->vcc_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WLT, &pd->vcc_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_AHT, &pd->tx_bias_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_ALT, &pd->tx_bias_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WHT, &pd->tx_bias_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WLT, &pd->tx_bias_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_AHT, &pd->tx_pwr_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_ALT, &pd->tx_pwr_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WHT, &pd->tx_pwr_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WLT, &pd->tx_pwr_wlt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_AHT, &pd->rx_pwr_aht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_ALT, &pd->rx_pwr_alt)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WHT, &pd->rx_pwr_wht)))
- goto out;
-
- if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WLT, &pd->rx_pwr_wlt)))
- goto out;
+ if (eo & DOM_EO_AW) {
+ for (i = 0; i < ARRAY_SIZE(basic); i++) {
+ res = read_phy_diag(hw, 0x1, aw[i].reg,
+ (u16 *)((char *)pd + aw[i].offset));
+ if (res)
+ goto out;
+ }
+ }
out:
return res;
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 9c2f06a..4e45a94 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -546,7 +546,7 @@ struct ethtool_ops {
int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
int (*flash_device)(struct net_device *, struct ethtool_flash *);
int (*reset)(struct net_device *, u32 *);
- int (*get_phy_diag)(struct net_device *, struct ethtool_phy_diag*);
+ int (*get_phy_diag)(struct net_device *, struct ethtool_phy_diag *);
};
#endif /* __KERNEL__ */
@@ -605,7 +605,7 @@ struct ethtool_ops {
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
-#define ETHTOOL_GPHYDIAG 0x00000035 /* Get PHY diagnostics */
+#define ETHTOOL_GPHYDIAG 0x00000035 /* Get PHY diagnostics */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
^ 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