* Re: [PATCH RFC ipsec-next] xfrm: Add sysctl option to enforce inbound policies for transport mode
From: Steffen Klassert @ 2014-09-19 9:24 UTC (permalink / raw)
To: Tobias Brunner; +Cc: davem, netdev, Herbert Xu
In-Reply-To: <541815C3.7080509@strongswan.org>
Ccing Herbert Xu.
On Tue, Sep 16, 2014 at 12:49:39PM +0200, Tobias Brunner wrote:
> Currently inbound policies for transport mode SAs are not enforced.
> If no policy is found or if the templates don't match this is not
> considered an error for transport mode SAs.
>
The strict inbound policy enforcement was implemented by Herbert.
The commit predates our git history but can be found in the history
tree:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
It was the following commit:
commit 8fe7ee2ba983fd89b2555dce5930ffd0f7f6c361
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Thu Oct 23 14:57:11 2003 -0700
[IPSEC]: Strengthen policy checks.
Maybe Herbert remembers why this was done only for tunnel mode.
If I read section 5.2.1 of RFC 2401 correct, the inbound policy
must be enforced regardless of the mode.
> The new sysctl option (net.core.xfrm_enforce_policies_transport_mode)
> allows enforcing the inbound policies also for transport mode SAs.
> By default this option remains disabled.
I'd not like to have a sysctl for this. I consider it as a bug
if an installed policy can not be enforced, and we don't fix bugs
with sysctls :).
>
> Signed-off-by: Tobias Brunner <tobias@strongswan.org>
> ---
> Consider a transport mode SA between two peers over which only TCP and
> ICMP traffic should be allowed. Because two protocols are involved the
> selector on the SA itself (xfrm_usersa_info.sel) can't be set. Instead
> one either has to negotiate separate SAs for each protocol (with a
> selector on each) or negotiate one SA and install two policies that
> use it. The problem with the latter is that the peer does not have to
> adhere to the negotiated traffic selectors, it is basically free to
> send anything over the SA e.g. UDP packets. So if no selectors are
> installed on the SA itself, the current implementation would accept
> such packets, even though the installed policies don't allow UDP
> traffic (some might consider this a security issue - at the very least
> it is not very intuitive, especially because the behavior is different
> for tunnel mode SAs).
> By enabling the new sysctl option the UDP packets would get dropped,
> exactly as they would if the SA were negotiated in tunnel mode.
>
> The behavior for optional transport mode templates also changes when
> the option is enabled. Basically, the special treatment of transport
> mode SAs is disabled and the behavior is like it is for other modes.
> I tested this with IPComp/ESP and strongSwan where the optional IPComp
> transform is installed in transport or tunnel mode depending on the
> negotiated mode of the SA (the ESP SA is always installed in transport
> mode in this combination). But I'm not sure if there are other uses
> for optional transport mode transforms that might rely on the current
> behavior (i.e. why are optional templates treated differently depending
> on their mode in the first place?).
The code arround xfrm_policy_ok() looks a bit obscure, I'm not sure if
all combinations of required and optional templates are handled correct.
>
> With this patch the default behavior remains as it is, but I wondered
> why it is like that and if we could perhaps change it so that policies
> are enforced by default, thus making such setups more secure out of
> the box. Or if we could even change the whole inbound processing so
> that transport mode SAs are treated exactly like their counterparts
> in other modes, without an option to change it.
>
> Documentation/networking/xfrm_sysctl.txt | 4 ++++
> include/net/netns/xfrm.h | 1 +
> net/xfrm/xfrm_policy.c | 24 +++++++++++++++---------
> net/xfrm/xfrm_sysctl.c | 8 ++++++++
> 4 files changed, 28 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/networking/xfrm_sysctl.txt b/Documentation/networking/xfrm_sysctl.txt
> index 5bbd167..2fbe539 100644
> --- a/Documentation/networking/xfrm_sysctl.txt
> +++ b/Documentation/networking/xfrm_sysctl.txt
> @@ -2,3 +2,7 @@
> xfrm_acq_expires - INTEGER
> default 30 - hard timeout in seconds for acquire requests
> +
> +xfrm_enforce_policies_transport_mode - BOOLEAN
> + default 0 (disabled) - whether to enforce inbound policies for transport
> + mode SAs
> \ No newline at end of file
> diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
> index 9da7982..e045ecc 100644
> --- a/include/net/netns/xfrm.h
> +++ b/include/net/netns/xfrm.h
> @@ -64,6 +64,7 @@ struct netns_xfrm {
> u32 sysctl_aevent_rseqth;
> int sysctl_larval_drop;
> u32 sysctl_acq_expires;
> + int sysctl_enforce_policies_transport_mode;
> #ifdef CONFIG_SYSCTL
> struct ctl_table_header *sysctl_hdr;
> #endif
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index 55bcb86..5296f6b 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -2355,20 +2355,22 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
> * Otherwise "-2 - errored_index" is returned.
> */
> static inline int
> -xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
> - unsigned short family)
> +xfrm_policy_ok(const struct net *net, const struct xfrm_tmpl *tmpl,
> + const struct sec_path *sp, int start, unsigned short family)
> {
> int idx = start;
> if (tmpl->optional) {
> - if (tmpl->mode == XFRM_MODE_TRANSPORT)
> + if (tmpl->mode == XFRM_MODE_TRANSPORT &&
> + !net->xfrm.sysctl_enforce_policies_transport_mode)
> return start;
> } else
> start = -1;
> for (; idx < sp->len; idx++) {
> if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
> return ++idx;
> - if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
> + if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT ||
> + net->xfrm.sysctl_enforce_policies_transport_mode) {
> if (start == -1)
> start = -2-idx;
> break;
> @@ -2393,10 +2395,13 @@ int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
> }
> EXPORT_SYMBOL(__xfrm_decode_session);
> -static inline int secpath_has_nontransport(const struct sec_path *sp, int k, int *idxp)
> +static inline int secpath_has_nontransport(const struct net *net,
> + const struct sec_path *sp,
> + int k, int *idxp)
> {
> for (; k < sp->len; k++) {
> - if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
> + if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT ||
> + net->xfrm.sysctl_enforce_policies_transport_mode) {
> *idxp = k;
> return 1;
> }
> @@ -2469,7 +2474,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
> }
> if (!pol) {
> - if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
> + if (skb->sp &&
> + secpath_has_nontransport(net, skb->sp, 0, &xerr_idx)) {
> xfrm_secpath_reject(xerr_idx, skb, &fl);
> XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
> return 0;
> @@ -2535,7 +2541,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
> * are implied between each two transformations.
> */
> for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
> - k = xfrm_policy_ok(tpp[i], sp, k, family);
> + k = xfrm_policy_ok(net, tpp[i], sp, k, family);
> if (k < 0) {
> if (k < -1)
> /* "-2 - errored_index" returned */
> @@ -2545,7 +2551,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
> }
> }
> - if (secpath_has_nontransport(sp, k, &xerr_idx)) {
> + if (secpath_has_nontransport(net, sp, k, &xerr_idx)) {
> XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH);
> goto reject;
> }
> diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
> index 05a6e3d..17671af 100644
> --- a/net/xfrm/xfrm_sysctl.c
> +++ b/net/xfrm/xfrm_sysctl.c
> @@ -9,6 +9,7 @@ static void __net_init __xfrm_sysctl_init(struct net *net)
> net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE;
> net->xfrm.sysctl_larval_drop = 1;
> net->xfrm.sysctl_acq_expires = 30;
> + net->xfrm.sysctl_enforce_policies_transport_mode = 0;
> }
> #ifdef CONFIG_SYSCTL
> @@ -37,6 +38,12 @@ static struct ctl_table xfrm_table[] = {
> .mode = 0644,
> .proc_handler = proc_dointvec
> },
> + {
> + .procname = "xfrm_enforce_policies_transport_mode",
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = proc_dointvec
> + },
> {}
> };
> @@ -53,6 +60,7 @@ int __net_init xfrm_sysctl_init(struct net *net)
> table[1].data = &net->xfrm.sysctl_aevent_rseqth;
> table[2].data = &net->xfrm.sysctl_larval_drop;
> table[3].data = &net->xfrm.sysctl_acq_expires;
> + table[4].data = &net->xfrm.sysctl_enforce_policies_transport_mode;
> /* Don't export sysctls to unprivileged users */
> if (net->user_ns != &init_user_ns)
> --
> 1.9.1
^ permalink raw reply
* Re: [PATCH net] net: fix sysfs symlinks of adjacent devices
From: Andres Freund @ 2014-09-19 8:59 UTC (permalink / raw)
To: Alexander Fomichev; +Cc: netdev, David Miller, Cong Wang, Vlad Yasevich
In-Reply-To: <1410516826-6926-1-git-send-email-git.user@gmail.com>
Hi,
On 2014-09-12 14:13:46 +0400, Alexander Fomichev wrote:
> From: "Alexander Y. Fomichev" <git.user@gmail.com>
>
> __netdev_adjacent_dev_insert may add adjacent device from another
> namespace. Without proper check it leads to emergence of broken
> symlink from/to device not existing in current namespace.
> Fix: check net_ns is the same before netdev_adjacent_sysfs_add/del
> related to: 4c75431ac3520631f1d9e74aa88407e6374dbbc4
>
This version, applied on top of 8ba4caf1ee, fixes the bug I had
reported. Not just the testcase, but the actual usage scenario.
I haven't tested David's version, but it doesn't look likely to be
materially different.
Greetings,
Andres Freund
^ permalink raw reply
* [PATCH net-next V2] net: keep original skb which only needs header checking during software GSO
From: Jason Wang @ 2014-09-19 8:04 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: Jason Wang, Eric Dumazet
Commit ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
around original SKB when we software segment GSO frames") frees the
original skb after software GSO even for dodgy gso skbs. This breaks
the stream throughput from untrusted sources, since only header
checking was done during software GSO instead of a true
segmentation. This patch fixes this by freeing the original gso skb
only when it was really segmented by software.
Fixes ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
around original SKB when we software segment GSO frames.")
Cc: David S. Miller <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Changes from V1:
- use consume_skb() instead of kfree_skb()
- fix coding style
---
net/core/dev.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index e916ba8..52cd71a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2694,10 +2694,12 @@ struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev)
struct sk_buff *segs;
segs = skb_gso_segment(skb, features);
- kfree_skb(skb);
- if (IS_ERR(segs))
+ if (IS_ERR(segs)) {
segs = NULL;
- skb = segs;
+ } else if (segs) {
+ consume_skb(skb);
+ skb = segs;
+ }
} else {
if (skb_needs_linearize(skb, features) &&
__skb_linearize(skb))
--
1.9.1
^ permalink raw reply related
* Re: [net-next PATCH 00/29] Add support for the Intel FM10000 Ethernet Switch Host Interface
From: Jiri Pirko @ 2014-09-19 7:55 UTC (permalink / raw)
To: Alexander Duyck
Cc: davem, nhorman, netdev, john.fastabend, matthew.vick,
jeffrey.t.kirsher, sassmann
In-Reply-To: <20140918223242.10373.27403.stgit@ahduyck-bv4.jf.intel.com>
Fri, Sep 19, 2014 at 12:35:37AM CEST, alexander.h.duyck@intel.com wrote:
>This patch series adds support for the FM10000 Ethernet switch host
>interface. The Intel FM10000 Ethernet Switch is a 48-port Ethernet switch
>supporting both Ethernet ports and PCI Express host interfaces. The fm10k
>driver provides support for the host interface portion of the switch, both
>PF and VF.
>
>As the host interfaces are directly connected to the switch this results in
>some significant differences versus a standard network driver. For example
>there is no PHY or MII on the device. Since packets are delivered directly
>from the switch to the host interface these are unnecessary. Otherwise most
>of the functionality is very similar to our other network drivers such as
>ixgbe or igb. For example we support all the standard network offloads,
>jumbo frames, SR-IOV (64 VFS), PTP, and some VXLAN and NVGRE offloads.
I'm very happy to see this patchset in the wind. Great news! I have
couple of questions:
Do you also plan to introduce support for FM6000?
>From what I understand, there is one netdev instance for the whole switch (PF).
How can user get stats and info for particular ports? This topic was
discussed many times and I believe that general consensus is to have 1
netdev instance to represent one switch port (that is for example how we
do it in rocker driver).
Thanks.
>
>---
>
>Alexander Duyck (29):
> fm10k: Add skeletal frame for Intel(R) FM10000 Ethernet Switch Host Interface Driver
> fm10k: Add register defines and basic structures
> fm10k: Add support for TLV message parsing and generation
> fm10k: Add support for basic interaction with hardware
> fm10k: Add support for mailbox
> fm10k: Implement PF <-> SM mailbox operations
> fm10k: Add support for PF
> fm10k: Add support for configuring PF interface
> fm10k: Add netdev
> fm10k: Add support for L2 filtering
> fm10k: Add support for ndo_open/stop
> fm10k: Add interrupt support
> fm10k: add support for Tx/Rx rings
> fm10k: Add service task to handle delayed events
> fm10k: Add Tx/Rx hardware ring bring-up/tear-down
> fm10k: Add transmit and receive fastpath and interrupt handlers
> fm10k: Add ethtool support
> fm10k: Add support for PCI power management and error handling
> fm10k: Add support for multiple queues
> fm10k: Add support for netdev offloads
> fm10k: Add support for MACVLAN acceleration
> fm10k: Add support for PF <-> VF mailbox
> fm10k: Add support for VF
> fm10k: Add support for SR-IOV to PF core files
> fm10k: Add support for SR-IOV to driver
> fm10k: Add support for IEEE DCBx
> fm10k: Add support for debugfs
> fm10k: Add support for ptp to hw specific files
> fm10k: Add support for PTP
>
>
> drivers/net/ethernet/intel/Kconfig | 19
> drivers/net/ethernet/intel/Makefile | 1
> drivers/net/ethernet/intel/fm10k/Makefile | 33
> drivers/net/ethernet/intel/fm10k/fm10k.h | 532 +++++
> drivers/net/ethernet/intel/fm10k/fm10k_common.c | 534 +++++
> drivers/net/ethernet/intel/fm10k/fm10k_common.h | 65 +
> drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c | 174 ++
> drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 259 +++
> drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 1069 +++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 536 +++++
> drivers/net/ethernet/intel/fm10k/fm10k_main.c | 1978 ++++++++++++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 2125 ++++++++++++++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_mbx.h | 307 +++
> drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 1424 ++++++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2166 ++++++++++++++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 1849 +++++++++++++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_pf.h | 135 +
> drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 535 +++++
> drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 863 +++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_tlv.h | 186 ++
> drivers/net/ethernet/intel/fm10k/fm10k_type.h | 769 ++++++++
> drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 552 ++++++
> drivers/net/ethernet/intel/fm10k/fm10k_vf.h | 78 +
> 23 files changed, 16189 insertions(+)
> create mode 100644 drivers/net/ethernet/intel/fm10k/Makefile
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_common.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_common.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_iov.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_main.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_mbx.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_pci.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_pf.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_pf.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_ptp.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_tlv.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_tlv.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_type.h
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_vf.c
> create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_vf.h
>
>--
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next] net: keep original skb which only needs header checking during software GSO
From: Jason Wang @ 2014-09-19 7:49 UTC (permalink / raw)
To: Eric Dumazet; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1411110263.7106.301.camel@edumazet-glaptop2.roam.corp.google.com>
On 09/19/2014 03:04 PM, Eric Dumazet wrote:
> On Fri, 2014-09-19 at 14:38 +0800, Jason Wang wrote:
>> Commit ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
>> around original SKB when we software segment GSO frames") frees the
>> original skb after software GSO even for dodgy gso skbs. This breaks
>> the stream throughput from untrusted sources, since only header
>> checking was done during software GSO instead of a true
>> segmentation. This patch fixes this by freeing the original gso skb
>> only when it was really segmented by software.
>>
>> Fixes ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
>> around original SKB when we software segment GSO frames.")
>>
>> CC: David S. Miller <davem@davemloft.net>
>> Signed-off-by: Jason Wang <jasowang@redhat.com>
>> ---
>> net/core/dev.c | 6 ++++--
>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index e916ba8..b7a0e1d 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -2694,10 +2694,12 @@ struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev)
>> struct sk_buff *segs;
>>
>> segs = skb_gso_segment(skb, features);
>> - kfree_skb(skb);
>> if (IS_ERR(segs))
>>
>> - skb = segs;
>> + else if (segs) {
>> + kfree_skb(skb);
>> + skb = segs;
>> + }
>> } else {
>> if (skb_needs_linearize(skb, features) &&
>> __skb_linearize(skb))
> Good catch !
>
> While we are at it, could you use consume_skb() instead of kfree_skb(),
> and add missing {} (CodingStyle) ?
>
> if (IS_ERR(segs)) {
> segs = NULL;
> } else if (segs) {
> consume_skb(skb);
> skb = segs;
> }
>
>
> Thanks !
>
>
Yes, it's better. Will do them in V2.
^ permalink raw reply
* Re: ipsec: Remove obsolete MAX_AH_AUTH_LEN
From: Steffen Klassert @ 2014-09-19 7:48 UTC (permalink / raw)
To: Herbert Xu; +Cc: David S. Miller, netdev
In-Reply-To: <20140918083818.GA13056@gondor.apana.org.au>
On Thu, Sep 18, 2014 at 04:38:18PM +0800, Herbert Xu wrote:
> Oops, should've sent this to Steffen:
>
> While tracking down the MAX_AH_AUTH_LEN crash in an old kernel
> I thought that this limit was rather arbitrary and we should
> just get rid of it.
>
> In fact it seems that we've already done all the work needed
> to remove it apart from actually removing it. This limit was
> there in order to limit stack usage. Since we've already
> switched over to allocating scratch space using kmalloc, there
> is no longer any need to limit the authentication length.
>
> This patch kills all references to it, including the BUG_ONs
> that led me here.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Applied to ipsec-next, thanks Herbert!
^ permalink raw reply
* Re: [net-next PATCH 28/29] fm10k: Add support for ptp to hw specific files
From: Richard Cochran @ 2014-09-19 7:38 UTC (permalink / raw)
To: Alexander Duyck
Cc: davem, nhorman, netdev, john.fastabend, matthew.vick,
jeffrey.t.kirsher, sassmann
In-Reply-To: <20140918224023.10373.11456.stgit@ahduyck-bv4.jf.intel.com>
On Thu, Sep 18, 2014 at 06:40:30PM -0400, Alexander Duyck wrote:
> +static s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb)
> +{
> + u64 systime_adjust;
> +
> + /* if sw_addr is not set we don't have switch register access */
> + if (!hw->sw_addr)
> + return ppb ? FM10K_ERR_PARAM : 0;
> +
> + /* we must convert the value from parts per billion to parts per
> + * 2^48 cycles. In addition we can only use the upper 30 bits of
> + * the value when making the change so that restricts us futher.
> + * The math for this is equivilent to ABS(pps) * 2^40 / 10 ^ 9,
Huh? Converting ppb to parts per 2^48 should be (ppb * 2^48 / 10^9),
shouldn't it?
Did you mean, "we must convert ... to parts per 2^40 cycles" ?
Also, the comment about using the upper 30 bits is not clear. Do you
mean that the hardware ignores the two least significant bits?
> + * the function below is roughly ABS(pps) * 2 ^ 31 / 5 ^ 9 which
> + * is as close as we can get to the exact value with numbers as
> + * small as possible.
> + */
> + systime_adjust = (ppb < 0) ? -ppb : ppb;
> + systime_adjust <<= 31;
> + do_div(systime_adjust, 1953125);
> +
> + /* verify the requested adjustment value is in range */
> + if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK)
> + return FM10K_ERR_PARAM;
> +
> + if (ppb < 0)
> + systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE;
> +
> + fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust);
> +
> + return 0;
> +}
Thanks,
Richard
^ permalink raw reply
* [PATCH net] r8152: disable ALDPS
From: Hayes Wang @ 2014-09-19 7:17 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, linux-usb, Hayes Wang
If the hw is in ALDPS mode, the hw may have no response for accessing
the most registers. Therefore, the ALDPS should be disabled before
accessing the hw in rtl_ops.init(), rtl_ops.disable(), rtl_ops.up(),
and rtl_ops.down(). Regardless of rtl_ops.enable(), because the hw
wouldn't enter ALDPS mode when linking on. The hw would enter the
ALDPS mode after several seconds when link down occurs and the ALDPS
is enabled.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
drivers/net/usb/r8152.c | 62 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 45 insertions(+), 17 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 87f7104..74760e8 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2019,7 +2019,7 @@ static int rtl8153_enable(struct r8152 *tp)
return rtl_enable(tp);
}
-static void rtl8152_disable(struct r8152 *tp)
+static void rtl_disable(struct r8152 *tp)
{
u32 ocp_data;
int i;
@@ -2232,6 +2232,13 @@ static inline void r8152b_enable_aldps(struct r8152 *tp)
LINKENA | DIS_SDSAVE);
}
+static void rtl8152_disable(struct r8152 *tp)
+{
+ r8152b_disable_aldps(tp);
+ rtl_disable(tp);
+ r8152b_enable_aldps(tp);
+}
+
static void r8152b_hw_phy_cfg(struct r8152 *tp)
{
u16 data;
@@ -2242,11 +2249,8 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)
r8152_mdio_write(tp, MII_BMCR, data);
}
- r8152b_disable_aldps(tp);
-
rtl_clear_bp(tp);
- r8152b_enable_aldps(tp);
set_bit(PHY_RESET, &tp->flags);
}
@@ -2255,9 +2259,6 @@ static void r8152b_exit_oob(struct r8152 *tp)
u32 ocp_data;
int i;
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
- return;
-
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
ocp_data &= ~RCR_ACPT_ALL;
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
@@ -2347,7 +2348,7 @@ static void r8152b_enter_oob(struct r8152 *tp)
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
- rtl8152_disable(tp);
+ rtl_disable(tp);
for (i = 0; i < 1000; i++) {
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -2485,9 +2486,6 @@ static void r8153_first_init(struct r8152 *tp)
u32 ocp_data;
int i;
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
- return;
-
rxdy_gated_en(tp, true);
r8153_teredo_off(tp);
@@ -2560,7 +2558,7 @@ static void r8153_enter_oob(struct r8152 *tp)
ocp_data &= ~NOW_IS_OOB;
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
- rtl8152_disable(tp);
+ rtl_disable(tp);
for (i = 0; i < 1000; i++) {
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -2624,6 +2622,13 @@ static void r8153_enable_aldps(struct r8152 *tp)
ocp_reg_write(tp, OCP_POWER_CFG, data);
}
+static void rtl8153_disable(struct r8152 *tp)
+{
+ r8153_disable_aldps(tp);
+ rtl_disable(tp);
+ r8153_enable_aldps(tp);
+}
+
static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
{
u16 bmcr, anar, gbcr;
@@ -2714,6 +2719,16 @@ out:
return ret;
}
+static void rtl8152_up(struct r8152 *tp)
+{
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ r8152b_disable_aldps(tp);
+ r8152b_exit_oob(tp);
+ r8152b_enable_aldps(tp);
+}
+
static void rtl8152_down(struct r8152 *tp)
{
if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
@@ -2727,6 +2742,16 @@ static void rtl8152_down(struct r8152 *tp)
r8152b_enable_aldps(tp);
}
+static void rtl8153_up(struct r8152 *tp)
+{
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ r8153_disable_aldps(tp);
+ r8153_first_init(tp);
+ r8153_enable_aldps(tp);
+}
+
static void rtl8153_down(struct r8152 *tp)
{
if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
@@ -2946,6 +2971,8 @@ static void r8152b_init(struct r8152 *tp)
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return;
+ r8152b_disable_aldps(tp);
+
if (tp->version == RTL_VER_01) {
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
ocp_data &= ~LED_MODE_MASK;
@@ -2984,6 +3011,7 @@ static void r8153_init(struct r8152 *tp)
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return;
+ r8153_disable_aldps(tp);
r8153_u1u2en(tp, false);
for (i = 0; i < 500; i++) {
@@ -3392,7 +3420,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
ops->init = r8152b_init;
ops->enable = rtl8152_enable;
ops->disable = rtl8152_disable;
- ops->up = r8152b_exit_oob;
+ ops->up = rtl8152_up;
ops->down = rtl8152_down;
ops->unload = rtl8152_unload;
ret = 0;
@@ -3400,8 +3428,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
case PRODUCT_ID_RTL8153:
ops->init = r8153_init;
ops->enable = rtl8153_enable;
- ops->disable = rtl8152_disable;
- ops->up = r8153_first_init;
+ ops->disable = rtl8153_disable;
+ ops->up = rtl8153_up;
ops->down = rtl8153_down;
ops->unload = rtl8153_unload;
ret = 0;
@@ -3416,8 +3444,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
case PRODUCT_ID_SAMSUNG:
ops->init = r8153_init;
ops->enable = rtl8153_enable;
- ops->disable = rtl8152_disable;
- ops->up = r8153_first_init;
+ ops->disable = rtl8153_disable;
+ ops->up = rtl8153_up;
ops->down = rtl8153_down;
ops->unload = rtl8153_unload;
ret = 0;
--
1.9.3
^ permalink raw reply related
* Re: [PATCH net-next] net: keep original skb which only needs header checking during software GSO
From: Eric Dumazet @ 2014-09-19 7:04 UTC (permalink / raw)
To: Jason Wang; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1411108686-20602-1-git-send-email-jasowang@redhat.com>
On Fri, 2014-09-19 at 14:38 +0800, Jason Wang wrote:
> Commit ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
> around original SKB when we software segment GSO frames") frees the
> original skb after software GSO even for dodgy gso skbs. This breaks
> the stream throughput from untrusted sources, since only header
> checking was done during software GSO instead of a true
> segmentation. This patch fixes this by freeing the original gso skb
> only when it was really segmented by software.
>
> Fixes ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
> around original SKB when we software segment GSO frames.")
>
> CC: David S. Miller <davem@davemloft.net>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> net/core/dev.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index e916ba8..b7a0e1d 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2694,10 +2694,12 @@ struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev)
> struct sk_buff *segs;
>
> segs = skb_gso_segment(skb, features);
> - kfree_skb(skb);
> if (IS_ERR(segs))
>
> - skb = segs;
> + else if (segs) {
> + kfree_skb(skb);
> + skb = segs;
> + }
> } else {
> if (skb_needs_linearize(skb, features) &&
> __skb_linearize(skb))
Good catch !
While we are at it, could you use consume_skb() instead of kfree_skb(),
and add missing {} (CodingStyle) ?
if (IS_ERR(segs)) {
segs = NULL;
} else if (segs) {
consume_skb(skb);
skb = segs;
}
Thanks !
^ permalink raw reply
* [PATCH] net: fec: fix code identation
From: Fugang Duan @ 2014-09-19 6:26 UTC (permalink / raw)
To: davem; +Cc: netdev, dan.carpenter, b38611
There have extra identation before .skb_copy_to_linear_data_offset(),
this patch just remove the identation.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Fugang Duan <B38611@freescale.com>
---
drivers/net/ethernet/freescale/fec_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 6e93336..bf3fd15 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1415,7 +1415,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN));
if (vlan_packet_rcvd)
payload_offset = (2 * ETH_ALEN) + VLAN_HLEN;
- skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN),
+ skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN),
data + payload_offset,
pkt_len - 4 - (2 * ETH_ALEN));
--
1.7.8
^ permalink raw reply related
* [PATCH net-next] net: keep original skb which only needs header checking during software GSO
From: Jason Wang @ 2014-09-19 6:38 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: Jason Wang
Commit ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
around original SKB when we software segment GSO frames") frees the
original skb after software GSO even for dodgy gso skbs. This breaks
the stream throughput from untrusted sources, since only header
checking was done during software GSO instead of a true
segmentation. This patch fixes this by freeing the original gso skb
only when it was really segmented by software.
Fixes ce93718fb7cdbc064c3000ff59e4d3200bdfa744 ("net: Don't keep
around original SKB when we software segment GSO frames.")
CC: David S. Miller <davem@davemloft.net>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/core/dev.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index e916ba8..b7a0e1d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2694,10 +2694,12 @@ struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev)
struct sk_buff *segs;
segs = skb_gso_segment(skb, features);
- kfree_skb(skb);
if (IS_ERR(segs))
segs = NULL;
- skb = segs;
+ else if (segs) {
+ kfree_skb(skb);
+ skb = segs;
+ }
} else {
if (skb_needs_linearize(skb, features) &&
__skb_linearize(skb))
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net-next] bnx2x: set gso_segs in LRO mode
From: Eric Dumazet @ 2014-09-19 5:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Ariel Elior
In-Reply-To: <1411073324.7106.294.camel@edumazet-glaptop2.roam.corp.google.com>
On Thu, 2014-09-18 at 13:48 -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> In commits cbf1de72324a8 ("bnx2x: fix GRO parameters"), and
> ab5777d748302 ("bnx2x: Get gso_segs from FW")
> special care was taken for GRO mode.
>
> We can also get proper gso_segs for LRO mode.
>
> This helps to get proper values for these SNMP counters, which should
> count number of segments. This also helps qdisc_pkt_len_init() to better
> track packet sizes when ingress qdisc is in place.
>
> IpExtInNoECTPkts 63458
> IpExtInECT0Pkts 8772480
> IpExtInCEPkts 1390713
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
Please disregard this patch. Its not needed, as bnx2x_gro_receive() is
called even in LRO mode...
^ permalink raw reply
* [PATCH net 2/2] net: bcmgenet: call bcmgenet_dma_teardown in bcmgenet_fini_dma
From: Florian Fainelli @ 2014-09-19 0:48 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411087697-19306-1-git-send-email-f.fainelli@gmail.com>
We should not be manipulaging the DMA_CTRL registers directly by writing
0 to them to disable DMA. This is an operation that needs to be timed to
make sure the DMA engines have been properly stopped since their state
machine stops on a packet boundary, not immediately.
Make sure that tha bcmgenet_fini_dma() calls bcmgenet_dma_teardown() to
ensure a proper DMA engine state.
Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 11a96437862d..5d9eac37993d 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1749,8 +1749,7 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
int i;
/* disable DMA */
- bcmgenet_rdma_writel(priv, 0, DMA_CTRL);
- bcmgenet_tdma_writel(priv, 0, DMA_CTRL);
+ bcmgenet_dma_teardown(priv);
for (i = 0; i < priv->num_tx_bds; i++) {
if (priv->tx_cbs[i].skb != NULL) {
--
1.9.1
^ permalink raw reply related
* [PATCH net 1/2] net: bcmgenet: fix TX reclaim accounting for fragments
From: Florian Fainelli @ 2014-09-19 0:48 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411087697-19306-1-git-send-email-f.fainelli@gmail.com>
The GENET driver supports SKB fragments, and succeeds in transmitting
them properly, but when reclaiming these transmitted fragments, we will
only update the count of free buffer descriptors by 1, even for SKBs
with fragments. This leads to the networking stack thinking it has more
room than the hardware has when pushing new SKBs, and backing off
consequently because we return NETDEV_TX_BUSY.
Fix this by accounting for the SKB nr_frags plus one (itself) and update
ring->free_bds accordingly with that value for each iteration loop in
__bcmgenet_tx_reclaim().
Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index cdef86a03862..11a96437862d 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -875,6 +875,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
int last_tx_cn, last_c_index, num_tx_bds;
struct enet_cb *tx_cb_ptr;
struct netdev_queue *txq;
+ unsigned int bds_compl;
unsigned int c_index;
/* Compute how many buffers are transmitted since last xmit call */
@@ -899,7 +900,9 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
/* Reclaim transmitted buffers */
while (last_tx_cn-- > 0) {
tx_cb_ptr = ring->cbs + last_c_index;
+ bds_compl = 0;
if (tx_cb_ptr->skb) {
+ bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1;
dev->stats.tx_bytes += tx_cb_ptr->skb->len;
dma_unmap_single(&dev->dev,
dma_unmap_addr(tx_cb_ptr, dma_addr),
@@ -916,7 +919,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0);
}
dev->stats.tx_packets++;
- ring->free_bds += 1;
+ ring->free_bds += bds_compl;
last_c_index++;
last_c_index &= (num_tx_bds - 1);
--
1.9.1
^ permalink raw reply related
* [PATCH net 0/2] net: bcmgenet: TX reclaim and DMA fixes
From: Florian Fainelli @ 2014-09-19 0:48 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
Hi David,
This patch set contains one fix for an accounting problem while reclaiming
transmitted buffers having fragments, and the second fix is to make sure
that the DMA shutdown is properly controlled.
Florian Fainelli (2):
net: bcmgenet: fix TX reclaim accounting for fragments
net: bcmgenet: call bcmgenet_dma_teardown in bcmgenet_fini_dma
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH net-next 4/4] net: dsa: bcm_sf2: add support for Wake-on-LAN
From: Florian Fainelli @ 2014-09-19 0:31 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411086685-18684-1-git-send-email-f.fainelli@gmail.com>
In order for Wake-on-LAN to work properly, we query the parent network
device Wake-on-LAN features and advertise those. Similarly, when
configuring Wake-on-LAN on a per-port network interface, we make sure
that we do not accept something the master network devices does not
support.
Finally, we need to maintain a bitmask of the ports enabled for
Wake-on-LAN to prevent the suspend() callback from disabling a port that
is used for waking up the system.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/bcm_sf2.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/bcm_sf2.h | 3 +++
2 files changed, 61 insertions(+)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 77b5a64560fa..e1f88de19145 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <net/dsa.h>
+#include <linux/ethtool.h>
#include "bcm_sf2.h"
#include "bcm_sf2_regs.h"
@@ -242,6 +243,9 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port)
struct bcm_sf2_priv *priv = ds_to_priv(ds);
u32 off, reg;
+ if (priv->wol_ports_mask & (1 << port))
+ return;
+
if (dsa_is_cpu_port(ds, port))
off = CORE_IMP_CTL;
else
@@ -674,6 +678,58 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
return 0;
}
+static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol)
+{
+ struct net_device *p = ds->dst[ds->index].master_netdev;
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ struct ethtool_wolinfo pwol;
+
+ /* Get the parent device WoL settings */
+ p->ethtool_ops->get_wol(p, &pwol);
+
+ /* Advertise the parent device supported settings */
+ wol->supported = pwol.supported;
+ memset(&wol->sopass, 0, sizeof(wol->sopass));
+
+ if (pwol.wolopts & WAKE_MAGICSECURE)
+ memcpy(&wol->sopass, pwol.sopass, sizeof(wol->sopass));
+
+ if (priv->wol_ports_mask & (1 << port))
+ wol->wolopts = pwol.wolopts;
+ else
+ wol->wolopts = 0;
+}
+
+static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol)
+{
+ struct net_device *p = ds->dst[ds->index].master_netdev;
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ s8 cpu_port = ds->dst[ds->index].cpu_port;
+ struct ethtool_wolinfo pwol;
+
+ p->ethtool_ops->get_wol(p, &pwol);
+ if (wol->wolopts & ~pwol.supported)
+ return -EINVAL;
+
+ if (wol->wolopts)
+ priv->wol_ports_mask |= (1 << port);
+ else
+ priv->wol_ports_mask &= ~(1 << port);
+
+ /* If we have at least one port enabled, make sure the CPU port
+ * is also enabled. If the CPU port is the last one enabled, we disable
+ * it since this configuration does not make sense.
+ */
+ if (priv->wol_ports_mask && priv->wol_ports_mask != (1 << cpu_port))
+ priv->wol_ports_mask |= (1 << cpu_port);
+ else
+ priv->wol_ports_mask &= ~(1 << cpu_port);
+
+ return p->ethtool_ops->set_wol(p, wol);
+}
+
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
.priv_size = sizeof(struct bcm_sf2_priv),
@@ -689,6 +745,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
.fixed_link_update = bcm_sf2_sw_fixed_link_update,
.suspend = bcm_sf2_sw_suspend,
.resume = bcm_sf2_sw_resume,
+ .get_wol = bcm_sf2_sw_get_wol,
+ .set_wol = bcm_sf2_sw_set_wol,
};
static int __init bcm_sf2_init(void)
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index 260bab313e58..49e52c5d64b4 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -69,6 +69,9 @@ struct bcm_sf2_priv {
struct bcm_sf2_hw_params hw_params;
struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS];
+
+ /* Mask of ports enabled for Wake-on-LAN */
+ u32 wol_ports_mask;
};
struct bcm_sf2_hw_stats {
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 3/4] net: dsa: add {get,set}_wol callbacks to slave devices
From: Florian Fainelli @ 2014-09-19 0:31 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411086685-18684-1-git-send-email-f.fainelli@gmail.com>
Allow switch drivers to implement per-port Wake-on-LAN getter and
setters.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/dsa.h | 8 ++++++++
net/dsa/slave.c | 23 +++++++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 0a34bf3d1ddd..1de4efff4e42 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -211,6 +211,14 @@ struct dsa_switch_driver {
int (*get_sset_count)(struct dsa_switch *ds);
/*
+ * ethtool Wake-on-LAN
+ */
+ void (*get_wol)(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *w);
+ int (*set_wol)(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *w);
+
+ /*
* Suspend and resume
*/
int (*suspend)(struct dsa_switch *ds);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e11c9bdca6e6..db53c1bf998c 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -301,6 +301,27 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
return -EOPNOTSUPP;
}
+static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->parent;
+
+ if (ds->drv->get_wol)
+ ds->drv->get_wol(ds, p->port, w);
+}
+
+static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->parent;
+ int ret = -EOPNOTSUPP;
+
+ if (ds->drv->set_wol)
+ ret = ds->drv->set_wol(ds, p->port, w);
+
+ return ret;
+}
+
static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_settings = dsa_slave_get_settings,
.set_settings = dsa_slave_set_settings,
@@ -310,6 +331,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_strings = dsa_slave_get_strings,
.get_ethtool_stats = dsa_slave_get_ethtool_stats,
.get_sset_count = dsa_slave_get_sset_count,
+ .set_wol = dsa_slave_set_wol,
+ .get_wol = dsa_slave_get_wol,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/4] net: dsa: bcm_sf2: add suspend/resume callbacks
From: Florian Fainelli @ 2014-09-19 0:31 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411086685-18684-1-git-send-email-f.fainelli@gmail.com>
Implement the suspend/resume callbacks for the Broadcom Starfighter 2
switch driver. Suspending the switch requires masking interrupts and
shutting down ports. Resuming the switch requires a software reset since
we do not know which power-sate we might be coming from, and re-enabling
the physical ports that are used.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/bcm_sf2.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 02d7db320d90..77b5a64560fa 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -591,6 +591,89 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
status->pause = 1;
}
+static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
+{
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ unsigned int port;
+
+ intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
+ intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
+ intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+ intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
+ intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
+ intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+
+ /* Disable all ports physically present including the IMP
+ * port, the other ones have already been disabled during
+ * bcm_sf2_sw_setup
+ */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if ((1 << port) & ds->phys_port_mask ||
+ dsa_is_cpu_port(ds, port))
+ bcm_sf2_port_disable(ds, port);
+ }
+
+ return 0;
+}
+
+static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
+{
+ unsigned int timeout = 1000;
+ u32 reg;
+
+ reg = core_readl(priv, CORE_WATCHDOG_CTRL);
+ reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
+ core_writel(priv, reg, CORE_WATCHDOG_CTRL);
+
+ do {
+ reg = core_readl(priv, CORE_WATCHDOG_CTRL);
+ if (!(reg & SOFTWARE_RESET))
+ break;
+
+ usleep_range(1000, 2000);
+ } while (timeout-- > 0);
+
+ if (timeout == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int bcm_sf2_sw_resume(struct dsa_switch *ds)
+{
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ unsigned int port;
+ u32 reg;
+ int ret;
+
+ ret = bcm_sf2_sw_rst(priv);
+ if (ret) {
+ pr_err("%s: failed to software reset switch\n", __func__);
+ return ret;
+ }
+
+ /* Reinitialize the single GPHY */
+ if (priv->hw_params.num_gphy == 1) {
+ reg = reg_readl(priv, REG_SPHY_CNTRL);
+ reg |= PHY_RESET;
+ reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS);
+ reg_writel(priv, reg, REG_SPHY_CNTRL);
+ udelay(21);
+ reg = reg_readl(priv, REG_SPHY_CNTRL);
+ reg &= ~PHY_RESET;
+ reg_writel(priv, reg, REG_SPHY_CNTRL);
+ }
+
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if ((1 << port) & ds->phys_port_mask)
+ bcm_sf2_port_setup(ds, port);
+ else if (dsa_is_cpu_port(ds, port))
+ bcm_sf2_imp_setup(ds, port);
+ }
+
+ return 0;
+}
+
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
.priv_size = sizeof(struct bcm_sf2_priv),
@@ -604,6 +687,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
.get_sset_count = bcm_sf2_sw_get_sset_count,
.adjust_link = bcm_sf2_sw_adjust_link,
.fixed_link_update = bcm_sf2_sw_fixed_link_update,
+ .suspend = bcm_sf2_sw_suspend,
+ .resume = bcm_sf2_sw_resume,
};
static int __init bcm_sf2_init(void)
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 1/4] net: dsa: allow switch drivers to implement suspend/resume hooks
From: Florian Fainelli @ 2014-09-19 0:31 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
In-Reply-To: <1411086685-18684-1-git-send-email-f.fainelli@gmail.com>
Add an abstraction layer to suspend/resume switch devices, doing the
following split:
- suspend/resume the slave network devices and their corresponding PHY
devices
- suspend/resume the switch hardware using switch driver callbacks
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/dsa.h | 6 ++++
net/dsa/dsa.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
net/dsa/dsa_priv.h | 2 ++
net/dsa/slave.c | 31 +++++++++++++++++++++
4 files changed, 119 insertions(+)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index c779e9bba1b3..0a34bf3d1ddd 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -209,6 +209,12 @@ struct dsa_switch_driver {
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
int (*get_sset_count)(struct dsa_switch *ds);
+
+ /*
+ * Suspend and resume
+ */
+ int (*suspend)(struct dsa_switch *ds);
+ int (*resume)(struct dsa_switch *ds);
};
void register_switch_driver(struct dsa_switch_driver *type);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6e40928ec0e7..6905f2d84c44 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -238,6 +238,49 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
{
}
+static int dsa_switch_suspend(struct dsa_switch *ds)
+{
+ int i, ret = 0;
+
+ /* Suspend slave network devices */
+ for (i = 0; i < DSA_MAX_PORTS; i++) {
+ if (!(ds->phys_port_mask & (1 << i)))
+ continue;
+
+ ret = dsa_slave_suspend(ds->ports[i]);
+ if (ret)
+ return ret;
+ }
+
+ if (ds->drv->suspend)
+ ret = ds->drv->suspend(ds);
+
+ return ret;
+}
+
+static int dsa_switch_resume(struct dsa_switch *ds)
+{
+ int i, ret = 0;
+
+ if (ds->drv->resume)
+ ret = ds->drv->resume(ds);
+
+ if (ret)
+ return ret;
+
+ /* Resume slave network devices */
+ for (i = 0; i < DSA_MAX_PORTS; i++) {
+ if (!(ds->phys_port_mask & (1 << i)))
+ continue;
+
+ ret = dsa_slave_resume(ds->ports[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
/* link polling *************************************************************/
static void dsa_link_poll_work(struct work_struct *ugly)
@@ -650,6 +693,42 @@ static struct packet_type dsa_pack_type __read_mostly = {
.func = dsa_switch_rcv,
};
+#ifdef CONFIG_PM_SLEEP
+static int dsa_suspend(struct device *d)
+{
+ struct platform_device *pdev = to_platform_device(d);
+ struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
+ int i, ret = 0;
+
+ for (i = 0; i < dst->pd->nr_chips; i++) {
+ struct dsa_switch *ds = dst->ds[i];
+
+ if (ds != NULL)
+ ret = dsa_switch_suspend(ds);
+ }
+
+ return ret;
+}
+
+static int dsa_resume(struct device *d)
+{
+ struct platform_device *pdev = to_platform_device(d);
+ struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
+ int i, ret = 0;
+
+ for (i = 0; i < dst->pd->nr_chips; i++) {
+ struct dsa_switch *ds = dst->ds[i];
+
+ if (ds != NULL)
+ ret = dsa_switch_resume(ds);
+ }
+
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume);
+
static const struct of_device_id dsa_of_match_table[] = {
{ .compatible = "brcm,bcm7445-switch-v4.0" },
{ .compatible = "marvell,dsa", },
@@ -665,6 +744,7 @@ static struct platform_driver dsa_driver = {
.name = "dsa",
.owner = THIS_MODULE,
.of_match_table = dsa_of_match_table,
+ .pm = &dsa_pm_ops,
},
};
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index f90899e8ab5a..dc9756d3154c 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -56,6 +56,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds);
struct net_device *dsa_slave_create(struct dsa_switch *ds,
struct device *parent,
int port, char *name);
+int dsa_slave_suspend(struct net_device *slave_dev);
+int dsa_slave_resume(struct net_device *slave_dev);
/* tag_dsa.c */
extern const struct dsa_device_ops dsa_netdev_ops;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 90c9689ed362..e11c9bdca6e6 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -408,6 +408,37 @@ static void dsa_slave_phy_setup(struct dsa_slave_priv *p,
p->phy->addr, p->phy->drv->name);
}
+int dsa_slave_suspend(struct net_device *slave_dev)
+{
+ struct dsa_slave_priv *p = netdev_priv(slave_dev);
+
+ netif_device_detach(slave_dev);
+
+ if (p->phy) {
+ phy_stop(p->phy);
+ p->old_pause = -1;
+ p->old_link = -1;
+ p->old_duplex = -1;
+ phy_suspend(p->phy);
+ }
+
+ return 0;
+}
+
+int dsa_slave_resume(struct net_device *slave_dev)
+{
+ struct dsa_slave_priv *p = netdev_priv(slave_dev);
+
+ netif_device_attach(slave_dev);
+
+ if (p->phy) {
+ phy_resume(p->phy);
+ phy_start(p->phy);
+ }
+
+ return 0;
+}
+
struct net_device *
dsa_slave_create(struct dsa_switch *ds, struct device *parent,
int port, char *name)
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 0/4] dsa: Broadcom SF2 suspend/resume and WoL
From: Florian Fainelli @ 2014-09-19 0:31 UTC (permalink / raw)
To: netdev; +Cc: davem, Florian Fainelli
Hi David,
This patch add supports for suspend/resume and configuring Wake-on-LAN
for Broadcom Starfighter 2 switches.
Thank you!
Florian Fainelli (4):
net: dsa: allow switch drivers to implement suspend/resume hooks
net: dsa: bcm_sf2: add suspend/resume callbacks
net: dsa: add {get,set}_wol callbacks to slave devices
net: dsa: bcm_sf2: add support for Wake-on-LAN
drivers/net/dsa/bcm_sf2.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/bcm_sf2.h | 3 +
include/net/dsa.h | 14 +++++
net/dsa/dsa.c | 80 ++++++++++++++++++++++++++
net/dsa/dsa_priv.h | 2 +
net/dsa/slave.c | 54 +++++++++++++++++
6 files changed, 296 insertions(+)
--
1.9.1
^ permalink raw reply
* Re: [PATCH net-next] net: bpf: arm: make hole-faulting more robust
From: Daniel Borkmann @ 2014-09-18 23:20 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: davem, netdev, Will Deacon, Mircea Gherzan, Catalin Marinas,
linux-arm-kernel, Alexei Starovoitov
In-Reply-To: <20140918231154.GH5182@n2100.arm.linux.org.uk>
On 09/19/2014 01:11 AM, Russell King - ARM Linux wrote:
> On Fri, Sep 19, 2014 at 12:57:03AM +0200, Daniel Borkmann wrote:
>> Will Deacon pointed out, that the currently used opcode for filling holes,
>> that is 0xe7ffffff, seems not robust enough ...
>
> If you're after a single 32-bit word which will fault if executed in
> ARM or Thumb mode, and you only want it to raise an undefined
> instruction exception (iow, you're not using it as a breakpoint or
> similar), then may I suggest the poison value I chose for the vectors
> page, designed to trap userspace branches to locations in there?
>
> 0xe7fddef1
>
>> Similarly, ptrace, kprobes, kgdb, bug and uprobes make use of such instruction
>> as well to trap. Given mentioned section from the specification, we can find
>> such a universe as (where 'x' denotes 'don't care'):
>>
>> ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
>> Thumb: 1101 1110 xxxx xxxx
>
> You'll notice that the value conforms to the ARM undefined instruction
> space. You'll also notice that the low 16 bits correspond to the
> Thumb case. The only question is, what is 0xe7fd as a Thumb instruction...
>
> 00000000 <a>:
> 0: def1 ; <UNDEFINED> instruction: 0xdef1
> 2: e7fd b.n 0 <a>
>
> So, if either 0 or 2 gets branched to, we end up at the Thumb UDF
> instruction. (Sorry, my binutils doesn't know about UDF.)
Yes, that should keep the code even simpler! Will try that out tomorrow
and respin the patch.
Thanks Russell!
^ permalink raw reply
* Re: [PATCH net-next] net: bpf: arm: make hole-faulting more robust
From: Russell King - ARM Linux @ 2014-09-18 23:11 UTC (permalink / raw)
To: Daniel Borkmann
Cc: davem, netdev, Will Deacon, Mircea Gherzan, Catalin Marinas,
linux-arm-kernel, Alexei Starovoitov
In-Reply-To: <1411081023-17874-1-git-send-email-dborkman@redhat.com>
On Fri, Sep 19, 2014 at 12:57:03AM +0200, Daniel Borkmann wrote:
> Will Deacon pointed out, that the currently used opcode for filling holes,
> that is 0xe7ffffff, seems not robust enough ...
If you're after a single 32-bit word which will fault if executed in
ARM or Thumb mode, and you only want it to raise an undefined
instruction exception (iow, you're not using it as a breakpoint or
similar), then may I suggest the poison value I chose for the vectors
page, designed to trap userspace branches to locations in there?
0xe7fddef1
> Similarly, ptrace, kprobes, kgdb, bug and uprobes make use of such instruction
> as well to trap. Given mentioned section from the specification, we can find
> such a universe as (where 'x' denotes 'don't care'):
>
> ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
> Thumb: 1101 1110 xxxx xxxx
You'll notice that the value conforms to the ARM undefined instruction
space. You'll also notice that the low 16 bits correspond to the
Thumb case. The only question is, what is 0xe7fd as a Thumb instruction...
00000000 <a>:
0: def1 ; <UNDEFINED> instruction: 0xdef1
2: e7fd b.n 0 <a>
So, if either 0 or 2 gets branched to, we end up at the Thumb UDF
instruction. (Sorry, my binutils doesn't know about UDF.)
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH] tg3: Work around HW/FW limitations with vlan encapsulated frames
From: Prashant Sreedharan @ 2014-09-18 23:00 UTC (permalink / raw)
To: Vladislav Yasevich; +Cc: netdev, Vladislav Yasevich, Michael Chan
In-Reply-To: <1411050677-28147-1-git-send-email-vyasevic@redhat.com>
On Thu, 2014-09-18 at 10:31 -0400, Vladislav Yasevich wrote:
> TG3 appears to have an issue performing TSO and checksum offloading
> correclty when the frame has been vlan encapsulated (non-accelrated).
> In these cases, tcp checksum is not correctly updated.
Yes that is true for inline vlan headers, to clarify was TSO and
checksum offload working for accelerated 802.1ad packets ?
> This patch attempts to work around this issue. After the patch,
> 802.1ad vlans start working correctly over tg3 devices.
>
> CC: Prashant Sreedharan <prashant@broadcom.com>
> CC: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
> ---
> drivers/net/ethernet/broadcom/tg3.c | 20 ++++++++++++++++++--
> 1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
> index cb77ae9..e7d3a62 100644
> --- a/drivers/net/ethernet/broadcom/tg3.c
> +++ b/drivers/net/ethernet/broadcom/tg3.c
> @@ -7914,8 +7914,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
>
> entry = tnapi->tx_prod;
> base_flags = 0;
> - if (skb->ip_summed == CHECKSUM_PARTIAL)
> - base_flags |= TXD_FLAG_TCPUDP_CSUM;
>
> mss = skb_shinfo(skb)->gso_size;
> if (mss) {
> @@ -7929,6 +7927,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
>
> hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
>
> + /* HW/FW can not correctly segment packets that have been
> + * vlan encapsulated.
> + */
> + if (skb->protocol == htons(ETH_P_8021Q) ||
> + skb->protocol == htons(ETH_P_8021AD))
> + return tg3_tso_bug(tp, tnapi, txq, skb);
I think skb_gso_segment() would return skbs that would still have
checksum offloaded to the chip.
> +
> if (!skb_is_gso_v6(skb)) {
> if (unlikely((ETH_HLEN + hdr_len) > 80) &&
> tg3_flag(tp, TSO_BUG))
> @@ -7979,6 +7984,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
> base_flags |= tsflags << 12;
> }
> }
> + } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
> + /* HW/FW can not correctly checksum packets that have been
> + * vlan encapsulated.
> + */
> + if (skb->protocol == htons(ETH_P_8021Q) ||
> + skb->protocol == htons(ETH_P_8021AD)) {
> + if (skb_checksum_help(skb))
> + goto drop;
> + } else {
> + base_flags |= TXD_FLAG_TCPUDP_CSUM;
> + }
> }
>
> if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
Instead of the above workarounds since the chips supported by tg3 does
not support checksum offload and TSO for inline vlan headers, these
features can be disabled/cleared in dev->vlan_features. Side effect is
accelerated vlan headers will also have TSO and checksum offload
disabled.
Also as part of this review, found a problem with the receive section of
the driver it was not checking for 802.1ad vlan protocol and dropping
802.1ad vlan packets of size > mtu + ETH_HLEN
diff --git a/drivers/net/ethernet/broadcom/tg3.c
b/drivers/net/ethernet/broadcom/tg3.c
index cb77ae9..620887a 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6918,7 +6918,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int
budget)
skb->protocol = eth_type_trans(skb, tp->dev);
if (len > (tp->dev->mtu + ETH_HLEN) &&
- skb->protocol != htons(ETH_P_8021Q)) {
+ skb->protocol != htons(ETH_P_8021Q) &&
+ skb->protocol != htons(ETH_P_8021AD)) {
dev_kfree_skb_any(skb);
goto drop_it_no_recycle;
}
^ permalink raw reply related
* [PATCH net-next] net: bpf: arm: make hole-faulting more robust
From: Daniel Borkmann @ 2014-09-18 22:57 UTC (permalink / raw)
To: davem
Cc: netdev, linux-arm-kernel, Catalin Marinas, Will Deacon,
Mircea Gherzan, Alexei Starovoitov
Will Deacon pointed out, that the currently used opcode for filling holes,
that is 0xe7ffffff, seems not robust enough ...
$ echo 0xffffffe7 | xxd -r > test.bin
$ arm-linux-gnueabihf-objdump -m arm -D -b binary test.bin
...
0: e7ffffff udf #65535 ; 0xffff
... while for Thumb, it ends up as ...
0: ffff e7ff vqshl.u64 q15, <illegal reg q15.5>, #63
... which is a bit fragile. The ARM specification defines some *permanently*
guaranteed undefined instruction (UDF) space, for example for ARM in ARMv7-AR,
section A5.4 and for Thumb in ARMv7-M, section A5.2.6.
Similarly, ptrace, kprobes, kgdb, bug and uprobes make use of such instruction
as well to trap. Given mentioned section from the specification, we can find
such a universe as (where 'x' denotes 'don't care'):
ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
Thumb: 1101 1110 xxxx xxxx
We therefore can use a more robust and so far unallocated pair of opcodes
for ARM: 0xe7f002f0 and Thumb: 0xde03. Moreover, when filling we should also
use proper macros __opcode_to_mem_arm() and __opcode_to_mem_thumb16().
New dump:
$ echo 0xf002f0e7 | xxd -r > test.bin
$ arm-unknown-linux-gnueabi-objdump -m arm -D -b binary test.bin
...
0: e7f002f0 udf #32
$ echo 0x03de | xxd -r > test.bin
$ arm-unknown-linux-gnueabi-objdump -marm -Mforce-thumb -D -b binary test.bin
...
0: de03 udf #3
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mircea Gherzan <mgherzan@gmail.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
---
arch/arm/net/bpf_jit_32.c | 22 ++++++++++++++++++----
arch/arm/net/bpf_jit_32.h | 15 +++++++++++++++
2 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 6b45f64..3b71b68 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/if_vlan.h>
+
#include <asm/cacheflush.h>
#include <asm/hwcap.h>
#include <asm/opcodes.h>
@@ -173,13 +174,26 @@ static inline bool is_load_to_a(u16 inst)
}
}
+static void __jit_fill_hole_arm(u32 *ptr, unsigned int bytes)
+{
+ for (; bytes >= sizeof(u32); bytes -= sizeof(u32))
+ *ptr++ = __opcode_to_mem_arm(ARM_INST_UDF);
+}
+
+static void __jit_fill_hole_thumb2(u16 *ptr, unsigned int bytes)
+{
+ for (; bytes >= sizeof(u16); bytes -= sizeof(u16))
+ *ptr++ = __opcode_to_mem_thumb16(THUMB2_INST_UDF);
+}
+
static void jit_fill_hole(void *area, unsigned int size)
{
- /* Insert illegal UND instructions. */
- u32 *ptr, fill_ins = 0xe7ffffff;
+ const bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
/* We are guaranteed to have aligned memory. */
- for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
- *ptr++ = fill_ins;
+ if (thumb2)
+ __jit_fill_hole_thumb2(area, size);
+ else
+ __jit_fill_hole_arm(area, size);
}
static void build_prologue(struct jit_ctx *ctx)
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index afb8462..4982db8 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -114,6 +114,21 @@
#define ARM_INST_UMULL 0x00800090
+/*
+ * Use a suitable undefined instruction to use for ARM/Thumb2 faulting.
+ * We need to be careful not to conflict with those used by other modules
+ * (BUG, kprobes, etc) and the register_undef_hook() system.
+ *
+ * The ARM architecture reference manual guarantees that the following
+ * instruction space will produce an undefined instruction exception on
+ * all CPUs:
+ *
+ * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx ARMv7-AR, section A5.4
+ * Thumb: 1101 1110 xxxx xxxx ARMv7-M, section A5.2.6
+ */
+#define ARM_INST_UDF 0xe7f002f0
+#define THUMB2_INST_UDF 0xde03
+
/* register */
#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm))
/* immediate */
--
1.9.3
^ permalink raw reply related
* [net-next PATCH 29/29] fm10k: Add support for PTP
From: Alexander Duyck @ 2014-09-18 22:40 UTC (permalink / raw)
To: davem
Cc: nhorman, netdev, john.fastabend, matthew.vick, jeffrey.t.kirsher,
sassmann
In-Reply-To: <20140918223242.10373.27403.stgit@ahduyck-bv4.jf.intel.com>
This change adds support for the Linux PTP Hardware clock and timestamping
functionality provided by the hardware. There are actually two cases that
this timestamping is meant to support.
The first case would be an ordinary clock scenario. In this configuration
the host interface does not have access to BAR 4. However all of the host
interfaces should be locked into the same boundary clock region and as such
they are all on the same clock anyway. With this being the case they can
synchronize among themselves and only need to adjust the offset since they
are all on the same clock with the same frequency.
The second case is a boundary clock scenario. This is a special case and
would require both BAR 4 access, and a means of presenting a netdev per
boundary region. The current plan is to use DSA at some point in the
future to provide these interfaces, but the DSA portion is still under
development.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/ethernet/intel/fm10k/Makefile | 2
drivers/net/ethernet/intel/fm10k/fm10k.h | 35 +
drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 30 +
drivers/net/ethernet/intel/fm10k/fm10k_main.c | 20 +
drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 17 +
drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 113 +++++
drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 535 ++++++++++++++++++++++
drivers/net/ethernet/intel/fm10k/fm10k_type.h | 7
8 files changed, 751 insertions(+), 8 deletions(-)
create mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_ptp.c
diff --git a/drivers/net/ethernet/intel/fm10k/Makefile b/drivers/net/ethernet/intel/fm10k/Makefile
index fbc0e09..08859dd 100644
--- a/drivers/net/ethernet/intel/fm10k/Makefile
+++ b/drivers/net/ethernet/intel/fm10k/Makefile
@@ -30,4 +30,4 @@ obj-$(CONFIG_FM10K) += fm10k.o
fm10k-objs := fm10k_main.o fm10k_common.o fm10k_pci.o \
fm10k_netdev.o fm10k_ethtool.o fm10k_pf.o fm10k_vf.o \
fm10k_mbx.o fm10k_iov.o fm10k_tlv.o \
- fm10k_debugfs.o fm10k_dcbnl.o
+ fm10k_debugfs.o fm10k_ptp.o fm10k_dcbnl.o
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index c355456..bdb1dbf 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -26,6 +26,9 @@
#include <linux/rtnetlink.h>
#include <linux/if_vlan.h>
#include <linux/pci.h>
+#include <linux/net_tstamp.h>
+#include <linux/clocksource.h>
+#include <linux/ptp_clock_kernel.h>
#include "fm10k_pf.h"
#include "fm10k_vf.h"
@@ -293,6 +296,7 @@ struct fm10k_intfc {
struct fm10k_hw_stats stats;
struct fm10k_hw hw;
u32 __iomem *uc_addr;
+ u32 __iomem *sw_addr;
u16 msg_enable;
u16 tx_ring_count;
u16 rx_ring_count;
@@ -314,6 +318,17 @@ struct fm10k_intfc {
struct dentry *dbg_intfc;
#endif /* CONFIG_DEBUG_FS */
+ struct ptp_clock_info ptp_caps;
+ struct ptp_clock *ptp_clock;
+
+ struct sk_buff_head ts_tx_skb_queue;
+ u32 tx_hwtstamp_timeouts;
+
+ struct delayed_work ts_overflow_work;
+ struct hwtstamp_config ts_config;
+ struct cyclecounter cc;
+ struct timecounter tc;
+ rwlock_t tsreg_lock;
#if defined(HAVE_DCBNL_IEEE) && defined(CONFIG_DCB)
u8 pfc_en;
#endif
@@ -411,6 +426,10 @@ union fm10k_ftag_info {
};
struct fm10k_cb {
+ union {
+ __le64 tstamp;
+ unsigned long ts_tx_timeout;
+ };
union fm10k_ftag_info fi;
};
@@ -492,6 +511,22 @@ static inline void fm10k_dbg_init(void) {}
static inline void fm10k_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS */
+/* Time Stamping */
+void fm10k_ts_cc_to_hwtstamp(struct fm10k_intfc *interface,
+ struct skb_shared_hwtstamps *hwtstamp,
+ cycle_t systime);
+void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb);
+void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort,
+ cycle_t systime);
+void fm10k_ts_reset_cc(struct fm10k_intfc *interface);
+void fm10k_ts_start_cc(struct fm10k_intfc *interface);
+void fm10k_ts_stop_cc(struct fm10k_intfc *interface);
+void fm10k_ts_tx_subtask(struct fm10k_intfc *interface);
+void fm10k_ptp_register(struct fm10k_intfc *interface);
+void fm10k_ptp_unregister(struct fm10k_intfc *interface);
+int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
+int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
+
/* DCB */
void fm10k_dcbnl_set_ops(struct net_device *dev);
#endif /* _FM10K_H_ */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
index 42beb89..a9bbe60 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
@@ -91,6 +91,8 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = {
FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages),
FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords),
FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err),
+
+ FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
};
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_stats)
@@ -1006,6 +1008,33 @@ static int fm10k_set_channels(struct net_device *dev,
return fm10k_setup_tc(dev, netdev_get_num_tc(dev));
}
+static int fm10k_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ struct fm10k_intfc *interface = netdev_priv(dev);
+
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ if (interface->ptp_clock)
+ info->phc_index = ptp_clock_index(interface->ptp_clock);
+ else
+ info->phc_index = -1;
+
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static const struct ethtool_ops fm10k_ethtool_ops = {
.get_strings = fm10k_get_strings,
.get_sset_count = fm10k_get_sset_count,
@@ -1031,6 +1060,7 @@ static const struct ethtool_ops fm10k_ethtool_ops = {
.set_rxfh = fm10k_set_rssh,
.get_channels = fm10k_get_channels,
.set_channels = fm10k_set_channels,
+ .get_ts_info = fm10k_get_ts_info,
};
void fm10k_set_ethtool_ops(struct net_device *dev)
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index d4b2fad..df478710 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -398,6 +398,19 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring,
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
}
+static void fm10k_rx_hwtstamp(struct fm10k_ring *rx_ring,
+ union fm10k_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct fm10k_intfc *interface = rx_ring->q_vector->interface;
+
+ FM10K_CB(skb)->tstamp = rx_desc->q.timestamp;
+
+ if (unlikely(interface->flags & FM10K_FLAG_RX_TS_ENABLED))
+ fm10k_ts_cc_to_hwtstamp(interface, skb_hwtstamps(skb),
+ le64_to_cpu(rx_desc->q.timestamp));
+}
+
static void fm10k_type_trans(struct fm10k_ring *rx_ring,
union fm10k_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -447,6 +460,8 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring,
fm10k_rx_checksum(rx_ring, rx_desc, skb);
+ fm10k_rx_hwtstamp(rx_ring, rx_desc, skb);
+
FM10K_CB(skb)->fi.w.vlan = rx_desc->w.vlan;
skb_record_rx_queue(skb, rx_ring->queue_index);
@@ -885,6 +900,11 @@ static u8 fm10k_tx_desc_flags(struct sk_buff *skb, u32 tx_flags)
/* set type for advanced descriptor with frame checksum insertion */
u32 desc_flags = 0;
+ /* set timestamping bits */
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+ likely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+ desc_flags |= FM10K_TXD_FLAG_TIME;
+
/* set checksum offload bits */
desc_flags |= FM10K_SET_FLAG(tx_flags, FM10K_TX_FLAGS_CSUM,
FM10K_TXD_FLAG_CSUM);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 3e56506..8239b5b 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -647,6 +647,10 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)
__skb_put(skb, pad_len);
}
+ /* prepare packet for hardware time stamping */
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ fm10k_ts_tx_enqueue(interface, skb);
+
if (r_idx >= interface->num_tx_queues)
r_idx %= interface->num_tx_queues;
@@ -1173,6 +1177,18 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc)
return 0;
}
+static int fm10k_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGHWTSTAMP:
+ return fm10k_get_ts_config(netdev, ifr);
+ case SIOCSHWTSTAMP:
+ return fm10k_set_ts_config(netdev, ifr);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static void fm10k_assign_l2_accel(struct fm10k_intfc *interface,
struct fm10k_l2_accel *l2_accel)
{
@@ -1341,6 +1357,7 @@ static const struct net_device_ops fm10k_netdev_ops = {
.ndo_get_vf_config = fm10k_ndo_get_vf_config,
.ndo_add_vxlan_port = fm10k_add_vxlan_port,
.ndo_del_vxlan_port = fm10k_del_vxlan_port,
+ .ndo_do_ioctl = fm10k_ioctl,
.ndo_dfwd_add_station = fm10k_dfwd_add_station,
.ndo_dfwd_del_station = fm10k_dfwd_del_station,
};
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 31741e5..9e25421 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -170,6 +170,9 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
/* reassociate interrupts */
fm10k_mbx_request_irq(interface);
+ /* reset clock */
+ fm10k_ts_reset_cc(interface);
+
if (netif_running(netdev))
fm10k_open(netdev);
@@ -490,6 +493,7 @@ static void fm10k_service_task(struct work_struct *work)
/* tasks only run when interface is up */
fm10k_watchdog_subtask(interface);
fm10k_check_hang_subtask(interface);
+ fm10k_ts_tx_subtask(interface);
/* release lock on service events to allow scheduling next event */
fm10k_service_event_complete(interface);
@@ -1064,6 +1068,25 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results,
return 0;
}
+static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results,
+ struct fm10k_mbx_info *mbx)
+{
+ struct fm10k_intfc *interface = container_of(hw,
+ struct fm10k_intfc,
+ hw);
+ u64 timestamp;
+ s32 err;
+
+ err = fm10k_tlv_attr_get_u64(results[FM10K_1588_MSG_TIMESTAMP],
+ ×tamp);
+ if (err)
+ return err;
+
+ fm10k_ts_tx_hwtstamp(interface, 0, timestamp);
+
+ return 0;
+}
+
/* generic error handler for mailbox issues */
static s32 fm10k_mbx_error(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx)
@@ -1083,6 +1106,7 @@ static const struct fm10k_msg_data vf_mbx_data[] = {
FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_mbx_mac_addr),
FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf),
+ FM10K_VF_MSG_1588_HANDLER(fm10k_1588_msg_vf),
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error),
};
@@ -1180,6 +1204,68 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results,
return 0;
}
+static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results,
+ struct fm10k_mbx_info *mbx)
+{
+ struct fm10k_intfc *interface = container_of(hw,
+ struct fm10k_intfc,
+ hw);
+ struct fm10k_iov_data *iov_data;
+ struct fm10k_swapi_1588_timestamp timestamp;
+ u16 sglort, vf_idx;
+ s32 err;
+
+ err = fm10k_tlv_attr_get_le_struct(
+ results[FM10K_PF_ATTR_ID_1588_TIMESTAMP],
+ ×tamp, sizeof(timestamp));
+ if (err)
+ return err;
+
+ if (timestamp.dglort) {
+ fm10k_ts_tx_hwtstamp(interface, timestamp.dglort,
+ le64_to_cpu(timestamp.egress));
+ return 0;
+ }
+
+ /* either dglort or sglort must be set */
+ if (!timestamp.sglort)
+ return FM10K_ERR_PARAM;
+
+ /* verify GLORT is at least one of the ones we own */
+ sglort = le16_to_cpu(timestamp.sglort);
+ if (!fm10k_glort_valid_pf(hw, sglort))
+ return FM10K_ERR_PARAM;
+
+ if (sglort == interface->glort) {
+ fm10k_ts_tx_hwtstamp(interface, 0,
+ le64_to_cpu(timestamp.ingress));
+ return 0;
+ }
+
+ /* if there is no iov_data then there is no mailboxes to process */
+ if (!ACCESS_ONCE(interface->iov_data))
+ return FM10K_ERR_PARAM;
+
+ rcu_read_lock();
+
+ /* notify VF if this timestamp belongs to it */
+ iov_data = interface->iov_data;
+ vf_idx = (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE) - sglort;
+
+ if (!iov_data || vf_idx >= iov_data->num_vfs) {
+ err = FM10K_ERR_PARAM;
+ goto err_unlock;
+ }
+
+ err = hw->iov.ops.report_timestamp(hw, &iov_data->vf_info[vf_idx],
+ le64_to_cpu(timestamp.ingress));
+
+err_unlock:
+ rcu_read_unlock();
+
+ return err;
+}
+
static const struct fm10k_msg_data pf_mbx_data[] = {
FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
@@ -1187,6 +1273,7 @@ static const struct fm10k_msg_data pf_mbx_data[] = {
FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf),
FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf),
FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_update_pvid),
+ FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(fm10k_1588_msg_pf),
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error),
};
@@ -1548,6 +1635,12 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
return -EIO;
}
+ /* assign BAR 4 resources for use with PTP */
+ if (fm10k_read_reg(hw, FM10K_CTRL) & FM10K_CTRL_BAR4_ALLOWED)
+ interface->sw_addr = ioremap(pci_resource_start(pdev, 4),
+ pci_resource_len(pdev, 4));
+ hw->sw_addr = interface->sw_addr;
+
/* Only the PF can support VXLAN and NVGRE offloads */
if (hw->mac.type != fm10k_mac_pf) {
netdev->hw_enc_features = 0;
@@ -1564,6 +1657,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
(unsigned long)interface);
INIT_WORK(&interface->service_task, fm10k_service_task);
+ /* Intitialize timestamp counters */
+ fm10k_ts_start_cc(interface);
+
/* set default ring sizes */
interface->tx_ring_count = FM10K_DEFAULT_TXD;
interface->rx_ring_count = FM10K_DEFAULT_RXD;
@@ -1715,6 +1811,9 @@ static int fm10k_probe(struct pci_dev *pdev,
/* stop all the transmit queues from transmitting until link is up */
netif_tx_stop_all_queues(netdev);
+ /* Register PTP interface */
+ fm10k_ptp_register(interface);
+
/* print bus type/speed/width info */
dev_info(&pdev->dev, "(PCI Express:%s Width: %s Payload: %s)\n",
(hw->bus.speed == fm10k_bus_speed_8000 ? "8.0GT/s" :
@@ -1746,6 +1845,8 @@ err_register:
err_mbx_interrupt:
fm10k_clear_queueing_scheme(interface);
err_sw_init:
+ if (interface->sw_addr)
+ iounmap(interface->sw_addr);
iounmap(interface->uc_addr);
err_ioremap:
free_netdev(netdev);
@@ -1779,6 +1880,10 @@ static void fm10k_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
+ /* cleanup timestamp handling */
+ fm10k_ptp_unregister(interface);
+ fm10k_ts_stop_cc(interface);
+
/* release VFs */
fm10k_iov_disable(pdev);
@@ -1791,6 +1896,8 @@ static void fm10k_remove(struct pci_dev *pdev)
/* remove any debugfs interfaces */
fm10k_dbg_intfc_exit(interface);
+ if (interface->sw_addr)
+ iounmap(interface->sw_addr);
iounmap(interface->uc_addr);
free_netdev(netdev);
@@ -1847,6 +1954,9 @@ static int fm10k_resume(struct pci_dev *pdev)
/* reset statistics starting values */
hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
+ /* reset clock */
+ fm10k_ts_reset_cc(interface);
+
rtnl_lock();
err = fm10k_init_queueing_scheme(interface);
@@ -2003,6 +2113,9 @@ static void fm10k_io_resume(struct pci_dev *pdev)
/* reassociate interrupts */
fm10k_mbx_request_irq(interface);
+ /* reset clock */
+ fm10k_ts_reset_cc(interface);
+
if (netif_running(netdev))
err = fm10k_open(netdev);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c
new file mode 100644
index 0000000..41da724
--- /dev/null
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c
@@ -0,0 +1,535 @@
+/* Intel Ethernet Switch Host Interface Driver
+ * Copyright(c) 2013 - 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ */
+
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+
+#include "fm10k.h"
+
+/* We use a 64b counter so overflow is extremely seldom. Just
+ * to keep things sane we should check for overflow once per day
+ */
+#define FM10K_SYSTIME_OVERFLOW_PERIOD (HZ * 3600 * 24)
+#define FM10K_TS_TX_TIMEOUT (HZ * 15)
+
+static cycle_t fm10k_cc_read_pf(const struct cyclecounter *cc)
+{
+ struct fm10k_intfc *intfc = container_of(cc, struct fm10k_intfc, cc);
+ struct fm10k_hw *hw = &intfc->hw;
+ u32 systime_l, systime_h, systime_tmp;
+
+ systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
+
+ do {
+ systime_tmp = systime_h;
+ systime_l = fm10k_read_reg(hw, FM10K_SYSTIME);
+ systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
+ } while (systime_tmp != systime_h);
+
+ return ((u64)systime_h << 32) | systime_l;
+}
+
+static cycle_t fm10k_cc_read_vf(const struct cyclecounter *cc)
+{
+ struct fm10k_intfc *intfc = container_of(cc, struct fm10k_intfc, cc);
+ struct fm10k_hw *hw = &intfc->hw;
+ u32 systime_l, systime_h, systime_tmp;
+
+ systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
+
+ do {
+ systime_tmp = systime_h;
+ systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME);
+ systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
+ } while (systime_tmp != systime_h);
+
+ return ((u64)systime_h << 32) | systime_l;
+}
+
+void fm10k_ts_cc_to_hwtstamp(struct fm10k_intfc *interface,
+ struct skb_shared_hwtstamps *hwtstamp,
+ cycle_t systime)
+{
+ unsigned long flags;
+ u64 ns;
+
+ read_lock_irqsave(&interface->tsreg_lock, flags);
+ ns = timecounter_cyc2time(&interface->tc, systime);
+ read_unlock_irqrestore(&interface->tsreg_lock, flags);
+
+ hwtstamp->hwtstamp = ns_to_ktime(ns);
+}
+
+static struct sk_buff *fm10k_ts_tx_skb(struct fm10k_intfc *interface,
+ __le16 dglort)
+{
+ struct sk_buff_head *list = &interface->ts_tx_skb_queue;
+ struct sk_buff *skb;
+
+ skb_queue_walk(list, skb) {
+ if (FM10K_CB(skb)->fi.w.dglort == dglort)
+ return skb;
+ }
+
+ return NULL;
+}
+
+void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb)
+{
+ struct sk_buff_head *list = &interface->ts_tx_skb_queue;
+ struct sk_buff *clone;
+ unsigned long flags;
+ __le16 dglort;
+
+ /* create clone for us to return on the Tx path */
+ clone = skb_clone_sk(skb);
+ if (!clone)
+ return;
+
+ FM10K_CB(clone)->ts_tx_timeout = jiffies + FM10K_TS_TX_TIMEOUT;
+ dglort = FM10K_CB(clone)->fi.w.dglort;
+
+ spin_lock_irqsave(&list->lock, flags);
+
+ /* attempt to locate any buffers with the same dglort,
+ * if none are present then insert skb in tail of list
+ */
+ skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort);
+ if (!skb)
+ __skb_queue_tail(list, clone);
+
+ spin_unlock_irqrestore(&list->lock, flags);
+
+ /* if list is already has one then we just free the clone */
+ if (skb)
+ kfree_skb(skb);
+ else
+ skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
+}
+
+void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort,
+ cycle_t systime)
+{
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff_head *list = &interface->ts_tx_skb_queue;
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+
+ /* attempt to locate and pull the sk_buff out of the list */
+ skb = fm10k_ts_tx_skb(interface, dglort);
+ if (skb)
+ __skb_unlink(skb, list);
+
+ spin_unlock_irqrestore(&list->lock, flags);
+
+ /* if not found do nothing */
+ if (!skb)
+ return;
+
+ /* timestamp the sk_buff and return it to the socket */
+ fm10k_ts_cc_to_hwtstamp(interface, &shhwtstamps, systime);
+ skb_complete_tx_timestamp(skb, &shhwtstamps);
+}
+
+static void fm10k_ts_overflow_check(struct work_struct *work)
+{
+ struct fm10k_intfc *interface = container_of(work,
+ struct fm10k_intfc,
+ ts_overflow_work.work);
+ unsigned long flags;
+ struct timespec ts;
+ u64 now;
+
+ read_lock_irqsave(&interface->tsreg_lock, flags);
+ now = timecounter_read(&interface->tc);
+ read_unlock_irqrestore(&interface->tsreg_lock, flags);
+
+ ts = ns_to_timespec(now);
+ pr_debug("fm10k overflow check at %lu.%09lu\n", ts.tv_sec, ts.tv_nsec);
+
+ schedule_delayed_work(&interface->ts_overflow_work,
+ FM10K_SYSTIME_OVERFLOW_PERIOD);
+}
+
+void fm10k_ts_reset_cc(struct fm10k_intfc *interface)
+{
+ unsigned long flags;
+ struct timespec now;
+
+ getnstimeofday(&now);
+
+ /* reinitialize the clock */
+ write_lock_irqsave(&interface->tsreg_lock, flags);
+ timecounter_init(&interface->tc, &interface->cc, timespec_to_ns(&now));
+ write_unlock_irqrestore(&interface->tsreg_lock, flags);
+}
+
+void fm10k_ts_start_cc(struct fm10k_intfc *interface)
+{
+ struct fm10k_hw *hw = &interface->hw;
+
+ /* Initialize cycle counter */
+ interface->cc.read = (hw->mac.type == fm10k_mac_pf) ? fm10k_cc_read_pf :
+ fm10k_cc_read_vf;
+ interface->cc.mask = CLOCKSOURCE_MASK(64);
+ interface->cc.mult = 1;
+
+ /* Initialize lock protecting register access */
+ rwlock_init(&interface->tsreg_lock);
+
+ /* Initialize skb queue for pending timestamp requests */
+ skb_queue_head_init(&interface->ts_tx_skb_queue);
+
+ /* Initialize the clock */
+ fm10k_ts_reset_cc(interface);
+
+ /* Initialize the overflow work */
+ INIT_DELAYED_WORK(&interface->ts_overflow_work,
+ fm10k_ts_overflow_check);
+ schedule_delayed_work(&interface->ts_overflow_work,
+ FM10K_SYSTIME_OVERFLOW_PERIOD);
+}
+
+void fm10k_ts_stop_cc(struct fm10k_intfc *interface)
+{
+ /* remove any stale SKBs and free them */
+ skb_queue_purge(&interface->ts_tx_skb_queue);
+
+ /* shut down the overflow check */
+ cancel_delayed_work_sync(&interface->ts_overflow_work);
+}
+
+void fm10k_ts_tx_subtask(struct fm10k_intfc *interface)
+{
+ struct sk_buff_head *list = &interface->ts_tx_skb_queue;
+ struct sk_buff *skb, *tmp;
+ unsigned long flags;
+
+ /* If we're down or resetting, just bail */
+ if (test_bit(__FM10K_DOWN, &interface->state) ||
+ test_bit(__FM10K_RESETTING, &interface->state))
+ return;
+
+ spin_lock_irqsave(&list->lock, flags);
+
+ /* walk though the list and flush any expired timestamp packets */
+ skb_queue_walk_safe(list, skb, tmp) {
+ if (!time_is_after_jiffies(FM10K_CB(skb)->ts_tx_timeout))
+ continue;
+ __skb_unlink(skb, list);
+ kfree_skb(skb);
+ interface->tx_hwtstamp_timeouts++;
+ }
+
+ spin_unlock_irqrestore(&list->lock, flags);
+}
+
+/**
+ * fm10k_get_ts_config - get current hardware timestamping configuration
+ * @netdev: network interface device structure
+ * @ifreq: ioctl data
+ *
+ * This function returns the current timestamping settings. Rather than
+ * attempt to deconstruct registers to fill in the values, simply keep a copy
+ * of the old settings around, and return a copy when requested.
+ */
+int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
+{
+ struct fm10k_intfc *interface = netdev_priv(netdev);
+ struct hwtstamp_config *config = &interface->ts_config;
+
+ return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+ -EFAULT : 0;
+}
+
+/**
+ * fm10k_set_ts_config - control hardware time stamping
+ * @netdev: network interface device structure
+ * @ifreq: ioctl data
+ *
+ * Outgoing time stamping can be enabled and disabled. Play nice and
+ * disable it when requested, although it shouldn't cause any overhead
+ * when no packet needs it. At most one packet in the queue may be
+ * marked for time stamping, otherwise it would be impossible to tell
+ * for sure to which packet the hardware time stamp belongs.
+ *
+ * Incoming time stamping has to be configured via the hardware
+ * filters. Not all combinations are supported, in particular event
+ * type has to be specified. Matching the kind of event packet is
+ * not supported, with the exception of "all V2 events regardless of
+ * level 2 or 4".
+ *
+ * Since hardware always timestamps Path delay packets when timestamping V2
+ * packets, regardless of the type specified in the register, only use V2
+ * Event mode. This more accurately tells the user what the hardware is going
+ * to do anyways.
+ */
+int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr)
+{
+ struct fm10k_intfc *interface = netdev_priv(netdev);
+ struct hwtstamp_config ts_config;
+
+ if (copy_from_user(&ts_config, ifr->ifr_data, sizeof(ts_config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (ts_config.flags)
+ return -EINVAL;
+
+ switch (ts_config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ break;
+ case HWTSTAMP_TX_ON:
+ /* we likely need some check here to see if this is supported */
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (ts_config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ interface->flags &= ~FM10K_FLAG_RX_TS_ENABLED;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ case HWTSTAMP_FILTER_ALL:
+ interface->flags |= FM10K_FLAG_RX_TS_ENABLED;
+ ts_config.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /* save these settings for future reference */
+ interface->ts_config = ts_config;
+
+ return copy_to_user(ifr->ifr_data, &ts_config, sizeof(ts_config)) ?
+ -EFAULT : 0;
+}
+
+static int fm10k_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ struct fm10k_intfc *interface =
+ container_of(ptp, struct fm10k_intfc, ptp_caps);
+ struct fm10k_hw *hw = &interface->hw;
+ int err;
+
+ err = hw->mac.ops.adjust_systime(hw, ppb);
+
+ /* the only error we should see is if the value is out of range */
+ return (err == FM10K_ERR_PARAM) ? -ERANGE : err;
+}
+
+static int fm10k_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct fm10k_intfc *interface =
+ container_of(ptp, struct fm10k_intfc, ptp_caps);
+ unsigned long flags;
+
+ write_lock_irqsave(&interface->tsreg_lock, flags);
+
+ delta += timecounter_read(&interface->tc);
+ timecounter_init(&interface->tc, &interface->cc, delta);
+
+ write_unlock_irqrestore(&interface->tsreg_lock, flags);
+
+ return 0;
+}
+
+static int fm10k_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ struct fm10k_intfc *interface =
+ container_of(ptp, struct fm10k_intfc, ptp_caps);
+ unsigned long flags;
+ u64 now;
+
+ read_lock_irqsave(&interface->tsreg_lock, flags);
+
+ now = timecounter_read(&interface->tc);
+
+ read_unlock_irqrestore(&interface->tsreg_lock, flags);
+
+ *ts = ns_to_timespec(now);
+
+ return 0;
+}
+
+static int fm10k_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ struct fm10k_intfc *interface =
+ container_of(ptp, struct fm10k_intfc, ptp_caps);
+ unsigned long flags;
+ u64 ns = timespec_to_ns(ts);
+
+ write_lock_irqsave(&interface->tsreg_lock, flags);
+
+ timecounter_init(&interface->tc, &interface->cc, ns);
+
+ write_unlock_irqrestore(&interface->tsreg_lock, flags);
+
+ return 0;
+}
+
+static int fm10k_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct fm10k_intfc *interface =
+ container_of(ptp, struct fm10k_intfc, ptp_caps);
+ struct ptp_clock_time *t = &rq->perout.period;
+ struct fm10k_hw *hw = &interface->hw;
+ u64 period;
+ u32 step;
+
+ /* we can only support periodic output */
+ if (rq->type != PTP_CLK_REQ_PEROUT)
+ return -EINVAL;
+
+ /* verify the requested channel is there */
+ if (rq->perout.index >= ptp->n_per_out)
+ return -EINVAL;
+
+ /* we simply cannot support the operation if we don't have BAR4 */
+ if (!hw->sw_addr)
+ return -ENOTSUPP;
+
+ /* we cannot enforce start time as there is no
+ * mechanism for that in the hardware, we can only control
+ * the period.
+ */
+
+ /* we cannot support periods greater than 4 seconds due to reg limit */
+ if (t->sec > 4 || t->sec < 0)
+ return -ERANGE;
+
+ /* convert to unsigned 64b ns, verify we can put it in a 32b register */
+ period = t->sec * 1000000000LL + t->nsec;
+
+ /* determine the minimum size for period */
+ step = 2 * (fm10k_read_reg(hw, FM10K_SYSTIME_CFG) &
+ FM10K_SYSTIME_CFG_STEP_MASK);
+
+ /* verify the value is in range supported by hardware */
+ if ((period && (period < step)) || (period > U32_MAX))
+ return -ERANGE;
+
+ /* notify hardware of request to being sending pulses */
+ fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_PULSE(rq->perout.index),
+ (u32)period);
+
+ return 0;
+}
+
+static struct ptp_pin_desc fm10k_ptp_pd[2] = {
+ {
+ .name = "IEEE1588_PULSE0",
+ .index = 0,
+ .func = PTP_PF_PEROUT,
+ .chan = 0
+ },
+ {
+ .name = "IEEE1588_PULSE1",
+ .index = 1,
+ .func = PTP_PF_PEROUT,
+ .chan = 1
+ }
+};
+
+static int fm10k_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+ enum ptp_pin_function func, unsigned int chan)
+{
+ /* verify the requested pin is there */
+ if (pin >= ptp->n_pins || !ptp->pin_config)
+ return -EINVAL;
+
+ /* enforce locked channels, no changing them */
+ if (chan != ptp->pin_config[pin].chan)
+ return -EINVAL;
+
+ /* we want to keep the functions locked as well */
+ if (func != ptp->pin_config[pin].func)
+ return -EINVAL;
+
+ return 0;
+}
+
+void fm10k_ptp_register(struct fm10k_intfc *interface)
+{
+ struct ptp_clock_info *ptp_caps = &interface->ptp_caps;
+ struct device *dev = &interface->pdev->dev;
+ struct ptp_clock *ptp_clock;
+
+ snprintf(ptp_caps->name, sizeof(ptp_caps->name),
+ "%s", interface->netdev->name);
+ ptp_caps->owner = THIS_MODULE;
+ ptp_caps->max_adj = 976562; /* (2^30 / 2^40) * 10^9 */
+ ptp_caps->adjfreq = fm10k_ptp_adjfreq;
+ ptp_caps->adjtime = fm10k_ptp_adjtime;
+ ptp_caps->gettime = fm10k_ptp_gettime;
+ ptp_caps->settime = fm10k_ptp_settime;
+
+ /* provide pins if BAR4 is accessible */
+ if (interface->sw_addr) {
+ /* enable periodic outputs */
+ ptp_caps->n_per_out = 2;
+ ptp_caps->enable = fm10k_ptp_enable;
+
+ /* enable clock pins */
+ ptp_caps->verify = fm10k_ptp_verify;
+ ptp_caps->n_pins = 2;
+ ptp_caps->pin_config = fm10k_ptp_pd;
+ }
+
+ ptp_clock = ptp_clock_register(ptp_caps, dev);
+ if (IS_ERR(ptp_clock)) {
+ ptp_clock = NULL;
+ dev_err(dev, "ptp_clock_register failed\n");
+ } else {
+ dev_info(dev, "registered PHC device %s\n", ptp_caps->name);
+ }
+
+ interface->ptp_clock = ptp_clock;
+}
+
+void fm10k_ptp_unregister(struct fm10k_intfc *interface)
+{
+ struct ptp_clock *ptp_clock = interface->ptp_clock;
+ struct device *dev = &interface->pdev->dev;
+
+ if (!ptp_clock)
+ return;
+
+ interface->ptp_clock = NULL;
+
+ ptp_clock_unregister(ptp_clock);
+ dev_info(dev, "removed PHC %s\n", interface->ptp_caps.name);
+}
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
index 5055bef..dac5b79 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
@@ -225,11 +225,7 @@ struct fm10k_hw;
#define FM10K_STATS_NODESC_DROP 0x3807
/* Timesync registers */
-#define FM10K_RRTIME_CFG 0x3808
-#define FM10K_RRTIME_LIMIT(_n) ((_n) + 0x380C)
-#define FM10K_RRTIME_COUNT(_n) ((_n) + 0x3810)
#define FM10K_SYSTIME 0x3814
-#define FM10K_SYSTIME0 0x3816
#define FM10K_SYSTIME_CFG 0x3818
#define FM10K_SYSTIME_CFG_STEP_MASK 0x0000000F
@@ -368,9 +364,6 @@ struct fm10k_hw;
#define FM10K_VFITR(_n) ((_n) + 0x00060)
/* Registers contained in BAR 4 for Switch management */
-#define FM10K_SW_SYSTIME_CFG 0x0224C
-#define FM10K_SW_SYSTIME_CFG_STEP_SHIFT 4
-#define FM10K_SW_SYSTIME_CFG_ADJUST_MASK 0xFF000000
#define FM10K_SW_SYSTIME_ADJUST 0x0224D
#define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF
#define FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE 0x80000000
^ 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