* [PATCH v7 0/4] Prerequisites for Cavium OCTEON-III network driver.
From: David Daney @ 2017-12-13 0:48 UTC (permalink / raw)
To: linux-mips, ralf, James Hogan
Cc: linux-kernel, Steven J. Hill, netdev, David S. Miller,
David Daney
We want to add the Cavium OCTEON-III network driver. But since
interacting with the input and output queues is done via special CPU
local memory, we also need to add support to the MIPS/Octeon
architecture code. Aren't SoCs nice in this way? These are the
prerequisite patches that are needed before the network driver can be
merged.
Changes in v7:
o Splitting of the patch set only. These 4 mips patches are unchanged
from the previous posting.
Changes in v6:
o Added back cleanup patch for previous generation SoC "staging"
driver, as Greg K-H acked it.
o Moved FPA driver to drivers/net/ethernet/cavium/octeon as it is
currently only used by the octeon3-ethernet driver.
o Many code formatting fixes as noted by davem.
Changes in v5:
o Removed cleanup patch for previous generation SoC "staging" driver,
as it will be sent as a follow-on.
o Fixed kernel doc formatting in all patches.
o Removed redundant licensing text boilerplate.
o Reviewed-by: header added to 2/7.
o Rewrote locking code in 3/7 to eliminate inline asm.
Changes in v4:
o Use phy_print_status() instead of open coding the equivalent.
o Print warning on phy mode mismatch.
o Improve dt-bindings and add Acked-by.
Changes in v3:
o Fix PKI (RX path) initialization to work with little endian kernel.
Changes in v2:
o Cleanup and use of standard bindings in the device tree bindings
document.
o Added (hopefully) clarifying comments about several OCTEON
architectural peculiarities.
o Removed unused testing code from the driver.
o Removed some module parameters that already default to the proper
values.
o KConfig cleanup, including testing on x86_64, arm64 and mips.
o Fixed breakage to the driver for previous generation of OCTEON SoCs (in
the staging directory still).
o Verified bisectability of the patch set.
Carlos Munoz (2):
MIPS: Octeon: Enable LMTDMA/LMTST operations.
MIPS: Octeon: Add a global resource manager.
David Daney (2):
MIPS: Octeon: Automatically provision CVMSEG space.
staging: octeon: Remove USE_ASYNC_IOBDMA macro.
arch/mips/cavium-octeon/Kconfig | 27 +-
arch/mips/cavium-octeon/Makefile | 1 +
arch/mips/cavium-octeon/resource-mgr.c | 351 +++++++++++++++++++++
arch/mips/cavium-octeon/setup.c | 22 +-
.../asm/mach-cavium-octeon/kernel-entry-init.h | 20 +-
arch/mips/include/asm/mipsregs.h | 2 +
arch/mips/include/asm/octeon/octeon.h | 32 +-
arch/mips/include/asm/processor.h | 2 +-
arch/mips/kernel/octeon_switch.S | 2 -
arch/mips/mm/tlbex.c | 29 +-
drivers/staging/octeon/ethernet-defines.h | 6 -
drivers/staging/octeon/ethernet-rx.c | 25 +-
drivers/staging/octeon/ethernet-tx.c | 85 ++---
13 files changed, 472 insertions(+), 132 deletions(-)
create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
--
2.14.3
^ permalink raw reply
* [PATCH net-next 5/6] hv_netvsc: remove open_cnt reference count
From: Stephen Hemminger @ 2017-12-13 0:48 UTC (permalink / raw)
To: kys, haiyangz, sthemmin; +Cc: devel, netdev
In-Reply-To: <20171213004840.17507-1-sthemmin@microsoft.com>
There is only ever a single instance of network device object
referencing the internal rndis object. Therefore the open_cnt atomic
is not necessary.
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
---
drivers/net/hyperv/hyperv_net.h | 2 --
drivers/net/hyperv/netvsc.c | 2 +-
drivers/net/hyperv/rndis_filter.c | 10 +++-------
3 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index eb01943b23c3..8ebe72bf89ff 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -810,8 +810,6 @@ struct netvsc_device {
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
u32 pkt_align; /* alignment bytes, e.g. 8 */
- atomic_t open_cnt;
-
struct netvsc_channel chan_table[VRSS_CHANNEL_MAX];
struct rcu_head rcu;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d8165407bcda..6dd97f232f87 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -73,7 +73,7 @@ static struct netvsc_device *alloc_net_device(void)
init_waitqueue_head(&net_device->wait_drain);
net_device->destroy = false;
- atomic_set(&net_device->open_cnt, 0);
+
net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 025110a19d4a..035976949177 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1362,9 +1362,6 @@ int rndis_filter_open(struct netvsc_device *nvdev)
if (!nvdev)
return -EINVAL;
- if (atomic_inc_return(&nvdev->open_cnt) != 1)
- return 0;
-
return rndis_filter_open_device(nvdev->extension);
}
@@ -1373,13 +1370,12 @@ int rndis_filter_close(struct netvsc_device *nvdev)
if (!nvdev)
return -EINVAL;
- if (atomic_dec_return(&nvdev->open_cnt) != 0)
- return 0;
-
return rndis_filter_close_device(nvdev->extension);
}
bool rndis_filter_opened(const struct netvsc_device *nvdev)
{
- return atomic_read(&nvdev->open_cnt) > 0;
+ const struct rndis_device *dev = nvdev->extension;
+
+ return dev->state == RNDIS_DEV_DATAINITIALIZED;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 2/6] hv_netvsc: track memory allocation failures in ethtool stats
From: Stephen Hemminger @ 2017-12-13 0:48 UTC (permalink / raw)
To: kys, haiyangz, sthemmin; +Cc: devel, netdev
In-Reply-To: <20171213004840.17507-1-sthemmin@microsoft.com>
When skb can not be allocated, update ethtool statisitics
rather than rx_dropped which is intended for netif_receive.
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
---
drivers/net/hyperv/hyperv_net.h | 1 +
drivers/net/hyperv/netvsc_drv.c | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 3d940c67ea94..42bbde1cbe45 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -692,6 +692,7 @@ struct netvsc_ethtool_stats {
unsigned long tx_busy;
unsigned long tx_send_full;
unsigned long rx_comp_busy;
+ unsigned long rx_no_memory;
unsigned long stop_queue;
unsigned long wake_queue;
};
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index dc70de674ca9..d16b68974d80 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -777,8 +777,8 @@ int netvsc_recv_callback(struct net_device *net,
skb = netvsc_alloc_recv_skb(net, &nvchan->napi,
csum_info, vlan, data, len);
if (unlikely(!skb)) {
+ ++net_device_ctx->eth_stats.rx_no_memory;
drop:
- ++net->stats.rx_dropped;
rcu_read_unlock();
return NVSP_STAT_FAIL;
}
@@ -1129,12 +1129,13 @@ static const struct {
u16 offset;
} netvsc_stats[] = {
{ "tx_scattered", offsetof(struct netvsc_ethtool_stats, tx_scattered) },
- { "tx_no_memory", offsetof(struct netvsc_ethtool_stats, tx_no_memory) },
+ { "tx_no_memory", offsetof(struct netvsc_ethtool_stats, tx_no_memory) },
{ "tx_no_space", offsetof(struct netvsc_ethtool_stats, tx_no_space) },
{ "tx_too_big", offsetof(struct netvsc_ethtool_stats, tx_too_big) },
{ "tx_busy", offsetof(struct netvsc_ethtool_stats, tx_busy) },
{ "tx_send_full", offsetof(struct netvsc_ethtool_stats, tx_send_full) },
{ "rx_comp_busy", offsetof(struct netvsc_ethtool_stats, rx_comp_busy) },
+ { "rx_no_memory", offsetof(struct netvsc_ethtool_stats, rx_no_memory) },
{ "stop_queue", offsetof(struct netvsc_ethtool_stats, stop_queue) },
{ "wake_queue", offsetof(struct netvsc_ethtool_stats, wake_queue) },
}, vf_stats[] = {
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 1/6] hv_netvsc: copy_to_send buf can be void
From: Stephen Hemminger @ 2017-12-13 0:48 UTC (permalink / raw)
To: kys, haiyangz, sthemmin; +Cc: devel, netdev
In-Reply-To: <20171213004840.17507-1-sthemmin@microsoft.com>
Since only caller does not care about return value.
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
---
drivers/net/hyperv/netvsc.c | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index e4bcd202a56a..9407907c4988 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -696,19 +696,18 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
return NETVSC_INVALID_INDEX;
}
-static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
- unsigned int section_index,
- u32 pend_size,
- struct hv_netvsc_packet *packet,
- struct rndis_message *rndis_msg,
- struct hv_page_buffer *pb,
- struct sk_buff *skb)
+static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
+ unsigned int section_index,
+ u32 pend_size,
+ struct hv_netvsc_packet *packet,
+ struct rndis_message *rndis_msg,
+ struct hv_page_buffer *pb,
+ struct sk_buff *skb)
{
char *start = net_device->send_buf;
char *dest = start + (section_index * net_device->send_section_size)
+ pend_size;
int i;
- u32 msg_size = 0;
u32 padding = 0;
u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt :
packet->page_buf_cnt;
@@ -728,16 +727,11 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
u32 len = pb[i].len;
memcpy(dest, (src + offset), len);
- msg_size += len;
dest += len;
}
- if (padding) {
+ if (padding)
memset(dest, 0, padding);
- msg_size += padding;
- }
-
- return msg_size;
}
static inline int netvsc_send_pkt(
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 0/6] hv_netvsc: minor changes
From: Stephen Hemminger @ 2017-12-13 0:48 UTC (permalink / raw)
To: kys, haiyangz, sthemmin; +Cc: devel, netdev
This includes minor cleanup of code in send and receive path and
also a new statistic to check for allocation failures. This also
eliminates some of the extra RCU when not needed.
There is a theoritical bug where buffered data could be blocked
for longer than necessary if the ring buffer got full. This
has not been seen in the wild, found by inspection.
The reference count between net device and internal RNDIS
is not needed.
Stephen Hemminger (6):
hv_netvsc: copy_to_send buf can be void
hv_netvsc: track memory allocation failures in ethtool stats
hv_netvsc: simplify function args in receive status path
hv_netvsc: pass netvsc_device to receive callback
hv_netvsc: remove open_cnt reference count
hv_netvsc: empty current transmit aggregation if flow blocked
drivers/net/hyperv/hyperv_net.h | 9 ++++----
drivers/net/hyperv/netvsc.c | 44 ++++++++++++++++++++-------------------
drivers/net/hyperv/netvsc_drv.c | 33 +++++++----------------------
drivers/net/hyperv/rndis_filter.c | 29 +++++++++++---------------
4 files changed, 47 insertions(+), 68 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: [RFC][PATCH] new byteorder primitives - ..._{replace,get}_bits()
From: Al Viro @ 2017-12-13 0:36 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: Linus Torvalds, netdev, linux-kernel
In-Reply-To: <20171212155933.03c88eab@cakuba.netronome.com>
On Tue, Dec 12, 2017 at 03:59:33PM -0800, Jakub Kicinski wrote:
> > +static __always_inline __##type type##_replace_bits(__##type old, \
> > + base val, base mask) \
> > +{ \
> > + __##type m = to(mask); \
> > + if (__builtin_constant_p(val) && \
>
> Is the lack of a __builtin_constant_p(mask) test intentional? Sometimes
> the bitfield is a packed array and people may have a helper to which
> only the mask is passed as non-constant and the value is implied by the
> helper, thus constant.
If the mask in non-constant, we probably shouldn't be using that at all;
could you show a real-world example where that would be the case?
^ permalink raw reply
* [PATCH 2/2] Bluetooth: hci_ll: add "ti,cc2560" compatible string
From: David Lechner @ 2017-12-13 0:29 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA
Cc: David Lechner, Rob Herring, Mark Rutland, Marcel Holtmann,
Johan Hedberg, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1513124971-23717-1-git-send-email-david-nq/r/kbU++upp/zk7JDF2g@public.gmane.org>
This adds the "ti,cc2560" compatible string for a TI CC2560 chip.
Signed-off-by: David Lechner <david-nq/r/kbU++upp/zk7JDF2g@public.gmane.org>
---
drivers/bluetooth/hci_ll.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index 9de106f..1b4417a 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -842,6 +842,7 @@ static void hci_ti_remove(struct serdev_device *serdev)
}
static const struct of_device_id hci_ti_of_match[] = {
+ { .compatible = "ti,cc2560" },
{ .compatible = "ti,wl1271-st" },
{ .compatible = "ti,wl1273-st" },
{ .compatible = "ti,wl1281-st" },
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: net: add TI CC2560 Bluetooth chip
From: David Lechner @ 2017-12-13 0:29 UTC (permalink / raw)
To: devicetree, linux-bluetooth
Cc: David Lechner, Rob Herring, Mark Rutland, Marcel Holtmann,
Johan Hedberg, netdev, linux-kernel
In-Reply-To: <1513124971-23717-1-git-send-email-david@lechnology.com>
This adds a compatible string for the Texas Instruments CC2560 Bluetooth
chip to the existing TI WiLink shared transport bindings. These chips are
similar enough that the same bindings work for both. The file is renamed
to ti-bluetooth.txt to make it more generic.
Signed-off-by: David Lechner <david@lechnology.com>
---
.../bindings/net/{ti,wilink-st.txt => ti-bluetooth.txt} | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
rename Documentation/devicetree/bindings/net/{ti,wilink-st.txt => ti-bluetooth.txt} (78%)
diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt b/Documentation/devicetree/bindings/net/ti-bluetooth.txt
similarity index 78%
rename from Documentation/devicetree/bindings/net/ti,wilink-st.txt
rename to Documentation/devicetree/bindings/net/ti-bluetooth.txt
index a45a508..6d03ff8 100644
--- a/Documentation/devicetree/bindings/net/ti,wilink-st.txt
+++ b/Documentation/devicetree/bindings/net/ti-bluetooth.txt
@@ -1,10 +1,18 @@
-TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
+Texas Instruments Bluetooth Chips
+---------------------------------
+
+This documents the binding structure and common properties for serial
+attached TI Bluetooth devices. The following chips are included in this
+binding:
+
+* TI CC256x Bluetooth devices
+* TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
and GPS over what's called "shared transport". The shared transport is
standard BT HCI protocol with additional channels for the other functions.
-These devices also have a separate WiFi interface as described in
+TI WiLink devices also have a separate WiFi interface as described in
wireless/ti,wlcore.txt.
This bindings follows the UART slave device binding in
@@ -12,6 +20,7 @@ This bindings follows the UART slave device binding in
Required properties:
- compatible: should be one of the following:
+ "ti,cc2560"
"ti,wl1271-st"
"ti,wl1273-st"
"ti,wl1281-st"
--
2.7.4
^ permalink raw reply related
* [PATCH 0/2] Bluetooth: Add device tree compatible for TI CC2560
From: David Lechner @ 2017-12-13 0:29 UTC (permalink / raw)
To: devicetree, linux-bluetooth
Cc: David Lechner, Rob Herring, Mark Rutland, Marcel Holtmann,
Johan Hedberg, netdev, linux-kernel
This series updates the bindings TI WiLink 7/8 Bluetooth to add TI CC256x
chips as well. A compatible string is also added to the hci_ll driver for
TI CC2560.
David Lechner (2):
dt-bindings: net: add TI CC2560 Bluetooth chip
Bluetooth: hci_ll: add "ti,cc2560" compatible string
.../bindings/net/{ti,wilink-st.txt => ti-bluetooth.txt} | 13 +++++++++++--
drivers/bluetooth/hci_ll.c | 1 +
2 files changed, 12 insertions(+), 2 deletions(-)
rename Documentation/devicetree/bindings/net/{ti,wilink-st.txt => ti-bluetooth.txt} (78%)
--
2.7.4
^ permalink raw reply
* [PATCH net] tcp: fix potential underestimation on rcv_rtt
From: Wei Wang @ 2017-12-13 0:28 UTC (permalink / raw)
To: David Miller, netdev; +Cc: Eric Dumazet, Wei Wang
From: Wei Wang <weiwan@google.com>
When ms timestamp is used, current logic uses 1us in
tcp_rcv_rtt_update() when the real rcv_rtt is within 1 - 999us.
This could cause rcv_rtt underestimation.
Fix it by always using a min value of 1ms if ms timestamp is used.
Fixes: 645f4c6f2ebd ("tcp: switch rcv_rtt_est and rcvq_space to high
resolution timestamps")
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_input.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9550cc42de2d..45f750e85714 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -508,9 +508,6 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
u32 new_sample = tp->rcv_rtt_est.rtt_us;
long m = sample;
- if (m == 0)
- m = 1;
-
if (new_sample != 0) {
/* If we sample in larger samples in the non-timestamp
* case, we could grossly overestimate the RTT especially
@@ -547,6 +544,8 @@ static inline void tcp_rcv_rtt_measure(struct tcp_sock *tp)
if (before(tp->rcv_nxt, tp->rcv_rtt_est.seq))
return;
delta_us = tcp_stamp_us_delta(tp->tcp_mstamp, tp->rcv_rtt_est.time);
+ if (!delta_us)
+ delta_us = 1;
tcp_rcv_rtt_update(tp, delta_us, 1);
new_measure:
@@ -563,8 +562,11 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
(TCP_SKB_CB(skb)->end_seq -
TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss)) {
u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
- u32 delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
+ u32 delta_us;
+ if (!delta)
+ delta = 1;
+ delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
tcp_rcv_rtt_update(tp, delta_us, 0);
}
}
--
2.15.1.424.g9478a66081-goog
^ permalink raw reply related
* [PATCH net-next v2 5/5] net: phy: phylink: Report MoCA as PORT_BNC
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
In-Reply-To: <20171213000029.8649-1-f.fainelli@gmail.com>
Similarly to what PHYLIB already does, make sure that
PHY_INTERFACE_MODE_MOCA is reported as PORT_BNC.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 1acdda69b3c6..c89b8c63f16a 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -556,7 +556,10 @@ struct phylink *phylink_create(struct net_device *ndev,
pl->netdev = ndev;
pl->phy_state.interface = iface;
pl->link_interface = iface;
- pl->link_port = PORT_MII;
+ if (iface == PHY_INTERFACE_MODE_MOCA)
+ pl->link_port = PORT_BNC;
+ else
+ pl->link_port = PORT_MII;
pl->link_config.interface = iface;
pl->link_config.pause = MLO_PAUSE_AN;
pl->link_config.speed = SPEED_UNKNOWN;
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v2 4/5] net: phy: phylink: Allow setting a custom link state callback
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
In-Reply-To: <20171213000029.8649-1-f.fainelli@gmail.com>
phylink_get_fixed_state() currently consults an optional "link_gpio"
GPIO descriptor, expand this mechanism to allow specifying a custom
callback. This is necessary to support out of band link notifcation
(e.g: from an interrupt within a MMIO register).
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 34 ++++++++++++++++++++++++++++++++--
include/linux/phylink.h | 3 +++
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 64e3eb73a237..1acdda69b3c6 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -54,6 +54,8 @@ struct phylink {
/* The link configuration settings */
struct phylink_link_state link_config;
struct gpio_desc *link_gpio;
+ void (*get_fixed_state)(struct net_device *dev,
+ struct phylink_link_state *s);
struct mutex state_mutex;
struct phylink_link_state phy_state;
@@ -350,12 +352,14 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *
}
/* The fixed state is... fixed except for the link state,
- * which may be determined by a GPIO.
+ * which may be determined by a GPIO or a callback.
*/
static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state)
{
*state = pl->link_config;
- if (pl->link_gpio)
+ if (pl->get_fixed_state)
+ pl->get_fixed_state(pl->netdev, state);
+ else if (pl->link_gpio)
state->link = !!gpiod_get_value(pl->link_gpio);
}
@@ -814,6 +818,32 @@ void phylink_disconnect_phy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
+/**
+ * phylink_fixed_state_cb() - allow setting a fixed link callback
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @cb: callback to execute to determine the fixed link state.
+ *
+ * The MAC driver should call this driver when the state of its link
+ * can be determined through e.g: an out of band MMIO register.
+ */
+int phylink_fixed_state_cb(struct phylink *pl,
+ void (*cb)(struct net_device *dev,
+ struct phylink_link_state *state))
+{
+ /* It does not make sense to let the link be overriden unless we use
+ * MLO_AN_FIXED
+ */
+ if (pl->link_an_mode != MLO_AN_FIXED)
+ return -EINVAL;
+
+ mutex_lock(&pl->state_mutex);
+ pl->get_fixed_state = cb;
+ mutex_unlock(&pl->state_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(phylink_fixed_state_cb);
+
/**
* phylink_mac_change() - notify phylink of a change in MAC state
* @pl: a pointer to a &struct phylink returned from phylink_create()
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 36e342b450c7..bd137c273d38 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -190,6 +190,9 @@ void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
void phylink_disconnect_phy(struct phylink *);
+int phylink_fixed_state_cb(struct phylink *,
+ void (*cb)(struct net_device *dev,
+ struct phylink_link_state *));
void phylink_mac_change(struct phylink *, bool up);
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v2 3/5] net: phy: phylink: Remove error message
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
In-Reply-To: <20171213000029.8649-1-f.fainelli@gmail.com>
Some subsystems like DSA may be trying to connect to a PHY through OF first,
and then attempt a connect using a local MDIO bus, remove the error message:
"unable to find PHY node" so we can let MAC drivers whether to print it or not.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 60c1b7e5490e..64e3eb73a237 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -765,10 +765,8 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
phy_node = of_parse_phandle(dn, "phy-device", 0);
if (!phy_node) {
- if (pl->link_an_mode == MLO_AN_PHY) {
- netdev_err(pl->netdev, "unable to find PHY node\n");
+ if (pl->link_an_mode == MLO_AN_PHY)
return -ENODEV;
- }
return 0;
}
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v2 2/5] net: phy: phylink: Use PHY device interface if N/A
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
In-Reply-To: <20171213000029.8649-1-f.fainelli@gmail.com>
We may not always be able to resolve a correct phy_interface_t value before
actually connecting to the PHY device, when that happens, just have
phylink_connect_phy() utilize what the PHY device/driver provided.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 94b43c5237fa..60c1b7e5490e 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -715,6 +715,12 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
phy_interface_mode_is_8023z(pl->link_interface))))
return -EINVAL;
+ /* Use PHY device/driver interface */
+ if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
+ pl->link_interface = phy->interface;
+ pl->link_config.interface = pl->link_interface;
+ }
+
ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface);
if (ret)
return ret;
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v2 1/5] net: phy: phylink: Allow specifying PHY device flags
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
In-Reply-To: <20171213000029.8649-1-f.fainelli@gmail.com>
In order to let subsystems like DSA fully utilize PHYLINK, we need to be able
to communicate phy_device::flags from of_phy_{connect,attach} even when using
PHYLINK APIs.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phylink.c | 7 +++++--
include/linux/phylink.h | 2 +-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 2bfb548d3dff..94b43c5237fa 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -731,6 +731,7 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
* phylink_of_phy_connect() - connect the PHY specified in the DT mode.
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @dn: a pointer to a &struct device_node.
+ * @flags: PHY-specific flags to communicate to the PHY device driver
*
* Connect the phy specified in the device node @dn to the phylink instance
* specified by @pl. Actions specified in phylink_connect_phy() will be
@@ -738,7 +739,8 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
*
* Returns 0 on success or a negative errno.
*/
-int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
+int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
+ u32 flags)
{
struct device_node *phy_node;
struct phy_device *phy_dev;
@@ -764,7 +766,8 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
return 0;
}
- phy_dev = of_phy_attach(pl->netdev, phy_node, 0, pl->link_interface);
+ phy_dev = of_phy_attach(pl->netdev, phy_node, flags,
+ pl->link_interface);
/* We're done with the phy_node handle */
of_node_put(phy_node);
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 4f0f452ff38d..36e342b450c7 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -188,7 +188,7 @@ struct phylink *phylink_create(struct net_device *, struct fwnode_handle *,
void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *);
-int phylink_of_phy_connect(struct phylink *, struct device_node *);
+int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
void phylink_disconnect_phy(struct phylink *);
void phylink_mac_change(struct phylink *, bool up);
--
2.14.1
^ permalink raw reply related
* [PATCH net-next v2 0/5] PHYLINK preparatory patches for DSA
From: Florian Fainelli @ 2017-12-13 0:00 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, rmk+kernel, davem, andrew, vivien.didelot
Hi all,
In preparation for having DSA migrate to PHYLINK, I had to come up with a
number of preparatory patches:
- we need to be able to pass phy_flags from an external component calling
phylink_of_phy_connect()
- DSA tries to connect through OF first, then fallsback using its own internal
MDIO bus, in that case we would both show an error, but also not know what
the correct phy_interface_t would be, instead use the PHY device/driver provided
one
- Finally bcm_sf2 makes use of all possible PHYs out there: internal, external,
fixed, and MoCA, the latter requires a bit of help to signal link notifications
through a MMIO interrupt, as well a report a correct PORT type
Changes in v2:
- rebased against latest net-next/master
- added kernel doc documentation
- dropped error message in phylink_of_phy_connect() as suggested by Russell
Florian Fainelli (5):
net: phy: phylink: Allow specifying PHY device flags
net: phy: phylink: Use PHY device interface if N/A
net: phy: phylink: Remove error message
net: phy: phylink: Allow setting a custom link state callback
net: phy: phylink: Report MoCA as PORT_BNC
drivers/net/phy/phylink.c | 56 ++++++++++++++++++++++++++++++++++++++++-------
include/linux/phylink.h | 5 ++++-
2 files changed, 52 insertions(+), 9 deletions(-)
--
2.14.1
^ permalink raw reply
* Re: [RFC][PATCH] new byteorder primitives - ..._{replace,get}_bits()
From: Jakub Kicinski @ 2017-12-12 23:59 UTC (permalink / raw)
To: Al Viro; +Cc: Linus Torvalds, netdev, linux-kernel
In-Reply-To: <20171212234856.GZ21978@ZenIV.linux.org.uk>
On Tue, 12 Dec 2017 23:48:56 +0000, Al Viro wrote:
> On Tue, Dec 12, 2017 at 12:04:09PM -0800, Jakub Kicinski wrote:
>
> > > static __always_inline u64 mask_to_multiplier(u64 mask)
> > > {
> > > return mask & (mask ^ (mask - 1));
> > > }
>
> D'oh. Even simpler than that, of course -
>
> static __always_inline u64 mask_to_multiplier(u64 mask)
> {
> return mask & -mask;
> }
>
> > Very nice! The compilation-time check if the value can fit in a field
> > covered by the mask (if they're both known) did help me catch bugs
> > early a few times over the years, so if it could be preserved we can
> > maybe even drop the FIELD_* macros and just use this approach?
>
> Umm... Something like this, perhaps? Same bunch, plus u{16,32,64}_...
> variants for host-endian. Adding sanity check on mask is also not
> hard, but I don't know how useful it actually is...
Sanity checking the mask is not that useful in my experience.
> diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
> index 451aaa0786ae..a032de9aa03d 100644
> --- a/include/linux/byteorder/generic.h
> +++ b/include/linux/byteorder/generic.h
> @@ -187,4 +187,36 @@ static inline void be32_to_cpu_array(u32 *dst, const __be32 *src, size_t len)
> dst[i] = be32_to_cpu(src[i]);
> }
>
> +extern void __compiletime_error("value doesn't fit into mask")
> +__field_overflow(void);
> +static __always_inline u64 mask_to_multiplier(u64 mask)
> +{
> + return mask & -mask;
> +}
> +
> +#define ____MAKE_OP(type,base,to,from) \
> +static __always_inline __##type type##_replace_bits(__##type old, \
> + base val, base mask) \
> +{ \
> + __##type m = to(mask); \
> + if (__builtin_constant_p(val) && \
Is the lack of a __builtin_constant_p(mask) test intentional? Sometimes
the bitfield is a packed array and people may have a helper to which
only the mask is passed as non-constant and the value is implied by the
helper, thus constant.
> + (val & ~(mask/mask_to_multiplier(mask)))) \
> + __field_overflow(); \
> + return (old & ~m) | \
> + (to(val * mask_to_multiplier(mask)) & m); \
> +} \
> +static __always_inline base type##_get_bits(__##type v, base mask) \
> +{ \
> + return (from(v) & mask)/mask_to_multiplier(mask); \
> +}
> +#define __MAKE_OP(size) \
> + ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
> + ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
> + ____MAKE_OP(u##size,u##size,,)
> +__MAKE_OP(16)
> +__MAKE_OP(32)
> +__MAKE_OP(64)
> +#undef __MAKE_OP
> +#undef ____MAKE_OP
> +
> #endif /* _LINUX_BYTEORDER_GENERIC_H */
^ permalink raw reply
* Re: [RFC PATCH 2/9] ethtool: introduce ethtool netlink interface
From: Michal Kubecek @ 2017-12-12 23:56 UTC (permalink / raw)
To: David Miller; +Cc: jiri, netdev, linux-kernel
In-Reply-To: <20171211.134547.711629508042364482.davem@davemloft.net>
On Mon, Dec 11, 2017 at 01:45:47PM -0500, David Miller wrote:
> From: Jiri Pirko <jiri@resnulli.us>
> Date: Mon, 11 Dec 2017 19:02:19 +0100
>
> > The discussion we had before was about flag bitfield that was there
> > *always*. In this case, that is not true. It is either ifindex or
> > ifname. Even rtnetlink has ifname as attribute.
> >
> > The flags and info_mask is just big mystery. If it is per-command,
> > seems natural to have it as attributes.
>
> I think flags and info_mask indeed can be moved out of this struct.
>
> I guess, in this case, I can see your point of view especially if we
> allow ethtool operations on non-netdev entities.
>
> So, ok, let's move forward without a base command struct and just
> use attributes.
OK, I'll rework the interface to use attributes for all data.
Michal Kubecek
^ permalink raw reply
* Re: [RFC PATCH 5/9] ethtool: implement GET_DRVINFO message
From: Michal Kubecek @ 2017-12-12 23:54 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, linux-kernel
In-Reply-To: <20171211161601.GB1885@nanopsycho>
On Mon, Dec 11, 2017 at 05:16:01PM +0100, Jiri Pirko wrote:
> Mon, Dec 11, 2017 at 02:54:01PM CET, mkubecek@suse.cz wrote:
> >+
> >+ ETHA_DRVINFO_DRIVER (string) driver name
> >+ ETHA_DRVINFO_VERSION (string) driver version
>
> You use 3 prefixes:
> ETHTOOL_ for cmd
> ETHA_ for attrs
> ethnl_ for function
>
> I suggest to sync this, perhaps to:
> ETHNL_CMD_*
> ETHNL_ATTR_*
> ethnl_*
> ?
Switching to ETHNL_CMD_* is certainly a good idea. For attributes, I'm a
bit worried that ETHNL_ATTR_ prefix might make it even harder to fit
into the 80 characters per line limit. I'll try and see what it would
look like.
> >+ ETHA_DRVINFO_FWVERSION (string) firmware version
> >+ ETHA_DRVINFO_BUSINFO (string) device bus address
> >+ ETHA_DRVINFO_EROM_VER (string) expansion ROM version
> >+ ETHA_DRVINFO_N_PRIV_FLAGS (u32) number of private flags
> >+ ETHA_DRVINFO_N_STATS (u32) number of device stats
> >+ ETHA_DRVINFO_TESTINFO_LEN (u32) number of test results
> >+ ETHA_DRVINFO_EEDUMP_LEN (u32) EEPROM dump size
> >+ ETHA_DRVINFO_REGDUMP_LEN (u32) register dump size
>
> We are now working on providing various fw memory regions dump in
> devlink. It makes sense to have it in devlink for couple of reasons:
> 1) per-asic, not netdev specific, therefore does not really make sense
> to have netdev as handle, but rather devlink handle.
> 2) snapshot support - we need to provide support for getting snapshot
> (for example on failure), transferring to user and deleting it
> (remove from driver memory).
>
> Also, driver name, version, fwversion, etc is per-asic. Would make sense
> to have it in devlink as well.
>
> I think this is great opprotunity to move things where they should be to
> be alligned with the current world and kernel infrastructure.
IMHO this depends on the question whether we are going to rework also
the interface between kernel and NIC drivers (currently ethtool_ops).
If we are, it would make good sense to split the information in both
interfaces. If not, it doesn't seem to make userspace do two queries,
each getting one part of the same information provided by NIC.
Also, I must admit that one thing I dislike about the iw tool is that it
pushes me to distinguish between operations on "phy" and "dev". While
I understand that it makes perfect sense for someone familiar with the
internals, it's quite annoying for an occasional "consumer". It would be
sad if we created a set of perfectly logical and clean tools and
(almost) 20 years later, people still used old ioctl based ethtool
because "it's what they are used to and it works just fine for them"
(like they do with ifconfig, netstat or brctl).
Michal
^ permalink raw reply
* Re: [RFC][PATCH] new byteorder primitives - ..._{replace,get}_bits()
From: Al Viro @ 2017-12-12 23:48 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: Linus Torvalds, netdev, linux-kernel
In-Reply-To: <20171212120409.64b6362e@cakuba.netronome.com>
On Tue, Dec 12, 2017 at 12:04:09PM -0800, Jakub Kicinski wrote:
> > static __always_inline u64 mask_to_multiplier(u64 mask)
> > {
> > return mask & (mask ^ (mask - 1));
> > }
D'oh. Even simpler than that, of course -
static __always_inline u64 mask_to_multiplier(u64 mask)
{
return mask & -mask;
}
> Very nice! The compilation-time check if the value can fit in a field
> covered by the mask (if they're both known) did help me catch bugs
> early a few times over the years, so if it could be preserved we can
> maybe even drop the FIELD_* macros and just use this approach?
Umm... Something like this, perhaps? Same bunch, plus u{16,32,64}_...
variants for host-endian. Adding sanity check on mask is also not
hard, but I don't know how useful it actually is...
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
index 451aaa0786ae..a032de9aa03d 100644
--- a/include/linux/byteorder/generic.h
+++ b/include/linux/byteorder/generic.h
@@ -187,4 +187,36 @@ static inline void be32_to_cpu_array(u32 *dst, const __be32 *src, size_t len)
dst[i] = be32_to_cpu(src[i]);
}
+extern void __compiletime_error("value doesn't fit into mask")
+__field_overflow(void);
+static __always_inline u64 mask_to_multiplier(u64 mask)
+{
+ return mask & -mask;
+}
+
+#define ____MAKE_OP(type,base,to,from) \
+static __always_inline __##type type##_replace_bits(__##type old, \
+ base val, base mask) \
+{ \
+ __##type m = to(mask); \
+ if (__builtin_constant_p(val) && \
+ (val & ~(mask/mask_to_multiplier(mask)))) \
+ __field_overflow(); \
+ return (old & ~m) | \
+ (to(val * mask_to_multiplier(mask)) & m); \
+} \
+static __always_inline base type##_get_bits(__##type v, base mask) \
+{ \
+ return (from(v) & mask)/mask_to_multiplier(mask); \
+}
+#define __MAKE_OP(size) \
+ ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
+ ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
+ ____MAKE_OP(u##size,u##size,,)
+__MAKE_OP(16)
+__MAKE_OP(32)
+__MAKE_OP(64)
+#undef __MAKE_OP
+#undef ____MAKE_OP
+
#endif /* _LINUX_BYTEORDER_GENERIC_H */
^ permalink raw reply related
* Re: [RFC PATCH 0/9] ethtool netlink interface (WiP)
From: Jakub Kicinski @ 2017-12-12 23:47 UTC (permalink / raw)
To: Roopa Prabhu
Cc: Michal Kubecek, netdev, linux-kernel, Jiri Pirko, David Miller
In-Reply-To: <CAJieiUgP6muLZbVczd4wVWfkCz4c4K6AgZtV9TPVsxUmEnYjBw@mail.gmail.com>
On Tue, 12 Dec 2017 07:32:44 -0800, Roopa Prabhu wrote:
> Thanks for working on this!. Agree with most comments already
> discussed on this thread.
> I would prefer if we fold ethtool netlink into devlink since there is
> already an overlap.
> many reasons:
> - have just one driver api for device global and per port config
> (devlink already provides that)
> - some of the devlink commands like port split/unsplit can already be
> applied per netdev (and since you bring up network interface managers,
> we are looking at getting these in network managers for switch ports)
> - if we keep them separate, we will soon see that drivers will need
> handlers for both devlink and ethtool
> - and the overlap is going to be confusing for both drivers and user-space
+1
FWIW my gut feeling is that extending devlink-port makes more sense
than creating another command. Although things like RSS tables don't
feel very natural in port context.
The other issue that springs to mind is that ethtool ops take RTNL lock
today, and devlink doesn't. It would be cool if we could make ethtool
not require RTNL lock (and drivers didn't have to drop locks half way
through the .flash_device callback, sigh...) but OTOH that would make
the driver conversion more brittle and potentially block the much
needed netlink conversion...
That's my $0.02 ;)
^ permalink raw reply
* [PATCH v2 next-queue 10/10] ixgbe: register ipsec offload with the xfrm subsystem
From: Shannon Nelson @ 2017-12-12 23:37 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, steffen.klassert, sowmini.varadhan
In-Reply-To: <1513121823-27944-1-git-send-email-shannon.nelson@oracle.com>
With all the support code in place we can now link in the ipsec
offload operations and set the ESP feature flag for the XFRM
subsystem to see.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
v2: added the xdo_dev_state_free callback to make XFRM happy
changed use of NETIF_F_HW_CSUM_BIT to NETIF_F_HW_CSUM
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 17 +++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++++
2 files changed, 21 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index ed3a4c8..4949ea9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -715,10 +715,23 @@ static bool ixgbe_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
return true;
}
+/**
+ * ixgbe_ipsec_free - called by xfrm garbage collections
+ * @xs: pointer to transformer state struct
+ *
+ * We don't have any garbage to collect, so we shouldn't bother
+ * implementing this function, but the XFRM code doesn't check for
+ * existence before calling the API callback.
+ **/
+static void ixgbe_ipsec_free(struct xfrm_state *xs)
+{
+}
+
static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
.xdo_dev_state_add = ixgbe_ipsec_add_sa,
.xdo_dev_state_delete = ixgbe_ipsec_del_sa,
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
+ .xdo_dev_state_free = ixgbe_ipsec_free,
};
/**
@@ -877,6 +890,10 @@ void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter)
ixgbe_ipsec_stop_engine(adapter);
ixgbe_ipsec_clear_hw_tables(adapter);
+ adapter->netdev->xfrmdev_ops = &ixgbe_xfrmdev_ops;
+ adapter->netdev->features |= NETIF_F_HW_ESP;
+ adapter->netdev->hw_enc_features |= NETIF_F_HW_ESP;
+
return;
err2:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 814268f..2e5d0a2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9796,6 +9796,10 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
features &= ~NETIF_F_TSO;
+ /* IPsec offload doesn't get along well with others *yet* */
+ if (skb->sp)
+ features &= ~(NETIF_F_TSO | NETIF_F_HW_CSUM);
+
return features;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v2 next-queue 09/10] ixgbe: ipsec offload stats
From: Shannon Nelson @ 2017-12-12 23:37 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, steffen.klassert, sowmini.varadhan
In-Reply-To: <1513121823-27944-1-git-send-email-shannon.nelson@oracle.com>
Add a simple statistic to count the ipsec offloads.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
v2: change per ring counter to adapter rx and tx counters
move tx_ipsec count to the tx clean code
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 2 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 ++++-
4 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 3d2b7bf..1dfe147 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -629,10 +629,12 @@ struct ixgbe_adapter {
int num_tx_queues;
u16 tx_itr_setting;
u16 tx_work_limit;
+ u64 tx_ipsec;
/* Rx fast path data */
int num_rx_queues;
u16 rx_itr_setting;
+ u64 rx_ipsec;
/* Port number used to identify VXLAN traffic */
__be16 vxlan_port;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index c3e7a81..bcf011e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -114,6 +114,8 @@ static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"tx_hwtstamp_timeouts", IXGBE_STAT(tx_hwtstamp_timeouts)},
{"tx_hwtstamp_skipped", IXGBE_STAT(tx_hwtstamp_skipped)},
{"rx_hwtstamp_cleared", IXGBE_STAT(rx_hwtstamp_cleared)},
+ {"tx_ipsec", IXGBE_STAT(tx_ipsec)},
+ {"rx_ipsec", IXGBE_STAT(rx_ipsec)},
#ifdef IXGBE_FCOE
{"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)},
{"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)},
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 5ed8a4f..ed3a4c8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -837,6 +837,8 @@ void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
xo = xfrm_offload(skb);
xo->flags = CRYPTO_DONE;
xo->status = CRYPTO_SUCCESS;
+
+ adapter->rx_ipsec++;
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 84fbfb9..814268f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1173,7 +1173,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_tx_buffer *tx_buffer;
union ixgbe_adv_tx_desc *tx_desc;
- unsigned int total_bytes = 0, total_packets = 0;
+ unsigned int total_bytes = 0, total_packets = 0, total_ipsec = 0;
unsigned int budget = q_vector->tx.work_limit;
unsigned int i = tx_ring->next_to_clean;
@@ -1204,6 +1204,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
/* update the statistics for this packet */
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;
+ if (tx_buffer->tx_flags & IXGBE_TX_FLAGS_IPSEC)
+ total_ipsec++;
/* free the skb */
if (ring_is_xdp(tx_ring))
@@ -1266,6 +1268,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
u64_stats_update_end(&tx_ring->syncp);
q_vector->tx.total_bytes += total_bytes;
q_vector->tx.total_packets += total_packets;
+ adapter->tx_ipsec += total_ipsec;
if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
/* schedule immediate reset if we believe we hung */
--
2.7.4
^ permalink raw reply related
* [PATCH v2 next-queue 08/10] ixgbe: process the Tx ipsec offload
From: Shannon Nelson @ 2017-12-12 23:37 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, steffen.klassert, sowmini.varadhan
In-Reply-To: <1513121823-27944-1-git-send-email-shannon.nelson@oracle.com>
If the skb has a security association referenced in the skb, then
set up the Tx descriptor with the ipsec offload bits. While we're
here, we fix an oddly named field in the context descriptor struct.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
v2: use ihl != 5
move the ixgbe_ipsec_tx() call to near the call to ixgbe_tso()
drop the ipsec packet if the tx offload setup fails
simplify the ixgbe_ipsec_tx() parameters by using 'first'
leave out the ixgbe_tso() changes since we don't support TSO
with ipsec yet.
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 10 +++-
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 79 ++++++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 4 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 24 ++++++--
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 +-
5 files changed, 110 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index a094b23..3d2b7bf 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -171,10 +171,11 @@ enum ixgbe_tx_flags {
IXGBE_TX_FLAGS_CC = 0x08,
IXGBE_TX_FLAGS_IPV4 = 0x10,
IXGBE_TX_FLAGS_CSUM = 0x20,
+ IXGBE_TX_FLAGS_IPSEC = 0x40,
/* software defined flags */
- IXGBE_TX_FLAGS_SW_VLAN = 0x40,
- IXGBE_TX_FLAGS_FCOE = 0x80,
+ IXGBE_TX_FLAGS_SW_VLAN = 0x80,
+ IXGBE_TX_FLAGS_FCOE = 0x100,
};
/* VLAN info */
@@ -1014,6 +1015,8 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter);
void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb);
+int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first,
+ struct ixgbe_ipsec_tx_data *itd);
#else
static inline void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter) { };
static inline void ixgbe_stop_ipsec_offload(struct ixgbe_adapter *adapter) { };
@@ -1021,5 +1024,8 @@ static inline void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter) { };
static inline void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb) { };
+static inline int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring,
+ struct ixgbe_tx_buffer *first,
+ struct ixgbe_ipsec_tx_data *itd) { return 0; };
#endif /* CONFIG_XFRM_OFFLOAD */
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 7e421b8..5ed8a4f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -695,12 +695,91 @@ static void ixgbe_ipsec_del_sa(struct xfrm_state *xs)
}
}
+/**
+ * ixgbe_ipsec_offload_ok - can this packet use the xfrm hw offload
+ * @skb: current data packet
+ * @xs: pointer to transformer state struct
+ **/
+static bool ixgbe_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
+{
+ if (xs->props.family == AF_INET) {
+ /* Offload with IPv4 options is not supported yet */
+ if (ip_hdr(skb)->ihl != 5)
+ return false;
+ } else {
+ /* Offload with IPv6 extension headers is not support yet */
+ if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
+ return false;
+ }
+
+ return true;
+}
+
static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
.xdo_dev_state_add = ixgbe_ipsec_add_sa,
.xdo_dev_state_delete = ixgbe_ipsec_del_sa,
+ .xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
};
/**
+ * ixgbe_ipsec_tx - setup Tx flags for ipsec offload
+ * @tx_ring: outgoing context
+ * @first: current data packet
+ * @itd: ipsec Tx data for later use in building context descriptor
+ **/
+int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring,
+ struct ixgbe_tx_buffer *first,
+ struct ixgbe_ipsec_tx_data *itd)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev);
+ struct ixgbe_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_state *xs;
+ struct tx_sa *tsa;
+
+ if (!first->skb->sp->len) {
+ netdev_err(tx_ring->netdev, "%s: no xfrm state len = %d\n",
+ __func__, first->skb->sp->len);
+ return 0;
+ }
+
+ xs = xfrm_input_state(first->skb);
+ if (!xs) {
+ netdev_err(tx_ring->netdev, "%s: no xfrm_input_state() xs = %p\n",
+ __func__, xs);
+ return 0;
+ }
+
+ itd->sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX;
+ if (itd->sa_idx > IXGBE_IPSEC_MAX_SA_COUNT) {
+ netdev_err(tx_ring->netdev, "%s: bad sa_idx=%d handle=%lu\n",
+ __func__, itd->sa_idx, xs->xso.offload_handle);
+ return 0;
+ }
+
+ tsa = &ipsec->tx_tbl[itd->sa_idx];
+ if (!tsa->used) {
+ netdev_err(tx_ring->netdev, "%s: unused sa_idx=%d\n",
+ __func__, itd->sa_idx);
+ return 0;
+ }
+
+ first->tx_flags |= IXGBE_TX_FLAGS_IPSEC | IXGBE_TX_FLAGS_CC;
+
+ itd->flags = 0;
+ if (xs->id.proto == IPPROTO_ESP) {
+ itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP |
+ IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ if (first->protocol == htons(ETH_P_IP))
+ itd->flags |= IXGBE_ADVTXD_TUCMD_IPV4;
+ itd->trailer_len = xs->props.trailer_len;
+ }
+ if (tsa->encrypt)
+ itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN;
+
+ return 1;
+}
+
+/**
* ixgbe_ipsec_rx - decode ipsec bits from Rx descriptor
* @rx_ring: receiving ring
* @rx_desc: receive data descriptor
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index f1bfae0..d7875b3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -1261,7 +1261,7 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
}
void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
- u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
+ u32 fceof_saidx, u32 type_tucmd, u32 mss_l4len_idx)
{
struct ixgbe_adv_tx_context_desc *context_desc;
u16 i = tx_ring->next_to_use;
@@ -1275,7 +1275,7 @@ void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
- context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
+ context_desc->fceof_saidx = cpu_to_le32(fceof_saidx);
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 0ee1e5e..84fbfb9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7756,10 +7756,12 @@ static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb)
}
static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
- struct ixgbe_tx_buffer *first)
+ struct ixgbe_tx_buffer *first,
+ struct ixgbe_ipsec_tx_data *itd)
{
struct sk_buff *skb = first->skb;
u32 vlan_macip_lens = 0;
+ u32 fceof_saidx = 0;
u32 type_tucmd = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL) {
@@ -7800,7 +7802,12 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
- ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0);
+ if (first->tx_flags & IXGBE_TX_FLAGS_IPSEC) {
+ fceof_saidx |= itd->sa_idx;
+ type_tucmd |= itd->flags | itd->trailer_len;
+ }
+
+ ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fceof_saidx, type_tucmd, 0);
}
#define IXGBE_SET_FLAG(_input, _flag, _result) \
@@ -7843,11 +7850,16 @@ static void ixgbe_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc,
IXGBE_TX_FLAGS_CSUM,
IXGBE_ADVTXD_POPTS_TXSM);
- /* enble IPv4 checksum for TSO */
+ /* enable IPv4 checksum for TSO */
olinfo_status |= IXGBE_SET_FLAG(tx_flags,
IXGBE_TX_FLAGS_IPV4,
IXGBE_ADVTXD_POPTS_IXSM);
+ /* enable IPsec */
+ olinfo_status |= IXGBE_SET_FLAG(tx_flags,
+ IXGBE_TX_FLAGS_IPSEC,
+ IXGBE_ADVTXD_POPTS_IPSEC);
+
/*
* Check Context must be set if Tx switch is enabled, which it
* always is for case where virtual functions are running
@@ -8306,6 +8318,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
u32 tx_flags = 0;
unsigned short f;
u16 count = TXD_USE_COUNT(skb_headlen(skb));
+ struct ixgbe_ipsec_tx_data ipsec_tx = { 0 };
__be16 protocol = skb->protocol;
u8 hdr_len = 0;
@@ -8410,11 +8423,14 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
}
#endif /* IXGBE_FCOE */
+
+ if (skb->sp && !ixgbe_ipsec_tx(tx_ring, first, &ipsec_tx))
+ goto out_drop;
tso = ixgbe_tso(tx_ring, first, &hdr_len);
if (tso < 0)
goto out_drop;
else if (!tso)
- ixgbe_tx_csum(tx_ring, first);
+ ixgbe_tx_csum(tx_ring, first, &ipsec_tx);
/* add the ATR filter if ATR is on */
if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 3df0763..0ac725fa 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -2856,7 +2856,7 @@ union ixgbe_adv_rx_desc {
/* Context descriptors */
struct ixgbe_adv_tx_context_desc {
__le32 vlan_macip_lens;
- __le32 seqnum_seed;
+ __le32 fceof_saidx;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
--
2.7.4
^ permalink raw reply related
* [PATCH v2 next-queue 07/10] ixgbe: process the Rx ipsec offload
From: Shannon Nelson @ 2017-12-12 23:37 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, steffen.klassert, sowmini.varadhan
In-Reply-To: <1513121823-27944-1-git-send-email-shannon.nelson@oracle.com>
If the chip sees and decrypts an ipsec offload, set up the skb
sp pointer with the ralated SA info. Since the chip is rude
enough to keep to itself the table index it used for the
decryption, we have to do our own table lookup, using the
hash for speed.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
v2: no changes
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 6 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 89 ++++++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +
3 files changed, 98 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index af690c2..a094b23 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -1011,9 +1011,15 @@ s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter);
void ixgbe_stop_ipsec_offload(struct ixgbe_adapter *adapter);
void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter);
+void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb);
#else
static inline void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter) { };
static inline void ixgbe_stop_ipsec_offload(struct ixgbe_adapter *adapter) { };
static inline void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter) { };
+static inline void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb) { };
#endif /* CONFIG_XFRM_OFFLOAD */
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 049c195..7e421b8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -374,6 +374,35 @@ static int ixgbe_ipsec_find_empty_idx(struct ixgbe_ipsec *ipsec, bool rxtable)
}
/**
+ * ixgbe_ipsec_find_rx_state - find the state that matches
+ * @ipsec: pointer to ipsec struct
+ * @daddr: inbound address to match
+ * @proto: protocol to match
+ * @spi: SPI to match
+ *
+ * Returns a pointer to the matching SA state information
+ **/
+static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
+ __be32 daddr, u8 proto,
+ __be32 spi)
+{
+ struct rx_sa *rsa;
+ struct xfrm_state *ret = NULL;
+
+ rcu_read_lock();
+ hash_for_each_possible_rcu(ipsec->rx_sa_list, rsa, hlist, spi)
+ if (spi == rsa->xs->id.spi &&
+ daddr == rsa->xs->id.daddr.a4 &&
+ proto == rsa->xs->id.proto) {
+ ret = rsa->xs;
+ xfrm_state_hold(ret);
+ break;
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
+/**
* ixgbe_ipsec_parse_proto_keys - find the key and salt based on the protocol
* @xs: pointer to xfrm_state struct
* @mykey: pointer to key array to populate
@@ -672,6 +701,66 @@ static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
};
/**
+ * ixgbe_ipsec_rx - decode ipsec bits from Rx descriptor
+ * @rx_ring: receiving ring
+ * @rx_desc: receive data descriptor
+ * @skb: current data packet
+ *
+ * Determine if there was an ipsec encapsulation noticed, and if so set up
+ * the resulting status for later in the receive stack.
+ **/
+void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(rx_ring->netdev);
+ u16 pkt_info = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
+ u16 ipsec_pkt_types = IXGBE_RXDADV_PKTTYPE_IPSEC_AH |
+ IXGBE_RXDADV_PKTTYPE_IPSEC_ESP;
+ struct ixgbe_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_offload *xo = NULL;
+ struct xfrm_state *xs = NULL;
+ struct iphdr *iph;
+ u8 *c_hdr;
+ __be32 spi;
+ u8 proto;
+
+ /* we can assume no vlan header in the way, b/c the
+ * hw won't recognize the IPsec packet and anyway the
+ * currently vlan device doesn't support xfrm offload.
+ */
+ /* TODO: not supporting IPv6 yet */
+ iph = (struct iphdr *)(skb->data + ETH_HLEN);
+ c_hdr = (u8 *)iph + iph->ihl * 4;
+ switch (pkt_info & ipsec_pkt_types) {
+ case IXGBE_RXDADV_PKTTYPE_IPSEC_AH:
+ spi = ((struct ip_auth_hdr *)c_hdr)->spi;
+ proto = IPPROTO_AH;
+ break;
+ case IXGBE_RXDADV_PKTTYPE_IPSEC_ESP:
+ spi = ((struct ip_esp_hdr *)c_hdr)->spi;
+ proto = IPPROTO_ESP;
+ break;
+ default:
+ return;
+ }
+
+ xs = ixgbe_ipsec_find_rx_state(ipsec, iph->daddr, proto, spi);
+ if (unlikely(!xs))
+ return;
+
+ skb->sp = secpath_dup(skb->sp);
+ if (unlikely(!skb->sp))
+ return;
+
+ skb->sp->xvec[skb->sp->len++] = xs;
+ skb->sp->olen++;
+ xo = xfrm_offload(skb);
+ xo->flags = CRYPTO_DONE;
+ xo->status = CRYPTO_SUCCESS;
+}
+
+/**
* ixgbe_init_ipsec_offload - initialize security registers for IPSec operation
* @adapter: board private structure
**/
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 04e8b26..0ee1e5e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1755,6 +1755,9 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
skb_record_rx_queue(skb, rx_ring->queue_index);
+ if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_SECP))
+ ixgbe_ipsec_rx(rx_ring, rx_desc, skb);
+
skb->protocol = eth_type_trans(skb, dev);
}
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox