* [PATCH v4 2/2] macvtap: restore vlan header on user read
From: Basil Gor @ 2012-05-04 8:55 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Eric W. Biederman, David S. Miller, netdev
Ethernet vlan header is not on the packet and kept in the skb->vlan_tci
when it comes from lower dev. This patch inserts vlan header in user
buffer during skb copy on user read.
Signed-off-by: Basil Gor <basil.gor@gmail.com>
---
drivers/net/macvtap.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 0427c65..cb8fd50 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -1,5 +1,6 @@
#include <linux/etherdevice.h>
#include <linux/if_macvlan.h>
+#include <linux/if_vlan.h>
#include <linux/interrupt.h>
#include <linux/nsproxy.h>
#include <linux/compat.h>
@@ -759,6 +760,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
struct macvlan_dev *vlan;
int ret;
int vnet_hdr_len = 0;
+ int vlan_offset = 0;
+ int copied;
if (q->flags & IFF_VNET_HDR) {
struct virtio_net_hdr vnet_hdr;
@@ -773,18 +776,48 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
return -EFAULT;
}
+ copied = vnet_hdr_len;
+
+ if (!vlan_tx_tag_present(skb))
+ len = min_t(int, skb->len, len);
+ else {
+ int copy;
+ struct {
+ __be16 h_vlan_proto;
+ __be16 h_vlan_TCI;
+ } veth;
+ veth.h_vlan_proto = htons(ETH_P_8021Q);
+ veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
+
+ vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
+ len = min_t(int, skb->len + VLAN_HLEN, len);
+
+ copy = min_t(int, vlan_offset, len);
+ ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
+ len -= copy;
+ copied += copy;
+ if (ret || !len)
+ goto done;
+
+ copy = min_t(int, sizeof(veth), len);
+ ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
+ len -= copy;
+ copied += copy;
+ if (ret || !len)
+ goto done;
+ }
- len = min_t(int, skb->len, len);
-
- ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len);
+ ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
+ copied += len;
+done:
rcu_read_lock_bh();
vlan = rcu_dereference_bh(q->vlan);
if (vlan)
- macvlan_count_rx(vlan, len, ret == 0, 0);
+ macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
rcu_read_unlock_bh();
- return ret ? ret : (len + vnet_hdr_len);
+ return ret ? ret : copied;
}
static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
--
1.7.6.5
^ permalink raw reply related
* Re: pull request: wireless-next 2012-05-03
From: Arend van Spriel @ 2012-05-04 8:57 UTC (permalink / raw)
To: Joe Perches; +Cc: David Miller, linville, linux-wireless, netdev
In-Reply-To: <1336066186.13866.25.camel@joe2Laptop>
On 05/03/2012 07:29 PM, Joe Perches wrote:
> On Thu, 2012-05-03 at 13:17 -0400, David Miller wrote:
>> ...
>> - if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
>> + if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
>> + hdev->discovery.state == DISCOVERY_FINDING) {
>>
>> Really, we went through this a million times very recently and I'm
>> not pulling anything into my tree that has garbage like this in it.
>
> Perhaps the bluetooth folk can adopt using
>
> scripts/checkpatch.pl --strict
>
> or maybe checkpatch could be changed to use
> --strict on patches in net and drivers/net
> automatically.
When the --strict option was added it made me wonder if that meant we
should add this option in Documentation/SubmittingPatches. I do not see
why the patches for net subsystem should have a different check level.
So why not do --strict by default and get rid of the option flag.
Gr. AvS
^ permalink raw reply
* IP_MULTICAST_IF getsockopt man part
From: Jiri Pirko @ 2012-05-04 9:00 UTC (permalink / raw)
To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
Hi.
<quote>
IP_MULTICAST_IF (since Linux 1.2)
Set the local device for a multicast socket.
Argument is an ip_mreqn or ip_mreq structure
similar to IP_ADD_MEMBERSHIP.
</quote>
That is not true. Setsockopt recognizes only ip_mreqn and in_addr. I
made patch which makes it recognize ip_mreq as well. So that would be
probably ok.
http://patchwork.ozlabs.org/patch/156815/
On the other hand, getsockopt works only with in_addr. That I think is
good behaviour but manpages here needs to be corrected in this way (read
part needs to be added here)
Thanks!
Jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-man" 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
* Re: [PATCH 1/2] cs89x0_platform : Use ioread16/iowrite16 instead of inw/outw
From: Arnd Bergmann @ 2012-05-04 9:05 UTC (permalink / raw)
To: Jaccon Bastiaansen
Cc: netdev, s.hauer, kernel, gfm, festevam, davem, linux-arm-kernel
In-Reply-To: <CAGzjT4cUPuwHQ-46saDWdFjweekWrYt7TTJMsUORGXd8FdLpLQ@mail.gmail.com>
On Thursday 03 May 2012, Jaccon Bastiaansen wrote:
> So if I understand you correctly you would like to have an
> iopart_map() call in the cs89x0_probe() function and use the return
> value of that iopart_map() call as ioaddr parameter of the
> cs89x0_probe1() function. Is this correct? This would make the
> cs89x0_probe() function similar to the cs89x0_platform_probe()
> function where the return value of the ioremap() call is used as
> ioaddr parameter of the cs89x0_probe1() function.
Correct. Currently the code relies on some platforms defining
the inw/outw functions to the same thing as readw/writew, which
is not a correct behaviour. If we change it to always use
ioread16/iowrite16, it will be correct in either case.
> But why do you want to convert the current 16 bit accesses in the
> #else path to 32 bit accesses? Why not using ioread16()/iowrite16()?
Sorry, typo on my side, I meant ioread16/iowrite16.
Arnd
^ permalink raw reply
* Re: pull request: wireless-next 2012-05-03
From: Joe Perches @ 2012-05-04 9:42 UTC (permalink / raw)
To: Arend van Spriel; +Cc: David Miller, linville, linux-wireless, netdev
In-Reply-To: <4FA399E1.5080708@broadcom.com>
On Fri, 2012-05-04 at 10:57 +0200, Arend van Spriel wrote:
> On 05/03/2012 07:29 PM, Joe Perches wrote:
> > On Thu, 2012-05-03 at 13:17 -0400, David Miller wrote:
> >> ...
> >> - if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
> >> + if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
> >> + hdev->discovery.state == DISCOVERY_FINDING) {
> >>
> >> Really, we went through this a million times very recently and I'm
> >> not pulling anything into my tree that has garbage like this in it.
> >
> > Perhaps the bluetooth folk can adopt using
> >
> > scripts/checkpatch.pl --strict
> >
> > or maybe checkpatch could be changed to use
> > --strict on patches in net and drivers/net
> > automatically.
>
> When the --strict option was added it
--strict was added to checkpatch in 2007
to quiet some of the more controversial
output messages.
> So why not do --strict by default and get rid of the option flag.
Some subsystem maintainers would again
complain about checkpatch output verbosity.
Maybe some of the less controversial CHK
tests can be changed to WARN.
Still, who really cares whether or not
multiline indentation is aligned after an
open parenthesis or on a tabstop?
Ted Ts'o had an idea awhile back about
adding .checkpatch config files to every
directory that had specific formatting
wants. That might work too.
https://lkml.org/lkml/2012/3/13/662
^ permalink raw reply
* Re: [PATCH 7/9] net: add skb_orphan_frags to copy aside frags with destructors
From: Michael S. Tsirkin @ 2012-05-04 10:03 UTC (permalink / raw)
To: David Miller; +Cc: ian.campbell, netdev, eric.dumazet
In-Reply-To: <20120504.025433.1474691040952890731.davem@davemloft.net>
On Fri, May 04, 2012 at 02:54:33AM -0400, David Miller wrote:
> From: "Michael S. Tsirkin" <mst@redhat.com>
> Date: Fri, 4 May 2012 00:10:24 +0300
>
> > Hmm we orphan skbs when we loop them back so how about reusing the
> > skb->destructor for this?
>
> That's one possibility.
>
> But I fear we're about to toss Ian into yet another rabbit hole. :-)
>
> Let's try to converge on something quickly as I think integration of
> his work has been delayed enough as-is.
This is more intrusive than I'd like because on
error we need to free the skb, so need
to return error code from orphan, but it does not add
an extra branch since skb_orphan is inline.
So intrusive but should not hurt fast path.
It's weekend here, I'll work on a patch like this
Sunday.
--
MST
^ permalink raw reply
* Re: [Lksctp-developers] Bug: sctp packets are dropped after IPSEC rekeying (route cache issue)
From: Nicolas Dichtel @ 2012-05-04 10:07 UTC (permalink / raw)
To: Vlad Yasevich
Cc: Babu Srinivasan, lksctp-developers, lksctp, netdev,
Kreuzer, Michael (NSN - DE/Ulm)
In-Reply-To: <4C46FD58.9030107@hp.com>
[-- Attachment #1: Type: text/plain, Size: 497 bytes --]
Finally, this patch was never integrated into the mainline. Should I rebase it
on the head?
I've attach the last approved patch.
Here is the original thread:
http://sourceforge.net/mailarchive/message.php?msg_id=25786006
Regards,
Nicolas
Le 21/07/2010 15:59, Vlad Yasevich a écrit :
> On 07/21/2010 04:06 AM, Nicolas Dichtel wrote:
>> Finally, we can use dst_check(). Please, find a new patch enclosed.
>>
>>
>> Regards,
>> Nicolas
>>
>
> I like this one a better. Taken.
>
> Thanks
> -vlad
[-- Attachment #2: 0001-sctp-check-cached-dst-before-using-it.patch --]
[-- Type: text/x-patch, Size: 2498 bytes --]
>From a54926eded11de99a0cfcda45d852d2f6e919b77 Mon Sep 17 00:00:00 2001
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Wed, 21 Jul 2010 09:59:49 +0200
Subject: [PATCH] sctp: check cached dst before using it
dst_check() will take care of SA (and obsolete field), hence
IPsec rekeying scenario is taken into account.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/sctp/sctp.h | 13 +++++++++++++
net/sctp/output.c | 4 +---
net/sctp/transport.c | 17 -----------------
3 files changed, 14 insertions(+), 20 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 65946bc..ab54df3 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -691,4 +691,17 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}
+/* The cookie is always 0 since this is how it's used in the
+ * pmtu code.
+ */
+static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+ if (t->dst && !dst_check(t->dst, 0)) {
+ dst_release(t->dst);
+ t->dst = NULL;
+ }
+
+ return t->dst;
+}
+
#endif /* __net_sctp_h__ */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index a646681..93daf59 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -376,9 +376,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
skb_set_owner_w(nskb, sk);
- /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
- if (!dst || (dst->obsolete > 1)) {
- dst_release(dst);
+ if (!sctp_transport_dst_check(tp)) {
sctp_transport_route(tp, NULL, sctp_sk(sk));
if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
sctp_assoc_sync_pmtu(asoc);
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 132046c..bce3f06 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -222,23 +222,6 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
-/* this is a complete rip-off from __sk_dst_check
- * the cookie is always 0 since this is how it's used in the
- * pmtu code
- */
-static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
-{
- struct dst_entry *dst = t->dst;
-
- if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
- dst_release(t->dst);
- t->dst = NULL;
- return NULL;
- }
-
- return dst;
-}
-
void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
{
struct dst_entry *dst;
--
1.5.4.5
^ permalink raw reply related
* Re: [PATCH 00/16] Swap-over-NBD without deadlocking V9
From: Mel Gorman @ 2012-05-04 10:16 UTC (permalink / raw)
To: David Miller
Cc: akpm, linux-mm, netdev, linux-kernel, neilb, a.p.zijlstra,
michaelc, emunson
In-Reply-To: <20120503.130611.160512784868698446.davem@davemloft.net>
On Thu, May 03, 2012 at 01:06:11PM -0400, David Miller wrote:
> From: Mel Gorman <mgorman@suse.de>
> Date: Thu, 3 May 2012 16:00:48 +0100
>
> > Any of the networking people care to comment?
>
> Post another series with any lingering feedback you've received and
> I'll make sure it gets queued up in patchwork so that it gets properly
> reviewed by us.
>
Will do, thanks a lot. Tests are currently running on a rebased series
and I'll post after a successful completion.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [net-next 0/8][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann
This series of patches contains updates for e1000e and ixgbe.
The e1000e updates the version number and adds support for i217
silicon. The ixgbe patches are cleanups/re-organizations to
the driver.
The following are changes since commit f19250883fe09dd2b6b5f818d84874837948c546:
net/niu: remove one superfluous dma mask check
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master
Alexander Duyck (6):
ixgbe: Track instances of buffer available but no DMA resources
present
ixgbe: Reorder the ring to q_vector mapping to improve performance
ixgbe: Make ixgbe_fc_autoneg return void and always set current_mode
ixgbe: Use __free_pages instead of put_page to release pages
ixgbe: Reorder link flow control functions in ixgbe_common.c
ixgbe: Update link flow control to correctly handle multiple packet
buffer DCB
Bruce Allan (1):
e1000e: initial support for i217
Matthew Vick (1):
e1000e: Update driver version number
drivers/net/ethernet/intel/e1000e/defines.h | 8 +
drivers/net/ethernet/intel/e1000e/e1000.h | 2 +
drivers/net/ethernet/intel/e1000e/ethtool.c | 17 +-
drivers/net/ethernet/intel/e1000e/hw.h | 9 +
drivers/net/ethernet/intel/e1000e/ich8lan.c | 370 +++++++++++-
drivers/net/ethernet/intel/e1000e/netdev.c | 19 +-
drivers/net/ethernet/intel/e1000e/phy.c | 3 +
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 65 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 631 +++++++++-----------
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 4 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c | 13 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 35 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 27 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 +-
14 files changed, 751 insertions(+), 457 deletions(-)
--
1.7.7.6
^ permalink raw reply
* [net-next 1/8] e1000e: Update driver version number
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Matthew Vick, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Matthew Vick <matthew.vick@intel.com>
Version bump to 1.11.3-k.
Signed-off-by: Matthew Vick <matthew.vick@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 9c4576e..c19784c 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -56,7 +56,7 @@
#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.10.6" DRV_EXTRAVERSION
+#define DRV_VERSION "1.11.3" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
--
1.7.7.6
^ permalink raw reply related
* [net-next 2/8] e1000e: initial support for i217
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Bruce Allan, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
i217 is the next-generation LOM that will be available on systems with the
Lynx Point Platform Controller Hub (PCH) chipset from Intel. This patch
provides the initial support for the device.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/defines.h | 8 +
drivers/net/ethernet/intel/e1000e/e1000.h | 2 +
drivers/net/ethernet/intel/e1000e/ethtool.c | 17 +-
drivers/net/ethernet/intel/e1000e/hw.h | 9 +
drivers/net/ethernet/intel/e1000e/ich8lan.c | 370 +++++++++++++++++++++++++--
drivers/net/ethernet/intel/e1000e/netdev.c | 17 +-
drivers/net/ethernet/intel/e1000e/phy.c | 3 +
7 files changed, 398 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index 3a50259..11c4666 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -74,7 +74,9 @@
#define E1000_WUS_BC E1000_WUFC_BC
/* Extended Device Control */
+#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */
#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
+#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000004 /* Force SMBus mode*/
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
@@ -573,6 +575,7 @@
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP 100TX Full Dplx Capable */
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
@@ -739,6 +742,7 @@
#define I82577_E_PHY_ID 0x01540050
#define I82578_E_PHY_ID 0x004DD040
#define I82579_E_PHY_ID 0x01540090
+#define I217_E_PHY_ID 0x015400A0
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
@@ -850,4 +854,8 @@
/* SerDes Control */
#define E1000_GEN_POLL_TIMEOUT 640
+/* FW Semaphore */
+#define E1000_FWSM_WLOCK_MAC_MASK 0x0380
+#define E1000_FWSM_WLOCK_MAC_SHIFT 7
+
#endif /* _E1000_DEFINES_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index c960cf8..6e6fffb 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -206,6 +206,7 @@ enum e1000_boards {
board_ich10lan,
board_pchlan,
board_pch2lan,
+ board_pch_lpt,
};
struct e1000_ps_page {
@@ -528,6 +529,7 @@ extern const struct e1000_info e1000_ich9_info;
extern const struct e1000_info e1000_ich10_info;
extern const struct e1000_info e1000_pch_info;
extern const struct e1000_info e1000_pch2_info;
+extern const struct e1000_info e1000_pch_lpt_info;
extern const struct e1000_info e1000_es2_info;
extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 4f1edd9..d863075 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -773,6 +773,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
u32 i;
u32 toggle;
u32 mask;
+ u32 wlock_mac = 0;
/*
* The status register is Read Only, so a write should fail.
@@ -838,19 +839,31 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
case e1000_ich10lan:
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
mask |= (1 << 18);
break;
default:
break;
}
- for (i = 0; i < mac->rar_entry_count; i++)
+
+ if (mac->type == e1000_pch_lpt)
+ wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >>
+ E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ for (i = 0; i < mac->rar_entry_count; i++) {
+ /* Cannot test write-protected SHRAL[n] registers */
+ if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac)))
+ continue;
+
REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
- mask, 0xFFFFFFFF);
+ mask, 0xFFFFFFFF);
+ }
for (i = 0; i < mac->mta_reg_count; i++)
REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
+
return 0;
}
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 00a0ebb..ed5b409 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -200,6 +200,10 @@ enum e1e_registers {
#define E1000_RA (E1000_RAL(0))
E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */
#define E1000_RAH(_n) (E1000_RAH_BASE + ((_n) * 8))
+ E1000_SHRAL_PCH_LPT_BASE = 0x05408,
+#define E1000_SHRAL_PCH_LPT(_n) (E1000_SHRAL_PCH_LPT_BASE + ((_n) * 8))
+ E1000_SHRAH_PCH_LTP_BASE = 0x0540C,
+#define E1000_SHRAH_PCH_LPT(_n) (E1000_SHRAH_PCH_LTP_BASE + ((_n) * 8))
E1000_SHRAL_BASE = 0x05438, /* Shared Receive Address Low - RW */
#define E1000_SHRAL(_n) (E1000_SHRAL_BASE + ((_n) * 8))
E1000_SHRAH_BASE = 0x0543C, /* Shared Receive Address High - RW */
@@ -406,6 +410,8 @@ enum e1e_registers {
#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
#define E1000_DEV_ID_PCH2_LV_LM 0x1502
#define E1000_DEV_ID_PCH2_LV_V 0x1503
+#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A
+#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B
#define E1000_REVISION_4 4
@@ -426,6 +432,7 @@ enum e1000_mac_type {
e1000_ich10lan,
e1000_pchlan,
e1000_pch2lan,
+ e1000_pch_lpt,
};
enum e1000_media_type {
@@ -463,6 +470,7 @@ enum e1000_phy_type {
e1000_phy_82578,
e1000_phy_82577,
e1000_phy_82579,
+ e1000_phy_i217,
};
enum e1000_bus_width {
@@ -971,6 +979,7 @@ struct e1000_dev_spec_ich8lan {
struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
bool nvm_k1_enabled;
bool eee_disable;
+ u16 eee_lp_ability;
};
struct e1000_hw {
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index dfff441..bbf70ba 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -116,6 +116,7 @@
#define E1000_ICH_RAR_ENTRIES 7
#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
+#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */
#define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
@@ -131,11 +132,18 @@
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+/* SMBus Control Phy Register */
+#define CV_SMB_CTRL PHY_REG(769, 23)
+#define CV_SMB_CTRL_FORCE_SMBUS 0x0001
+
/* SMBus Address Phy Register */
#define HV_SMB_ADDR PHY_REG(768, 26)
#define HV_SMB_ADDR_MASK 0x007F
#define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080
+#define HV_SMB_ADDR_FREQ_MASK 0x1100
+#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8
+#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12
/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)
@@ -152,11 +160,26 @@
#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
#define I82579_MSE_THRESHOLD 0x084F /* Mean Square Error Threshold */
#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
+#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
+#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
+#define I217_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
+
+/* Intel Rapid Start Technology Support */
+#define I217_PROXY_CTRL PHY_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
+#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28)
+#define I217_SxCTRL_MASK 0x1000
+#define I217_CGFREG PHY_REG(772, 29)
+#define I217_CGFREG_MASK 0x0002
+#define I217_MEMPWR PHY_REG(772, 26)
+#define I217_MEMPWR_MASK 0x0010
/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+#define E1000_STRAP_SMT_FREQ_MASK 0x00003000
+#define E1000_STRAP_SMT_FREQ_SHIFT 12
/* OEM Bits Phy Register */
#define HV_OEM_BITS PHY_REG(768, 25)
@@ -261,6 +284,7 @@ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
@@ -332,6 +356,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
{
u32 mac_reg, fwsm = er32(FWSM);
s32 ret_val;
+ u16 phy_reg;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val) {
@@ -345,16 +370,42 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
* LANPHYPC Value bit to force the interconnect to PCIe mode.
*/
switch (hw->mac.type) {
+ case e1000_pch_lpt:
+ if (e1000_phy_is_accessible_pchlan(hw))
+ break;
+
+ /*
+ * Before toggling LANPHYPC, see if PHY is accessible by
+ * forcing MAC to SMBus mode first.
+ */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+
+ /* fall-through */
case e1000_pch2lan:
/*
* Gate automatic PHY configuration by hardware on
* non-managed 82579
*/
- if (!(fwsm & E1000_ICH_FWSM_FW_VALID))
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID))
e1000_gate_hw_phy_config_ich8lan(hw, true);
- if (e1000_phy_is_accessible_pchlan(hw))
+ if (e1000_phy_is_accessible_pchlan(hw)) {
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Unforce SMBus mode in PHY */
+ e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
+
+ /* Unforce SMBus mode in MAC */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+ }
break;
+ }
/* fall-through */
case e1000_pchlan:
@@ -385,7 +436,15 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
ew32(CTRL, mac_reg);
e1e_flush();
- msleep(50);
+ if (hw->mac.type < e1000_pch_lpt) {
+ msleep(50);
+ } else {
+ u16 count = 20;
+ do {
+ usleep_range(5000, 10000);
+ } while (!(er32(CTRL_EXT) &
+ E1000_CTRL_EXT_LPCD) && count--);
+ }
break;
default:
break;
@@ -454,6 +513,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
break;
/* fall-through */
case e1000_pch2lan:
+ case e1000_pch_lpt:
/*
* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
@@ -471,6 +531,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
switch (phy->type) {
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577;
@@ -655,7 +716,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
/* Adaptive IFS supported */
mac->adaptive_ifs = true;
- /* LED operations */
+ /* LED and other operations */
switch (mac->type) {
case e1000_ich8lan:
case e1000_ich9lan:
@@ -678,6 +739,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
mac->ops.rar_set = e1000_rar_set_pch2lan;
/* fall-through */
+ case e1000_pch_lpt:
case e1000_pchlan:
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
@@ -695,12 +757,20 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
+ if (mac->type == e1000_pch_lpt) {
+ mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch_lpt;
+ }
+
/* Enable PCS Lock-loss workaround for ICH8 */
if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
- /* Gate automatic PHY configuration by hardware on managed 82579 */
- if ((mac->type == e1000_pch2lan) &&
+ /*
+ * Gate automatic PHY configuration by hardware on managed
+ * 82579 and i217
+ */
+ if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) &&
(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
e1000_gate_hw_phy_config_ich8lan(hw, true);
@@ -716,22 +786,50 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
s32 ret_val = 0;
u16 phy_reg;
- if (hw->phy.type != e1000_phy_82579)
+ if ((hw->phy.type != e1000_phy_82579) &&
+ (hw->phy.type != e1000_phy_i217))
return 0;
ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
if (ret_val)
return ret_val;
- if (hw->dev_spec.ich8lan.eee_disable)
+ if (dev_spec->eee_disable)
phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
else
phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
- return e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->phy.type == e1000_phy_i217) && !dev_spec->eee_disable) {
+ /* Save off link partner's EEE ability */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_LP_ABILITY);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability);
+
+ /*
+ * EEE is not supported in 100Half, so ignore partner's EEE
+ * in 100 ability if full-duplex is not advertised.
+ */
+ e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg);
+ if (!(phy_reg & NWAY_LPAR_100TX_FD_CAPS))
+ dev_spec->eee_lp_ability &= ~I217_EEE_100_SUPPORTED;
+release:
+ hw->phy.ops.release(hw);
+ }
+
+ return 0;
}
/**
@@ -773,6 +871,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val;
}
+ /* Clear link partner's EEE ability */
+ hw->dev_spec.ich8lan.eee_lp_ability = 0;
+
if (!link)
return 0; /* No link detected */
@@ -868,6 +969,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
break;
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
rc = e1000_init_phy_params_pchlan(hw);
break;
default:
@@ -1117,6 +1219,81 @@ out:
}
/**
+ * e1000_rar_set_pch_lpt - Set receive address registers
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address register array at index to the address passed
+ * in by addr. For LPT, RAR[0] is the base address register that is to
+ * contain the MAC address. SHRA[0-10] are the shared receive address
+ * registers that are shared between the Host and manageability engine (ME).
+ **/
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+ u32 wlock_mac;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ /*
+ * The manageability engine (ME) can lock certain SHRAR registers that
+ * it is using - those registers are unavailable for use.
+ */
+ if (index < hw->mac.rar_entry_count) {
+ wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK;
+ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ /* Check if all SHRAR registers are locked */
+ if (wlock_mac == 1)
+ goto out;
+
+ if ((wlock_mac == 0) || (index <= wlock_mac)) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL_PCH_LPT(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH_PCH_LPT(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) &&
+ (er32(SHRAH_PCH_LPT(index - 1)) == rar_high))
+ return;
+ }
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
* e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -1144,6 +1321,8 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
{
u16 phy_data;
u32 strap = er32(STRAP);
+ u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >>
+ E1000_STRAP_SMT_FREQ_SHIFT;
s32 ret_val = 0;
strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
@@ -1156,6 +1335,19 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ if (hw->phy.type == e1000_phy_i217) {
+ /* Restore SMBus frequency */
+ if (freq--) {
+ phy_data &= ~HV_SMB_ADDR_FREQ_MASK;
+ phy_data |= (freq & (1 << 0)) <<
+ HV_SMB_ADDR_FREQ_LOW_SHIFT;
+ phy_data |= (freq & (1 << 1)) <<
+ (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1);
+ } else {
+ e_dbg("Unsupported SMB frequency in PHY\n");
+ }
+ }
+
return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
}
@@ -1193,6 +1385,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Fall-thru */
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -1212,10 +1405,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
- if (!(hw->mac.type == e1000_pch2lan)) {
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto release;
- }
+ if ((hw->mac.type < e1000_pch2lan) &&
+ (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE))
+ goto release;
cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -1226,9 +1418,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
- if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
- (hw->mac.type == e1000_pchlan)) ||
- (hw->mac.type == e1000_pch2lan)) {
+ if (((hw->mac.type == e1000_pchlan) &&
+ !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
+ (hw->mac.type > e1000_pchlan)) {
/*
* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
@@ -1425,14 +1617,14 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg;
u16 oem_reg;
- if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
+ if (hw->mac.type < e1000_pchlan)
return ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- if (!(hw->mac.type == e1000_pch2lan)) {
+ if (hw->mac.type == e1000_pchlan) {
mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto release;
@@ -1629,7 +1821,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
u32 mac_reg;
u16 i;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return 0;
/* disable Rx path while enabling/disabling workaround */
@@ -1886,7 +2078,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
{
u32 extcnf_ctrl;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return;
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -3525,6 +3717,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ew32(FCRTV_PCH, hw->fc.refresh_time);
@@ -3588,6 +3781,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
break;
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val)
return ret_val;
@@ -3834,14 +4028,88 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
* the LPLU setting in the NVM or custom setting. For PCH and newer parts,
* the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
* needs to be written.
+ * Parts that support (and are linked to a partner which support) EEE in
+ * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
+ * than 10Mbps w/o EEE.
**/
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 phy_ctrl;
s32 ret_val;
phy_ctrl = er32(PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
+ if (!dev_spec->eee_disable) {
+ u16 eee_advert;
+
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_ADVERTISEMENT);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert);
+
+ /*
+ * Disable LPLU if both link partners support 100BaseT
+ * EEE and 100Full is advertised on both ends of the
+ * link.
+ */
+ if ((eee_advert & I217_EEE_100_SUPPORTED) &&
+ (dev_spec->eee_lp_ability &
+ I217_EEE_100_SUPPORTED) &&
+ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+ phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU);
+ }
+
+ /*
+ * For i217 Intel Rapid Start Technology support,
+ * when the system is going into Sx and no manageability engine
+ * is present, the driver must configure proxy to reset only on
+ * power good. LPI (Low Power Idle) state must also reset only
+ * on power good, as well as the MTA (Multicast table array).
+ * The SMBus release must also be disabled on LCD reset.
+ */
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+
+ /* Enable proxy to reset only on power good. */
+ e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg);
+ phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg);
+
+ /*
+ * Set bit enable LPI (EEE) to reset only on
+ * power good.
+ */
+ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg);
+ phy_reg |= I217_SxCTRL_MASK;
+ e1e_wphy_locked(hw, I217_SxCTRL, phy_reg);
+
+ /* Disable the SMB release on LCD reset. */
+ e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ phy_reg &= ~I217_MEMPWR;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+ }
+
+ /*
+ * Enable MTA to reset for Intel Rapid Start Technology
+ * Support
+ */
+ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ phy_reg |= I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
+ }
+out:
ew32(PHY_CTRL, phy_ctrl);
if (hw->mac.type == e1000_ich8lan)
@@ -3870,6 +4138,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
* on which PHY resets are not blocked, if the PHY registers cannot be
* accessed properly by the s/w toggle the LANPHYPC value to power cycle
* the PHY.
+ * On i217, setup Intel Rapid Start Technology.
**/
void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
@@ -3883,6 +4152,47 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val);
return;
}
+
+ /*
+ * For i217 Intel Rapid Start Technology support when the system
+ * is transitioning from Sx and no manageability engine is present
+ * configure SMBus to restore on reset, disable proxy, and enable
+ * the reset on MTA (Multicast table array).
+ */
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to setup iRST\n");
+ return;
+ }
+
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+ /*
+ * Restore clear on SMB if no manageability engine
+ * is present
+ */
+ ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg |= I217_MEMPWR_MASK;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+
+ /* Disable Proxy */
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, 0);
+ }
+ /* Enable reset on MTA */
+ ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg &= ~I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
+release:
+ if (ret_val)
+ e_dbg("Error %d in resume workarounds\n", ret_val);
+ hw->phy.ops.release(hw);
+ }
}
/**
@@ -4123,6 +4433,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
@@ -4282,3 +4593,22 @@ const struct e1000_info e1000_pch2_info = {
.phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops,
};
+
+const struct e1000_info e1000_pch_lpt_info = {
+ .mac = e1000_pch_lpt,
+ .flags = FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+ | FLAG_HAS_AMT
+ | FLAG_HAS_FLASH
+ | FLAG_HAS_JUMBO_FRAMES
+ | FLAG_APME_IN_WUC,
+ .flags2 = FLAG2_HAS_PHY_STATS
+ | FLAG2_HAS_EEE,
+ .pba = 26,
+ .max_hw_frame_size = DEFAULT_JUMBO,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+};
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index c19784c..b53ea83 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -79,6 +79,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_ich10lan] = &e1000_ich10_info,
[board_pchlan] = &e1000_pch_info,
[board_pch2lan] = &e1000_pch2_info,
+ [board_pch_lpt] = &e1000_pch_lpt_info,
};
struct e1000_reg_info {
@@ -2863,8 +2864,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
u32 rctl, rfctl;
u32 pages = 0;
- /* Workaround Si errata on 82579 - configure jumbo frame flow */
- if (hw->mac.type == e1000_pch2lan) {
+ /* Workaround Si errata on PCHx - configure jumbo frame flow */
+ if (hw->mac.type >= e1000_pch2lan) {
s32 ret_val;
if (adapter->netdev->mtu > ETH_DATA_LEN)
@@ -3487,6 +3488,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->refresh_time = 0x1000;
break;
case e1000_pch2lan:
+ case e1000_pch_lpt:
fc->high_water = 0x05C20;
fc->low_water = 0x05048;
fc->pause_time = 0x0650;
@@ -5264,11 +5266,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
- /* Jumbo frame workaround on 82579 requires CRC be stripped */
- if ((adapter->hw.mac.type == e1000_pch2lan) &&
+ /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
+ if ((adapter->hw.mac.type >= e1000_pch2lan) &&
!(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
(new_mtu > ETH_DATA_LEN)) {
- e_err("Jumbo Frames not supported on 82579 when CRC stripping is disabled.\n");
+ e_err("Jumbo Frames not supported on this device when CRC stripping is disabled.\n");
return -EINVAL;
}
@@ -5665,7 +5667,7 @@ static int __e1000_resume(struct pci_dev *pdev)
return err;
}
- if (hw->mac.type == e1000_pch2lan)
+ if (hw->mac.type >= e1000_pch2lan)
e1000_resume_workarounds_pchlan(&adapter->hw);
e1000e_power_up_phy(adapter);
@@ -6564,6 +6566,9 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt },
+
{ 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index ad22b8c..ada7133 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -2335,6 +2335,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
case I82579_E_PHY_ID:
phy_type = e1000_phy_82579;
break;
+ case I217_E_PHY_ID:
+ phy_type = e1000_phy_i217;
+ break;
default:
phy_type = e1000_phy_unknown;
break;
--
1.7.7.6
^ permalink raw reply related
* [net-next 3/8] ixgbe: Track instances of buffer available but no DMA resources present
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change makes it so that we can track instances of where a packet was
dropped due to a packet being received when there are no DMA buffers
available in the ring.
For some reason this was only being enabled with RSC, however it makes
more sense to always have this feature on so that we can track any cases
where we might drop a buffer due to an Rx ring being full.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 688c7bb..09409ae 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4967,9 +4967,6 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
u64 rsc_count = 0;
u64 rsc_flush = 0;
- for (i = 0; i < 16; i++)
- adapter->hw_rx_no_dma_resources +=
- IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
for (i = 0; i < adapter->num_rx_queues; i++) {
rsc_count += adapter->rx_ring[i]->rx_stats.rsc_count;
rsc_flush += adapter->rx_ring[i]->rx_stats.rsc_flush;
@@ -5072,6 +5069,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC);
hwstats->b2ogprc += IXGBE_READ_REG(hw, IXGBE_B2OGPRC);
case ixgbe_mac_82599EB:
+ for (i = 0; i < 16; i++)
+ adapter->hw_rx_no_dma_resources +=
+ IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */
hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
--
1.7.7.6
^ permalink raw reply related
* [net-next 4/8] ixgbe: Reorder the ring to q_vector mapping to improve performance
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change reorders the mapping of rings to q_vectors in the case that the
number of rings exceeds the number of q_vectors. Previously we would
allocate the first R/N queues to the first q_vector where R is the number
of rings and N is the number of q_vectors. Instead of doing this we can do
a better job of interleaving the rings to the CPUs by assigning every Nth
ring to the q_vector.
The below tables illustrate this change for the R = 16 N = 4 case.
Before patch After patch
q_vector: 0 1 2 3 0 1 2 3
Rings: 0 4 8 12 0 1 2 3
1 5 9 13 4 5 6 7
3 6 10 14 8 9 10 11
4 7 11 15 12 13 14 15
This should improve the performance for both DCB or ATR when the number of
rings exceeds the number of q_vectors allocated by the adapter.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 35 ++++++++++++++-----------
1 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index ed1b47d..af1a531 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -523,11 +523,17 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
/**
* ixgbe_alloc_q_vector - Allocate memory for a single interrupt vector
* @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
* @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
*
* We allocate one q_vector. If allocation fails we return -ENOMEM.
**/
-static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
+static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
+ int v_count, int v_idx,
int txr_count, int txr_idx,
int rxr_count, int rxr_idx)
{
@@ -598,7 +604,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
/* update count and index */
txr_count--;
- txr_idx++;
+ txr_idx += v_count;
/* push pointer to next ring */
ring++;
@@ -641,7 +647,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
/* update count and index */
rxr_count--;
- rxr_idx++;
+ rxr_idx += v_count;
/* push pointer to next ring */
ring++;
@@ -700,24 +706,23 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
q_vectors = 1;
if (q_vectors >= (rxr_remaining + txr_remaining)) {
- for (; rxr_remaining; v_idx++, q_vectors--) {
- int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors);
- err = ixgbe_alloc_q_vector(adapter, v_idx,
- 0, 0, rqpv, rxr_idx);
+ for (; rxr_remaining; v_idx++) {
+ err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
+ 0, 0, 1, rxr_idx);
if (err)
goto err_out;
/* update counts and index */
- rxr_remaining -= rqpv;
- rxr_idx += rqpv;
+ rxr_remaining--;
+ rxr_idx++;
}
}
- for (; q_vectors; v_idx++, q_vectors--) {
- int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors);
- int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors);
- err = ixgbe_alloc_q_vector(adapter, v_idx,
+ for (; v_idx < q_vectors; v_idx++) {
+ int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+ int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+ err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
tqpv, txr_idx,
rqpv, rxr_idx);
@@ -726,9 +731,9 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
/* update counts and index */
rxr_remaining -= rqpv;
- rxr_idx += rqpv;
txr_remaining -= tqpv;
- txr_idx += tqpv;
+ rxr_idx++;
+ txr_idx++;
}
return 0;
--
1.7.7.6
^ permalink raw reply related
* [net-next 6/8] ixgbe: Use __free_pages instead of put_page to release pages
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change replaces the calls to put_page with calls to __free_page.
Since the FCoE code is able to access order 1 pages I thought it would be a
good idea to change things over to using __free_pages since that is the
preferred approach for freeing pages.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 09409ae..c2ceda9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1144,7 +1144,7 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
* there isn't much point in holding memory we can't use
*/
if (dma_mapping_error(rx_ring->dev, dma)) {
- put_page(page);
+ __free_pages(page, ixgbe_rx_pg_order(rx_ring));
bi->page = NULL;
rx_ring->rx_stats.alloc_rx_page_failed++;
@@ -4102,7 +4102,8 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
DMA_FROM_DEVICE);
rx_buffer->dma = 0;
if (rx_buffer->page)
- put_page(rx_buffer->page);
+ __free_pages(rx_buffer->page,
+ ixgbe_rx_pg_order(rx_ring));
rx_buffer->page = NULL;
}
--
1.7.7.6
^ permalink raw reply related
* [net-next 5/8] ixgbe: Make ixgbe_fc_autoneg return void and always set current_mode
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change makes it so that ixgbe_fc_autoneg is a void and always sets the
current_mode. Previously if the link was down we would return an error,
however there is no harm in simply treating a link down case as a case in
which autoneg simply failed. This allows us to rely on the return value of
the ixgbe_fc_enable call now since there should be no cases where it
returns an error that would normally be ignored.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 4 +--
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 37 +++++++----------------
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 -
4 files changed, 13 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 6175845..badcf82 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -363,9 +363,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
}
/* Negotiate the fc mode to use */
- ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val == IXGBE_ERR_FLOW_CONTROL)
- goto out;
+ ixgbe_fc_autoneg(hw);
/* Disable any previous flow control settings */
fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index e2b0519..9854d94 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -1940,9 +1940,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
#endif /* CONFIG_DCB */
/* Negotiate the fc mode to use */
- ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val == IXGBE_ERR_FLOW_CONTROL)
- goto out;
+ ixgbe_fc_autoneg(hw);
/* Disable any previous flow control settings */
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
@@ -2051,15 +2049,12 @@ out:
* Compares our advertised flow control capabilities to those advertised by
* our link partner, and determines the proper flow control mode to use.
**/
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
{
s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
ixgbe_link_speed speed;
bool link_up;
- if (hw->fc.disable_fc_autoneg)
- goto out;
-
/*
* AN should have completed when the cable was plugged in.
* Look for reasons to bail out. Bail out if:
@@ -2069,11 +2064,12 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
* Since we're being called from an LSC, link is already known to be up.
* So use link_up_wait_to_complete=false.
*/
+ if (hw->fc.disable_fc_autoneg)
+ goto out;
+
hw->mac.ops.check_link(hw, &speed, &link_up, false);
- if (!link_up) {
- ret_val = IXGBE_ERR_FLOW_CONTROL;
+ if (!link_up)
goto out;
- }
switch (hw->phy.media_type) {
/* Autoneg flow control on fiber adapters */
@@ -2104,7 +2100,6 @@ out:
hw->fc.fc_was_autonegged = false;
hw->fc.current_mode = hw->fc.requested_mode;
}
- return ret_val;
}
/**
@@ -2116,7 +2111,7 @@ out:
static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
{
u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
- s32 ret_val;
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
/*
* On multispeed fiber at 1g, bail out if
@@ -2126,10 +2121,8 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
- (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
goto out;
- }
pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
@@ -2153,7 +2146,7 @@ out:
static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
{
u32 links2, anlp1_reg, autoc_reg, links;
- s32 ret_val;
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
/*
* On backplane, bail out if
@@ -2161,21 +2154,13 @@ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
* - we are 82599 and link partner is not AN enabled
*/
links = IXGBE_READ_REG(hw, IXGBE_LINKS);
- if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
- hw->fc.fc_was_autonegged = false;
- hw->fc.current_mode = hw->fc.requested_mode;
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
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;
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
goto out;
- }
}
/*
* Read the 10g AN autoc and LP ability registers and resolve
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index f992777..9e8a1c0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -78,7 +78,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index d82e25c..5337260 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -2981,7 +2981,6 @@ struct ixgbe_info {
#define IXGBE_ERR_OVERTEMP -26
#define IXGBE_ERR_FC_NOT_NEGOTIATED -27
#define IXGBE_ERR_FC_NOT_SUPPORTED -28
-#define IXGBE_ERR_FLOW_CONTROL -29
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32
--
1.7.7.6
^ permalink raw reply related
* [net-next 7/8] ixgbe: Reorder link flow control functions in ixgbe_common.c
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
We can avoid many of the forward declarations found in ixgbe_common.c by
just reordering things so this patch does that to help cleanup the code.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 572 +++++++++++------------
1 files changed, 282 insertions(+), 290 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 9854d94..3035f19 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -47,13 +47,6 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
-static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
@@ -64,6 +57,216 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
/**
+ * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ * control
+ * @hw: pointer to hardware structure
+ *
+ * There are several phys that do not support autoneg flow control. This
+ * function check the device id to see if the associated phy supports
+ * autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X540T:
+ return 0;
+ case IXGBE_DEV_ID_82599_T3_LOM:
+ return 0;
+ default:
+ return IXGBE_ERR_FC_NOT_SUPPORTED;
+ }
+}
+
+/**
+ * ixgbe_setup_fc - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+{
+ s32 ret_val = 0;
+ u32 reg = 0, reg_bp = 0;
+ u16 reg_cu = 0;
+
+#ifdef CONFIG_DCB
+ if (hw->fc.requested_mode == ixgbe_fc_pfc) {
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+
+#endif /* CONFIG_DCB */
+ /* Validate the packetbuf configuration */
+ if (packetbuf_num < 0 || packetbuf_num > 7) {
+ hw_dbg(hw, "Invalid packet buffer number [%d], expected range is 0-7\n",
+ packetbuf_num);
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * Validate the water mark configuration. Zero water marks are invalid
+ * because it causes the controller to just blast out fc packets.
+ */
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[packetbuf_num] ||
+ !hw->fc.pause_time) {
+ hw_dbg(hw, "Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * Validate the requested mode. Strict IEEE mode does not allow
+ * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
+ */
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * 10gig parts do not have a word in the EEPROM to determine the
+ * default flow control setting, so we explicitly set it to full.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ /*
+ * Set up the 1G and 10G flow control advertisement registers so the
+ * HW will be able to do fc autoneg once the cable is plugged in. If
+ * we link at 10G, the 1G advertisement is harmless and vice versa.
+ */
+
+ switch (hw->phy.media_type) {
+ case ixgbe_media_type_fiber:
+ case ixgbe_media_type_backplane:
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ break;
+
+ case ixgbe_media_type_copper:
+ hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+ MDIO_MMD_AN, ®_cu);
+ break;
+
+ default:
+ ;
+ }
+
+ /*
+ * The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+#ifdef CONFIG_DCB
+ * 4: Priority Flow Control is enabled.
+#endif
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
+ reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
+ } else if (hw->phy.media_type == ixgbe_media_type_copper) {
+ reg_cu |= (IXGBE_TAF_ASM_PAUSE);
+ reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
+ }
+ break;
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+ break;
+#ifdef CONFIG_DCB
+ case ixgbe_fc_pfc:
+ goto out;
+ break;
+#endif /* CONFIG_DCB */
+ default:
+ hw_dbg(hw, "Flow control param set incorrectly\n");
+ ret_val = IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+
+ if (hw->mac.type != ixgbe_mac_X540) {
+ /*
+ * Enable auto-negotiation between the MAC & PHY;
+ * the MAC will advertise clause 37 flow control.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+ /* Disable AN timeout */
+ if (hw->fc.strict_ieee)
+ reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+ hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ }
+
+ /*
+ * AUTOC restart handles negotiation of 1G and 10G on backplane
+ * and copper. There is no need to set the PCS1GCTL register.
+ *
+ */
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+ } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+ (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
+ hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+ MDIO_MMD_AN, reg_cu);
+ }
+
+ hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+out:
+ return ret_val;
+}
+
+/**
* ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
*
@@ -2043,63 +2246,52 @@ out:
}
/**
- * ixgbe_fc_autoneg - Configure flow control
+ * ixgbe_negotiate_fc - Negotiate flow control
* @hw: pointer to hardware structure
+ * @adv_reg: flow control advertised settings
+ * @lp_reg: link partner's flow control settings
+ * @adv_sym: symmetric pause bit in advertisement
+ * @adv_asm: asymmetric pause bit in advertisement
+ * @lp_sym: symmetric pause bit in link partner advertisement
+ * @lp_asm: asymmetric pause bit in link partner advertisement
*
- * Compares our advertised flow control capabilities to those advertised by
- * our link partner, and determines the proper flow control mode to use.
+ * Find the intersection between advertised settings and link partner's
+ * advertised settings
**/
-void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
{
- s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
- ixgbe_link_speed speed;
- bool link_up;
-
- /*
- * AN should have completed when the cable was plugged in.
- * Look for reasons to bail out. Bail out if:
- * - FC autoneg is disabled, or if
- * - link is not up.
- *
- * Since we're being called from an LSC, link is already known to be up.
- * So use link_up_wait_to_complete=false.
- */
- if (hw->fc.disable_fc_autoneg)
- goto out;
-
- hw->mac.ops.check_link(hw, &speed, &link_up, false);
- if (!link_up)
- goto out;
-
- switch (hw->phy.media_type) {
- /* Autoneg flow control on fiber adapters */
- case ixgbe_media_type_fiber:
- if (speed == IXGBE_LINK_SPEED_1GB_FULL)
- ret_val = ixgbe_fc_autoneg_fiber(hw);
- break;
-
- /* Autoneg flow control on backplane adapters */
- case ixgbe_media_type_backplane:
- ret_val = ixgbe_fc_autoneg_backplane(hw);
- break;
+ if ((!(adv_reg)) || (!(lp_reg)))
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
- /* Autoneg flow control on copper adapters */
- case ixgbe_media_type_copper:
- if (ixgbe_device_supports_autoneg_fc(hw) == 0)
- ret_val = ixgbe_fc_autoneg_copper(hw);
- break;
-
- default:
- break;
- }
-
-out:
- if (ret_val == 0) {
- hw->fc.fc_was_autonegged = true;
+ if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ hw_dbg(hw, "Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
+ }
+ } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+ } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
} else {
- hw->fc.fc_was_autonegged = false;
- hw->fc.current_mode = hw->fc.requested_mode;
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw_dbg(hw, "Flow Control = NONE.\n");
}
+ return 0;
}
/**
@@ -2202,241 +2394,63 @@ static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
}
/**
- * ixgbe_negotiate_fc - Negotiate flow control
- * @hw: pointer to hardware structure
- * @adv_reg: flow control advertised settings
- * @lp_reg: link partner's flow control settings
- * @adv_sym: symmetric pause bit in advertisement
- * @adv_asm: asymmetric pause bit in advertisement
- * @lp_sym: symmetric pause bit in link partner advertisement
- * @lp_asm: asymmetric pause bit in link partner advertisement
- *
- * Find the intersection between advertised settings and link partner's
- * advertised settings
- **/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
-{
- if ((!(adv_reg)) || (!(lp_reg)))
- return IXGBE_ERR_FC_NOT_NEGOTIATED;
-
- if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
- /*
- * Now we need to check if the user selected Rx ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
- */
- if (hw->fc.requested_mode == ixgbe_fc_full) {
- hw->fc.current_mode = ixgbe_fc_full;
- hw_dbg(hw, "Flow Control = FULL.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
- }
- } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
- (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
- hw->fc.current_mode = ixgbe_fc_tx_pause;
- hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
- } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
- !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_none;
- hw_dbg(hw, "Flow Control = NONE.\n");
- }
- return 0;
-}
-
-/**
- * ixgbe_setup_fc - Set up flow control
+ * ixgbe_fc_autoneg - Configure flow control
* @hw: pointer to hardware structure
*
- * Called at init time to set up flow control.
+ * Compares our advertised flow control capabilities to those advertised by
+ * our link partner, and determines the proper flow control mode to use.
**/
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
- u32 reg = 0, reg_bp = 0;
- u16 reg_cu = 0;
-
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc) {
- hw->fc.current_mode = hw->fc.requested_mode;
- goto out;
- }
-
-#endif /* CONFIG_DCB */
- /* Validate the packetbuf configuration */
- if (packetbuf_num < 0 || packetbuf_num > 7) {
- hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
- "is 0-7\n", packetbuf_num);
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ ixgbe_link_speed speed;
+ bool link_up;
/*
- * Validate the water mark configuration. Zero water marks are invalid
- * because it causes the controller to just blast out fc packets.
+ * AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ *
+ * Since we're being called from an LSC, link is already known to be up.
+ * So use link_up_wait_to_complete=false.
*/
- if (!hw->fc.low_water ||
- !hw->fc.high_water[packetbuf_num] ||
- !hw->fc.pause_time) {
- hw_dbg(hw, "Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ if (hw->fc.disable_fc_autoneg)
goto out;
- }
- /*
- * Validate the requested mode. Strict IEEE mode does not allow
- * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
- */
- if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
- hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict "
- "IEEE mode\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ hw->mac.ops.check_link(hw, &speed, &link_up, false);
+ if (!link_up)
goto out;
- }
-
- /*
- * 10gig parts do not have a word in the EEPROM to determine the
- * default flow control setting, so we explicitly set it to full.
- */
- if (hw->fc.requested_mode == ixgbe_fc_default)
- hw->fc.requested_mode = ixgbe_fc_full;
-
- /*
- * Set up the 1G and 10G flow control advertisement registers so the
- * HW will be able to do fc autoneg once the cable is plugged in. If
- * we link at 10G, the 1G advertisement is harmless and vice versa.
- */
switch (hw->phy.media_type) {
+ /* Autoneg flow control on fiber adapters */
case ixgbe_media_type_fiber:
+ if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+ ret_val = ixgbe_fc_autoneg_fiber(hw);
+ break;
+
+ /* Autoneg flow control on backplane adapters */
case ixgbe_media_type_backplane:
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
- reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ ret_val = ixgbe_fc_autoneg_backplane(hw);
break;
+ /* Autoneg flow control on copper adapters */
case ixgbe_media_type_copper:
- hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN, ®_cu);
+ if (ixgbe_device_supports_autoneg_fc(hw) == 0)
+ ret_val = ixgbe_fc_autoneg_copper(hw);
break;
default:
- ;
- }
-
- /*
- * The possible values of fc.requested_mode are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames,
- * but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but
- * we do not support receiving pause frames).
- * 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
- * other: Invalid.
- */
- switch (hw->fc.requested_mode) {
- case ixgbe_fc_none:
- /* Flow control completely disabled by software override. */
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
- case ixgbe_fc_rx_pause:
- /*
- * Rx Flow control is enabled and Tx Flow control is
- * disabled by software override. Since there really
- * isn't a way to advertise that we are capable of RX
- * Pause ONLY, we will advertise that we support both
- * symmetric and asymmetric Rx PAUSE. Later, we will
- * disable the adapter's ability to send PAUSE frames.
- */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
break;
- case ixgbe_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is
- * disabled by software override.
- */
- reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
- reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
- } else if (hw->phy.media_type == ixgbe_media_type_copper) {
- reg_cu |= (IXGBE_TAF_ASM_PAUSE);
- reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
- }
- break;
- case ixgbe_fc_full:
- /* Flow control (both Rx and Tx) is enabled by SW override. */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
- default:
- hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = IXGBE_ERR_CONFIG;
- goto out;
- break;
- }
-
- if (hw->mac.type != ixgbe_mac_X540) {
- /*
- * Enable auto-negotiation between the MAC & PHY;
- * the MAC will advertise clause 37 flow control.
- */
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
- /* Disable AN timeout */
- if (hw->fc.strict_ieee)
- reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
-
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
- hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
}
- /*
- * AUTOC restart handles negotiation of 1G and 10G on backplane
- * and copper. There is no need to set the PCS1GCTL register.
- *
- */
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= IXGBE_AUTOC_AN_RESTART;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
- } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
- (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
- hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN, reg_cu);
- }
-
- hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
out:
- return ret_val;
+ if (ret_val == 0) {
+ hw->fc.fc_was_autonegged = true;
+ } else {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
}
/**
@@ -3207,28 +3221,6 @@ wwn_prefix_out:
}
/**
- * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
- * control
- * @hw: pointer to hardware structure
- *
- * There are several phys that do not support autoneg flow control. This
- * function check the device id to see if the associated phy supports
- * autoneg flow control.
- **/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
-{
-
- switch (hw->device_id) {
- case IXGBE_DEV_ID_X540T:
- return 0;
- case IXGBE_DEV_ID_82599_T3_LOM:
- return 0;
- default:
- return IXGBE_ERR_FC_NOT_SUPPORTED;
- }
-}
-
-/**
* ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
* @hw: pointer to hardware structure
* @enable: enable or disable switch for anti-spoofing
--
1.7.7.6
^ permalink raw reply related
* [net-next 8/8] ixgbe: Update link flow control to correctly handle multiple packet buffer DCB
From: Jeff Kirsher @ 2012-05-04 10:35 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1336127716-20383-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change updates the link flow control configuration so that we
correctly set the link flow control settings for DCB. Previously we would
have to call the fc_enable call 8 times, once for each packet buffer. If
we move that logic into the fc_enable call itself we can avoid multiple
unnecessary register writes.
This change also corrects an issue in which we were only shifting the water
marks for 82599 parts by 6 instead of 10. This was resulting in us only
using 1/16 of the packet buffer when flow control was enabled.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 61 ++++----
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 164 +++++++-------------
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c | 13 +--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 16 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 +-
6 files changed, 102 insertions(+), 158 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index badcf82..4253733 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -324,24 +324,33 @@ out:
/**
* ixgbe_fc_enable_82598 - Enable flow control
* @hw: pointer to hardware structure
- * @packetbuf_num: packet buffer number (0-7)
*
* Enable flow control according to the current settings.
**/
-static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
+static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 fctrl_reg;
u32 rmcs_reg;
u32 reg;
+ u32 fcrtl, fcrth;
u32 link_speed = 0;
+ int i;
bool link_up;
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc)
+ /*
+ * Validate the water mark configuration for packet buffer 0. Zero
+ * water marks indicate that the packet buffer was not configured
+ * and the watermarks for packet buffer 0 should always be configured.
+ */
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[0] ||
+ !hw->fc.pause_time) {
+ hw_dbg(hw, "Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
+ }
-#endif /* CONFIG_DCB */
/*
* On 82598 having Rx FC on causes resets while doing 1G
* so if it's on turn it off once we know link_speed. For
@@ -380,9 +389,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
* other: Invalid.
*/
switch (hw->fc.current_mode) {
@@ -415,11 +421,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
fctrl_reg |= IXGBE_FCTRL_RFCE;
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = IXGBE_ERR_CONFIG;
@@ -432,29 +433,29 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
- /* Set up and enable Rx high/low water mark thresholds, enable XON. */
- if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- reg = hw->fc.low_water << 6;
- if (hw->fc.send_xon)
- reg |= IXGBE_FCRTL_XONE;
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
-
- reg = hw->fc.high_water[packetbuf_num] << 6;
- reg |= IXGBE_FCRTH_FCEN;
+ /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+ hw->fc.high_water[i]) {
+ fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
+ }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
}
/* Configure pause time (2 TCs per register) */
- reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
- if ((packetbuf_num & 1) == 0)
- reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
- else
- reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+ /* Configure flow control refresh threshold value */
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
out:
return ret_val;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 3035f19..c7e51b8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -84,39 +84,12 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
*
* Called at init time to set up flow control.
**/
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 reg = 0, reg_bp = 0;
u16 reg_cu = 0;
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc) {
- hw->fc.current_mode = hw->fc.requested_mode;
- goto out;
- }
-
-#endif /* CONFIG_DCB */
- /* Validate the packetbuf configuration */
- if (packetbuf_num < 0 || packetbuf_num > 7) {
- hw_dbg(hw, "Invalid packet buffer number [%d], expected range is 0-7\n",
- packetbuf_num);
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
-
- /*
- * Validate the water mark configuration. Zero water marks are invalid
- * because it causes the controller to just blast out fc packets.
- */
- if (!hw->fc.low_water ||
- !hw->fc.high_water[packetbuf_num] ||
- !hw->fc.pause_time) {
- hw_dbg(hw, "Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
-
/*
* Validate the requested mode. Strict IEEE mode does not allow
* ixgbe_fc_rx_pause because it will cause us to fail at UNH.
@@ -139,21 +112,18 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
* HW will be able to do fc autoneg once the cable is plugged in. If
* we link at 10G, the 1G advertisement is harmless and vice versa.
*/
-
switch (hw->phy.media_type) {
case ixgbe_media_type_fiber:
case ixgbe_media_type_backplane:
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
break;
-
case ixgbe_media_type_copper:
hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
MDIO_MMD_AN, ®_cu);
break;
-
default:
- ;
+ break;
}
/*
@@ -164,9 +134,6 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
* other: Invalid.
*/
switch (hw->fc.requested_mode) {
@@ -179,51 +146,40 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
else if (hw->phy.media_type == ixgbe_media_type_copper)
reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
break;
- case ixgbe_fc_rx_pause:
- /*
- * Rx Flow control is enabled and Tx Flow control is
- * disabled by software override. Since there really
- * isn't a way to advertise that we are capable of RX
- * Pause ONLY, we will advertise that we support both
- * symmetric and asymmetric Rx PAUSE. Later, we will
- * disable the adapter's ability to send PAUSE frames.
- */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
- reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ reg |= IXGBE_PCS1GANA_ASM_PAUSE;
+ reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
- reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
+ reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
+ reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
} else if (hw->phy.media_type == ixgbe_media_type_copper) {
- reg_cu |= (IXGBE_TAF_ASM_PAUSE);
- reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
+ reg_cu |= IXGBE_TAF_ASM_PAUSE;
+ reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
}
break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE, as such we fall
+ * through to the fc_full statement. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
+ reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE;
else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
+ reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
break;
-#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = IXGBE_ERR_CONFIG;
@@ -298,7 +254,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
IXGBE_WRITE_FLUSH(hw);
/* Setup flow control */
- ixgbe_setup_fc(hw, 0);
+ ixgbe_setup_fc(hw);
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
@@ -2126,28 +2082,36 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
/**
* ixgbe_fc_enable_generic - Enable flow control
* @hw: pointer to hardware structure
- * @packetbuf_num: packet buffer number (0-7)
*
* Enable flow control according to the current settings.
**/
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 mflcn_reg, fccfg_reg;
u32 reg;
u32 fcrtl, fcrth;
+ int i;
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc)
+ /*
+ * Validate the water mark configuration for packet buffer 0. Zero
+ * water marks indicate that the packet buffer was not configured
+ * and the watermarks for packet buffer 0 should always be configured.
+ */
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[0] ||
+ !hw->fc.pause_time) {
+ hw_dbg(hw, "Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
+ }
-#endif /* CONFIG_DCB */
/* Negotiate the fc mode to use */
ixgbe_fc_autoneg(hw);
/* Disable any previous flow control settings */
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
+ mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
@@ -2160,9 +2124,6 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
* other: Invalid.
*/
switch (hw->fc.current_mode) {
@@ -2195,11 +2156,6 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
mflcn_reg |= IXGBE_MFLCN_RFCE;
fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = IXGBE_ERR_CONFIG;
@@ -2212,34 +2168,34 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
- fcrtl = hw->fc.low_water << 10;
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
- if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- fcrth = hw->fc.high_water[packetbuf_num] << 10;
- fcrth |= IXGBE_FCRTH_FCEN;
- if (hw->fc.send_xon)
- fcrtl |= IXGBE_FCRTL_XONE;
- } else {
- /*
- * If Tx flow control is disabled, set our high water mark
- * to Rx FIFO size minus 32 in order prevent Tx switch
- * loopback from stalling on DMA.
- */
- fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)) - 32;
- }
+ /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+ hw->fc.high_water[i]) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
+ fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+ /*
+ * In order to prevent Tx hangs when the internal Tx
+ * switch is enabled we must set the high water mark
+ * to the maximum FCRTH value. This allows the Tx
+ * switch to function even under heavy Rx workloads.
+ */
+ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+ }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
+ }
/* Configure pause time (2 TCs per register) */
- reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
- if ((packetbuf_num & 1) == 0)
- reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
- else
- reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
out:
return ret_val;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 9e8a1c0..6222fdb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -77,7 +77,7 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index 888a419..65913c5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -278,18 +278,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
} else {
- /* X540 devices have a RX bit that should be cleared
- * if PFC is disabled on all TCs but PFC features is
- * enabled.
- */
- if (hw->mac.type == ixgbe_mac_X540) {
- reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- reg &= ~IXGBE_MFLCN_RPFCE_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
- }
-
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- hw->mac.ops.fc_enable(hw, i);
+ hw->mac.ops.fc_enable(hw);
}
return 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index c2ceda9..b2daff3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -5250,7 +5250,7 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
u32 link_speed = adapter->link_speed;
bool link_up = adapter->link_up;
- int i;
+ bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE))
return;
@@ -5262,14 +5262,12 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
link_speed = IXGBE_LINK_SPEED_10GB_FULL;
link_up = true;
}
- if (link_up) {
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- hw->mac.ops.fc_enable(hw, i);
- } else {
- hw->mac.ops.fc_enable(hw, 0);
- }
- }
+
+ if (adapter->ixgbe_ieee_pfc)
+ pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
+
+ if (link_up && !((adapter->flags & IXGBE_FLAG_DCB_ENABLED) && pfc_en))
+ hw->mac.ops.fc_enable(hw);
if (link_up ||
time_after(jiffies, (adapter->link_check_timeout +
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 5337260..5e64c77 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -1892,7 +1892,7 @@ enum {
#define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */
#define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */
#define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */
-#define IXGBE_MFLCN_RPFCE_MASK 0x00000FF0 /* Receive FC Mask */
+#define IXGBE_MFLCN_RPFCE_MASK 0x00000FF4 /* Receive FC Mask */
#define IXGBE_MFLCN_RPFCE_SHIFT 4
@@ -2808,7 +2808,7 @@ struct ixgbe_mac_operations {
void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
/* Flow Control */
- s32 (*fc_enable)(struct ixgbe_hw *, s32);
+ s32 (*fc_enable)(struct ixgbe_hw *);
/* Manageability interface */
s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH 7/9] net: add skb_orphan_frags to copy aside frags with destructors
From: Ian Campbell @ 2012-05-04 10:51 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: David Miller, netdev@vger.kernel.org, eric.dumazet@gmail.com
In-Reply-To: <20120504100310.GB31083@redhat.com>
On Fri, 2012-05-04 at 11:03 +0100, Michael S. Tsirkin wrote:
> On Fri, May 04, 2012 at 02:54:33AM -0400, David Miller wrote:
> > From: "Michael S. Tsirkin" <mst@redhat.com>
> > Date: Fri, 4 May 2012 00:10:24 +0300
> >
> > > Hmm we orphan skbs when we loop them back so how about reusing the
> > > skb->destructor for this?
> >
> > That's one possibility.
> >
> > But I fear we're about to toss Ian into yet another rabbit hole. :-)
> >
> > Let's try to converge on something quickly as I think integration of
> > his work has been delayed enough as-is.
>
> This is more intrusive than I'd like because on
> error we need to free the skb, so need
> to return error code from orphan, but it does not add
> an extra branch since skb_orphan is inline.
> So intrusive but should not hurt fast path.
>
> It's weekend here, I'll work on a patch like this
> Sunday.
Thanks, I was starting to feel my nose twitching and my ears beginning
to elongate ;-)
Ian.
^ permalink raw reply
* Re: [net 0/2][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-05-04 10:52 UTC (permalink / raw)
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, gospo@redhat.com, sassmann@redhat.com
In-Reply-To: <1336039717-12336-1-git-send-email-jeffrey.t.kirsher@intel.com>
[-- Attachment #1: Type: text/plain, Size: 1033 bytes --]
On Thu, 2012-05-03 at 03:08 -0700, Kirsher, Jeffrey T wrote:
> This series of patches contains fixes for ixgbe.
>
> The following are changes since commit 5a8887d39e1ba5ee2d4ccb94b14d6f2dce5ddfca:
> sungem: Fix WakeOnLan
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master`
>
> Don Skidmore (1):
> ixgbe: fix race condition with shutdown
>
> John Fastabend (1):
> ixgbe: dcb: BIT_APP_UPCHG not set by ixgbe_copy_dcb_cfg()
>
> drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 --
> drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c | 43 ++++++++++------------
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 ++-
> 3 files changed, 24 insertions(+), 28 deletions(-)
>
> --
> 1.7.7.6
>
Dave-
Since you have not pulled this yet, I plan to send a v2 of this pull
request because I need to add 2 more patches to this pull request. So
please disregard this pull request while I update my net tree.
Cheers,
Jeff
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH 0/3] smsc75xx: more minor fixes
From: Steve Glendinning @ 2012-05-04 10:57 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Steve Glendinning
3 more minor patches for smsc75xx
Steve Glendinning (3):
smsc75xx: replace 0xffff with PHY_INT_SRC_CLEAR_ALL
smsc75xx: eliminate unnecessary phy register read
smsc75xx: let EEPROM determine GPIO/LED settings
drivers/net/usb/smsc75xx.c | 26 +++++++++++++++-----------
drivers/net/usb/smsc75xx.h | 1 +
2 files changed, 16 insertions(+), 11 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH 1/3] smsc75xx: replace 0xffff with PHY_INT_SRC_CLEAR_ALL
From: Steve Glendinning @ 2012-05-04 10:57 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Steve Glendinning
In-Reply-To: <1336129033-15826-1-git-send-email-steve.glendinning@shawell.net>
This patch defines PHY_INT_SRC_CLEAR_ALL to replace the value 0xffff
in order to be more self-documenting.
This patch should make no functional change, it is purely cosmetic.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 3 ++-
drivers/net/usb/smsc75xx.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 00103a8..ecab87b 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -511,7 +511,8 @@ static int smsc75xx_link_reset(struct usbnet *dev)
/* read and write to clear phy interrupt status */
ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
check_warn_return(ret, "Error reading PHY_INT_SRC");
- smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, 0xffff);
+ smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC,
+ PHY_INT_SRC_CLEAR_ALL);
ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
check_warn_return(ret, "Error writing INT_STS");
diff --git a/drivers/net/usb/smsc75xx.h b/drivers/net/usb/smsc75xx.h
index 16e98c7..67eba39 100644
--- a/drivers/net/usb/smsc75xx.h
+++ b/drivers/net/usb/smsc75xx.h
@@ -388,6 +388,7 @@
#define PHY_INT_SRC_ANEG_COMP ((u16)0x0040)
#define PHY_INT_SRC_REMOTE_FAULT ((u16)0x0020)
#define PHY_INT_SRC_LINK_DOWN ((u16)0x0010)
+#define PHY_INT_SRC_CLEAR_ALL ((u16)0xffff)
#define PHY_INT_MASK (30)
#define PHY_INT_MASK_ENERGY_ON ((u16)0x0080)
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/3] smsc75xx: eliminate unnecessary phy register read
From: Steve Glendinning @ 2012-05-04 10:57 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Steve Glendinning
In-Reply-To: <1336129033-15826-1-git-send-email-steve.glendinning@shawell.net>
Only a write is necessary to clear the interrupt status, and we
don't use the value from the preceding read operation. This
patch eliminates the unnecessary read.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index ecab87b..72b62b5 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -508,9 +508,7 @@ static int smsc75xx_link_reset(struct usbnet *dev)
u16 lcladv, rmtadv;
int ret;
- /* read and write to clear phy interrupt status */
- ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
- check_warn_return(ret, "Error reading PHY_INT_SRC");
+ /* write to clear phy interrupt status */
smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC,
PHY_INT_SRC_CLEAR_ALL);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/3] smsc75xx: let EEPROM determine GPIO/LED settings
From: Steve Glendinning @ 2012-05-04 10:57 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Steve Glendinning
In-Reply-To: <1336129033-15826-1-git-send-email-steve.glendinning@shawell.net>
This patch allows the GPIO/LED settings to be configured by the
EEPROM if present, and only sets the default values (LED outputs
for link/activity) when an EEPROM is not detected.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 72b62b5..fb1a087 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -903,15 +903,20 @@ static int smsc75xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf);
- /* Configure GPIO pins as LED outputs */
- ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
- check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
+ ret = smsc75xx_read_reg(dev, E2P_CMD, &buf);
+ check_warn_return(ret, "Failed to read E2P_CMD: %d", ret);
- buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
- buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
+ /* only set default GPIO/LED settings if no EEPROM is detected */
+ if (!(buf & E2P_CMD_LOADED)) {
+ ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
+ check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
- ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
- check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+ buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
+ buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
+
+ ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
+ check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+ }
ret = smsc75xx_write_reg(dev, FLOW, 0);
check_warn_return(ret, "Failed to write FLOW: %d", ret);
--
1.7.9.5
^ permalink raw reply related
* [net v2 0/4][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-05-04 11:05 UTC (permalink / raw)
To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann
This series of patches contains fixes for ixgbe, igb and e1000.
v2: Added e1000 patch to fix sparse warnings and igb/ixgbe to
correct an issue of calling function to reset Tx queue in
init path.
The following are changes since commit 5a8887d39e1ba5ee2d4ccb94b14d6f2dce5ddfca:
sungem: Fix WakeOnLan
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master`
Andrei Emeltchenko (1):
e1000: Silence sparse warnings by correcting type
Don Skidmore (1):
ixgbe: fix race condition with shutdown
John Fastabend (2):
ixgbe: dcb: BIT_APP_UPCHG not set by ixgbe_copy_dcb_cfg()
igb, ixgbe: netdev_tx_reset_queue incorrectly called from tx init
path
drivers/net/ethernet/intel/e1000/e1000_main.c | 4 +-
drivers/net/ethernet/intel/igb/igb_main.c | 4 +-
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 --
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c | 43 ++++++++++------------
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 +
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 +++--
6 files changed, 32 insertions(+), 34 deletions(-)
--
1.7.7.6
^ permalink raw reply
* [net 1/4] ixgbe: fix race condition with shutdown
From: Jeff Kirsher @ 2012-05-04 11:05 UTC (permalink / raw)
To: davem
Cc: Don Skidmore, netdev, gospo, sassmann, Hariharan Nagarajan,
Jeff Kirsher
In-Reply-To: <1336129504-29919-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Don Skidmore <donald.c.skidmore@intel.com>
It was possible for shutdown to pull the rug out from other driver entry
points. Now we just grab the rtnl lock before taking everything apart.
Thanks to Hariharan for noticing this tight race condition.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Cc: Hariharan Nagarajan <hanagara@cisco.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 88f6b2e..d9dbf87 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4866,10 +4866,12 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
netif_device_detach(netdev);
if (netif_running(netdev)) {
+ rtnl_lock();
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
+ rtnl_unlock();
}
ixgbe_clear_interrupt_scheme(adapter);
--
1.7.7.6
^ 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