* [PATCH net-next 10/15] nfp: add RTsym access helpers
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
RTsyms may have special encodings for more complex symbol types.
For example symbols which are placed in external memory unit's
cache directly, constants or local memory. Add set of helpers
which will check for those special encodings and handle them
correctly.
For now only add direct cache accesses, we don't have a need to
access the other ones in foreseeable future.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
.../ethernet/netronome/nfp/nfpcore/nfp_nffw.h | 25 +++
.../netronome/nfp/nfpcore/nfp_rtsym.c | 146 ++++++++++++++++++
2 files changed, 171 insertions(+)
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
index df599d5b6bb3..04700278d00d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
@@ -98,6 +98,31 @@ const struct nfp_rtsym *nfp_rtsym_get(struct nfp_rtsym_table *rtbl, int idx);
const struct nfp_rtsym *
nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name);
+int __nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, void *buf, size_t len);
+int nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ void *buf, size_t len);
+int __nfp_rtsym_readl(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u32 *value);
+int nfp_rtsym_readl(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u32 *value);
+int __nfp_rtsym_readq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u64 *value);
+int nfp_rtsym_readq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u64 *value);
+int __nfp_rtsym_write(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, void *buf, size_t len);
+int nfp_rtsym_write(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ void *buf, size_t len);
+int __nfp_rtsym_writel(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u32 value);
+int nfp_rtsym_writel(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u32 value);
+int __nfp_rtsym_writeq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u64 value);
+int nfp_rtsym_writeq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u64 value);
+
u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
int *error);
int nfp_rtsym_write_le(struct nfp_rtsym_table *rtbl, const char *name,
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
index 9e34216578da..1c0b1b11b69f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
@@ -233,6 +233,152 @@ nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name)
return NULL;
}
+static int
+nfp_rtsym_to_dest(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u32 *cpp_id, u64 *addr)
+{
+ *addr = sym->addr + off;
+
+ if (sym->target == NFP_RTSYM_TARGET_EMU_CACHE) {
+ int locality_off = nfp_cpp_mu_locality_lsb(cpp);
+
+ *addr &= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK << locality_off);
+ *addr |= NFP_MU_ADDR_ACCESS_TYPE_DIRECT << locality_off;
+
+ *cpp_id = NFP_CPP_ISLAND_ID(NFP_CPP_TARGET_MU, action, token,
+ sym->domain);
+ } else if (sym->target < 0) {
+ nfp_err(cpp, "Unhandled RTsym target encoding: %d\n",
+ sym->target);
+ return -EINVAL;
+ } else {
+ *cpp_id = NFP_CPP_ISLAND_ID(sym->target, action, token,
+ sym->domain);
+ }
+
+ return 0;
+}
+
+int __nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, void *buf, size_t len)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_read(cpp, cpp_id, addr, buf, len);
+}
+
+int nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ void *buf, size_t len)
+{
+ return __nfp_rtsym_read(cpp, sym, NFP_CPP_ACTION_RW, 0, off, buf, len);
+}
+
+int __nfp_rtsym_readl(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u32 *value)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_readl(cpp, cpp_id, addr, value);
+}
+
+int nfp_rtsym_readl(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u32 *value)
+{
+ return __nfp_rtsym_readl(cpp, sym, NFP_CPP_ACTION_RW, 0, off, value);
+}
+
+int __nfp_rtsym_readq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u64 *value)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_readq(cpp, cpp_id, addr, value);
+}
+
+int nfp_rtsym_readq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u64 *value)
+{
+ return __nfp_rtsym_readq(cpp, sym, NFP_CPP_ACTION_RW, 0, off, value);
+}
+
+int __nfp_rtsym_write(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, void *buf, size_t len)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_write(cpp, cpp_id, addr, buf, len);
+}
+
+int nfp_rtsym_write(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ void *buf, size_t len)
+{
+ return __nfp_rtsym_write(cpp, sym, NFP_CPP_ACTION_RW, 0, off, buf, len);
+}
+
+int __nfp_rtsym_writel(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u32 value)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_writel(cpp, cpp_id, addr, value);
+}
+
+int nfp_rtsym_writel(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u32 value)
+{
+ return __nfp_rtsym_writel(cpp, sym, NFP_CPP_ACTION_RW, 0, off, value);
+}
+
+int __nfp_rtsym_writeq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
+ u8 action, u8 token, u64 off, u64 value)
+{
+ u32 cpp_id;
+ u64 addr;
+ int err;
+
+ err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
+ if (err)
+ return err;
+
+ return nfp_cpp_writeq(cpp, cpp_id, addr, value);
+}
+
+int nfp_rtsym_writeq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
+ u64 value)
+{
+ return __nfp_rtsym_writeq(cpp, sym, NFP_CPP_ACTION_RW, 0, off, value);
+}
+
/**
* nfp_rtsym_read_le() - Read a simple unsigned scalar value from symbol
* @rtbl: NFP RTsym table
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 11/15] nfp: pass cpp_id to nfp_cpp_map_area()
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
Align nfp_cpp_map_area() with other CPP-level APIs and pass
encoded cpp_id/dest rather than target, action, domain tuple.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 8 ++++----
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h | 4 ++--
.../net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c | 12 ++++--------
.../net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c | 8 ++++++--
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 28516eecccc8..0b1ac9c234d1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -470,8 +470,8 @@ static void nfp_net_pci_unmap_mem(struct nfp_pf *pf)
static int nfp_net_pci_map_mem(struct nfp_pf *pf)
{
+ u32 min_size, cpp_id;
u8 __iomem *mem;
- u32 min_size;
int err;
min_size = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE;
@@ -519,9 +519,9 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf)
pf->vfcfg_tbl2 = NULL;
}
- mem = nfp_cpp_map_area(pf->cpp, "net.qc", 0, 0,
- NFP_PCIE_QUEUE(0), NFP_QCP_QUEUE_AREA_SZ,
- &pf->qc_area);
+ cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0);
+ mem = nfp_cpp_map_area(pf->cpp, "net.qc", cpp_id, NFP_PCIE_QUEUE(0),
+ NFP_QCP_QUEUE_AREA_SZ, &pf->qc_area);
if (IS_ERR(mem)) {
nfp_err(pf->cpp, "Failed to map Queue Controller area.\n");
err = PTR_ERR(mem);
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
index 991b8ed7e036..123e29cba6d1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
@@ -294,8 +294,8 @@ int nfp_cpp_writeq(struct nfp_cpp *cpp, u32 cpp_id,
unsigned long long address, u64 value);
u8 __iomem *
-nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, int domain, int target,
- u64 addr, unsigned long size, struct nfp_cpp_area **area);
+nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, u32 cpp_id, u64 addr,
+ unsigned long size, struct nfp_cpp_area **area);
struct nfp_cpp_mutex;
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c
index 20bad05e2e92..03fcde5fa137 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c
@@ -294,8 +294,7 @@ int nfp_cpp_explicit_write(struct nfp_cpp *cpp, u32 cpp_id, u64 addr,
* nfp_cpp_map_area() - Helper function to map an area
* @cpp: NFP CPP handler
* @name: Name for the area
- * @domain: CPP domain
- * @target: CPP target
+ * @cpp_id: CPP ID for operation
* @addr: CPP address
* @size: Size of the area
* @area: Area handle (output)
@@ -306,15 +305,12 @@ int nfp_cpp_explicit_write(struct nfp_cpp *cpp, u32 cpp_id, u64 addr,
* Return: Pointer to memory mapped area or ERR_PTR
*/
u8 __iomem *
-nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, int domain, int target,
- u64 addr, unsigned long size, struct nfp_cpp_area **area)
+nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, u32 cpp_id, u64 addr,
+ unsigned long size, struct nfp_cpp_area **area)
{
u8 __iomem *res;
- u32 dest;
- dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain);
-
- *area = nfp_cpp_area_alloc_acquire(cpp, name, dest, addr, size);
+ *area = nfp_cpp_area_alloc_acquire(cpp, name, cpp_id, addr, size);
if (!*area)
goto err_eio;
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
index 1c0b1b11b69f..4d98905c0651 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
@@ -481,18 +481,22 @@ nfp_rtsym_map(struct nfp_rtsym_table *rtbl, const char *name, const char *id,
{
const struct nfp_rtsym *sym;
u8 __iomem *mem;
+ u32 cpp_id;
sym = nfp_rtsym_lookup(rtbl, name);
if (!sym)
return (u8 __iomem *)ERR_PTR(-ENOENT);
+ cpp_id = NFP_CPP_ISLAND_ID(sym->target, NFP_CPP_ACTION_RW, 0,
+ sym->domain);
+
if (sym->size < min_size) {
nfp_err(rtbl->cpp, "Symbol %s too small\n", name);
return (u8 __iomem *)ERR_PTR(-EINVAL);
}
- mem = nfp_cpp_map_area(rtbl->cpp, id, sym->domain, sym->target,
- sym->addr, sym->size, area);
+ mem = nfp_cpp_map_area(rtbl->cpp, id, cpp_id, sym->addr,
+ sym->size, area);
if (IS_ERR(mem)) {
nfp_err(rtbl->cpp, "Failed to map symbol %s: %ld\n",
name, PTR_ERR(mem));
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 12/15] nfp: convert existing RTsym helpers to full target decoding
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
Make nfp_rtsym_{read,write}_le() and nfp_rtsym_map() use the new
target resolution helpers to allow accessing in-cache symbols.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
.../netronome/nfp/nfpcore/nfp_rtsym.c | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
index 4d98905c0651..28e5ed0bb31d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
@@ -395,7 +395,7 @@ u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
int *error)
{
const struct nfp_rtsym *sym;
- u32 val32, id;
+ u32 val32;
u64 val;
int err;
@@ -405,15 +405,13 @@ u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
goto exit;
}
- id = NFP_CPP_ISLAND_ID(sym->target, NFP_CPP_ACTION_RW, 0, sym->domain);
-
switch (sym->size) {
case 4:
- err = nfp_cpp_readl(rtbl->cpp, id, sym->addr, &val32);
+ err = nfp_rtsym_readl(rtbl->cpp, sym, 0, &val32);
val = val32;
break;
case 8:
- err = nfp_cpp_readq(rtbl->cpp, id, sym->addr, &val);
+ err = nfp_rtsym_readq(rtbl->cpp, sym, 0, &val);
break;
default:
nfp_err(rtbl->cpp,
@@ -449,20 +447,17 @@ int nfp_rtsym_write_le(struct nfp_rtsym_table *rtbl, const char *name,
{
const struct nfp_rtsym *sym;
int err;
- u32 id;
sym = nfp_rtsym_lookup(rtbl, name);
if (!sym)
return -ENOENT;
- id = NFP_CPP_ISLAND_ID(sym->target, NFP_CPP_ACTION_RW, 0, sym->domain);
-
switch (sym->size) {
case 4:
- err = nfp_cpp_writel(rtbl->cpp, id, sym->addr, value);
+ err = nfp_rtsym_writel(rtbl->cpp, sym, 0, value);
break;
case 8:
- err = nfp_cpp_writeq(rtbl->cpp, id, sym->addr, value);
+ err = nfp_rtsym_writeq(rtbl->cpp, sym, 0, value);
break;
default:
nfp_err(rtbl->cpp,
@@ -482,21 +477,26 @@ nfp_rtsym_map(struct nfp_rtsym_table *rtbl, const char *name, const char *id,
const struct nfp_rtsym *sym;
u8 __iomem *mem;
u32 cpp_id;
+ u64 addr;
+ int err;
sym = nfp_rtsym_lookup(rtbl, name);
if (!sym)
return (u8 __iomem *)ERR_PTR(-ENOENT);
- cpp_id = NFP_CPP_ISLAND_ID(sym->target, NFP_CPP_ACTION_RW, 0,
- sym->domain);
+ err = nfp_rtsym_to_dest(rtbl->cpp, sym, NFP_CPP_ACTION_RW, 0, 0,
+ &cpp_id, &addr);
+ if (err) {
+ nfp_err(rtbl->cpp, "Symbol %s mapping failed\n", name);
+ return (u8 __iomem *)ERR_PTR(err);
+ }
if (sym->size < min_size) {
nfp_err(rtbl->cpp, "Symbol %s too small\n", name);
return (u8 __iomem *)ERR_PTR(-EINVAL);
}
- mem = nfp_cpp_map_area(rtbl->cpp, id, cpp_id, sym->addr,
- sym->size, area);
+ mem = nfp_cpp_map_area(rtbl->cpp, id, cpp_id, addr, sym->size, area);
if (IS_ERR(mem)) {
nfp_err(rtbl->cpp, "Failed to map symbol %s: %ld\n",
name, PTR_ERR(mem));
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 14/15] nfp: support access to absolute RTsyms
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
Add support in nfpcore for reading the absolute RTsyms.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
.../ethernet/netronome/nfp/nfpcore/nfp_nffw.h | 13 +++---
.../netronome/nfp/nfpcore/nfp_rtsym.c | 42 +++++++++++++++++--
2 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
index 04700278d00d..8d2cbdf4d517 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
@@ -61,10 +61,12 @@ void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size);
/* Implemented in nfp_rtsym.c */
-#define NFP_RTSYM_TYPE_NONE 0
-#define NFP_RTSYM_TYPE_OBJECT 1
-#define NFP_RTSYM_TYPE_FUNCTION 2
-#define NFP_RTSYM_TYPE_ABS 3
+enum nfp_rtsym_type {
+ NFP_RTSYM_TYPE_NONE = 0,
+ NFP_RTSYM_TYPE_OBJECT = 1,
+ NFP_RTSYM_TYPE_FUNCTION = 2,
+ NFP_RTSYM_TYPE_ABS = 3,
+};
#define NFP_RTSYM_TARGET_NONE 0
#define NFP_RTSYM_TARGET_LMEM -1
@@ -83,7 +85,7 @@ struct nfp_rtsym {
const char *name;
u64 addr;
u64 size;
- int type;
+ enum nfp_rtsym_type type;
int target;
int domain;
};
@@ -98,6 +100,7 @@ const struct nfp_rtsym *nfp_rtsym_get(struct nfp_rtsym_table *rtbl, int idx);
const struct nfp_rtsym *
nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name);
+u64 nfp_rtsym_size(const struct nfp_rtsym *rtsym);
int __nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
u8 action, u8 token, u64 off, void *buf, size_t len);
int nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym, u64 off,
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
index 28e5ed0bb31d..108ce8c5e68e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
@@ -233,10 +233,32 @@ nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name)
return NULL;
}
+u64 nfp_rtsym_size(const struct nfp_rtsym *sym)
+{
+ switch (sym->type) {
+ case NFP_RTSYM_TYPE_NONE:
+ pr_err("rtsym type NONE\n");
+ return 0;
+ default:
+ pr_warn("Unknown rtsym type: %d\n", sym->type);
+ /* fall through */
+ case NFP_RTSYM_TYPE_OBJECT:
+ case NFP_RTSYM_TYPE_FUNCTION:
+ return sym->size;
+ case NFP_RTSYM_TYPE_ABS:
+ return sizeof(u64);
+ }
+}
+
static int
nfp_rtsym_to_dest(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
u8 action, u8 token, u64 off, u32 *cpp_id, u64 *addr)
{
+ if (sym->type != NFP_RTSYM_TYPE_OBJECT) {
+ nfp_err(cpp, "Direct access attempt to non-object rtsym\n");
+ return -EINVAL;
+ }
+
*addr = sym->addr + off;
if (sym->target == NFP_RTSYM_TARGET_EMU_CACHE) {
@@ -266,6 +288,15 @@ int __nfp_rtsym_read(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
u64 addr;
int err;
+ if (sym->type == NFP_RTSYM_TYPE_ABS) {
+ __le64 tmp = cpu_to_le64(sym->addr);
+
+ len = min(len, sizeof(tmp));
+ memcpy(buf, &tmp, len);
+
+ return len;
+ }
+
err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
if (err)
return err;
@@ -306,6 +337,9 @@ int __nfp_rtsym_readq(struct nfp_cpp *cpp, const struct nfp_rtsym *sym,
u64 addr;
int err;
+ if (sym->type == NFP_RTSYM_TYPE_ABS)
+ return sym->addr;
+
err = nfp_rtsym_to_dest(cpp, sym, action, token, off, &cpp_id, &addr);
if (err)
return err;
@@ -405,7 +439,7 @@ u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
goto exit;
}
- switch (sym->size) {
+ switch (nfp_rtsym_size(sym)) {
case 4:
err = nfp_rtsym_readl(rtbl->cpp, sym, 0, &val32);
val = val32;
@@ -416,7 +450,7 @@ u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
default:
nfp_err(rtbl->cpp,
"rtsym '%s' unsupported or non-scalar size: %lld\n",
- name, sym->size);
+ name, nfp_rtsym_size(sym));
err = -EINVAL;
break;
}
@@ -452,7 +486,7 @@ int nfp_rtsym_write_le(struct nfp_rtsym_table *rtbl, const char *name,
if (!sym)
return -ENOENT;
- switch (sym->size) {
+ switch (nfp_rtsym_size(sym)) {
case 4:
err = nfp_rtsym_writel(rtbl->cpp, sym, 0, value);
break;
@@ -462,7 +496,7 @@ int nfp_rtsym_write_le(struct nfp_rtsym_table *rtbl, const char *name,
default:
nfp_err(rtbl->cpp,
"rtsym '%s' unsupported or non-scalar size: %lld\n",
- name, sym->size);
+ name, nfp_rtsym_size(sym));
err = -EINVAL;
break;
}
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 13/15] nfp: convert all RTsym users to use new read/write helpers
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
Convert all users of RTsym to the new set of helpers which
handle all targets correctly.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
drivers/net/ethernet/netronome/nfp/abm/ctrl.c | 28 ++++++-------------
drivers/net/ethernet/netronome/nfp/nfp_main.c | 28 ++++++++-----------
.../netronome/nfp/nfp_net_debugdump.c | 13 ++-------
3 files changed, 23 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
index b157ccd8c80f..53fb40aa83db 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
@@ -55,30 +55,21 @@
#define NFP_QMSTAT_DROP 16
#define NFP_QMSTAT_ECN 24
-static unsigned long long
-nfp_abm_q_lvl_thrs(struct nfp_abm_link *alink, unsigned int queue)
-{
- return alink->abm->q_lvls->addr +
- (alink->queue_base + queue) * NFP_QLVL_STRIDE + NFP_QLVL_THRS;
-}
-
static int
nfp_abm_ctrl_stat(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
unsigned int stride, unsigned int offset, unsigned int i,
bool is_u64, u64 *res)
{
struct nfp_cpp *cpp = alink->abm->app->cpp;
- u32 val32, mur;
- u64 val, addr;
+ u64 val, sym_offset;
+ u32 val32;
int err;
- mur = NFP_CPP_ATOMIC_RD(sym->target, sym->domain);
-
- addr = sym->addr + (alink->queue_base + i) * stride + offset;
+ sym_offset = (alink->queue_base + i) * stride + offset;
if (is_u64)
- err = nfp_cpp_readq(cpp, mur, addr, &val);
+ err = __nfp_rtsym_readq(cpp, sym, 3, 0, sym_offset, &val);
else
- err = nfp_cpp_readl(cpp, mur, addr, &val32);
+ err = __nfp_rtsym_readl(cpp, sym, 3, 0, sym_offset, &val32);
if (err) {
nfp_err(cpp,
"RED offload reading stat failed on vNIC %d queue %d\n",
@@ -114,13 +105,12 @@ nfp_abm_ctrl_stat_all(struct nfp_abm_link *alink, const struct nfp_rtsym *sym,
int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int i, u32 val)
{
struct nfp_cpp *cpp = alink->abm->app->cpp;
- u32 muw;
+ u64 sym_offset;
int err;
- muw = NFP_CPP_ATOMIC_WR(alink->abm->q_lvls->target,
- alink->abm->q_lvls->domain);
-
- err = nfp_cpp_writel(cpp, muw, nfp_abm_q_lvl_thrs(alink, i), val);
+ sym_offset = (alink->queue_base + i) * NFP_QLVL_STRIDE + NFP_QLVL_THRS;
+ err = __nfp_rtsym_writel(cpp, alink->abm->q_lvls, 4, 0,
+ sym_offset, val);
if (err) {
nfp_err(cpp, "RED offload setting level failed on vNIC %d queue %d\n",
alink->id, i);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index b0f1c313fee0..61b4b2055784 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -116,23 +116,18 @@ nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
void *out_data, u64 out_length)
{
- unsigned long long addr;
unsigned long err_at;
u64 max_data_sz;
u32 val = 0;
- u32 cpp_id;
int n, err;
if (!pf->mbox)
return -EOPNOTSUPP;
- cpp_id = NFP_CPP_ISLAND_ID(pf->mbox->target, NFP_CPP_ACTION_RW, 0,
- pf->mbox->domain);
- addr = pf->mbox->addr;
max_data_sz = pf->mbox->size - NFP_MBOX_SYM_MIN_SIZE;
/* Check if cmd field is clear */
- err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val);
+ err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
if (err || val) {
nfp_warn(pf->cpp, "failed to issue command (%u): %u, err: %d\n",
cmd, val, err);
@@ -140,30 +135,29 @@ int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
}
in_length = min(in_length, max_data_sz);
- n = nfp_cpp_write(pf->cpp, cpp_id, addr + NFP_MBOX_DATA,
- in_data, in_length);
+ n = nfp_rtsym_write(pf->cpp, pf->mbox, NFP_MBOX_DATA, in_data,
+ in_length);
if (n != in_length)
return -EIO;
/* Write data_len and wipe reserved */
- err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN,
- in_length);
+ err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, in_length);
if (err)
return err;
/* Read back for ordering */
- err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val);
+ err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
if (err)
return err;
/* Write cmd and wipe return value */
- err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, cmd);
+ err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_CMD, cmd);
if (err)
return err;
err_at = jiffies + 5 * HZ;
while (true) {
/* Wait for command to go to 0 (NFP_MBOX_NO_CMD) */
- err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val);
+ err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
if (err)
return err;
if (!val)
@@ -176,18 +170,18 @@ int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
}
/* Copy output if any (could be error info, do it before reading ret) */
- err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val);
+ err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
if (err)
return err;
out_length = min_t(u32, val, min(out_length, max_data_sz));
- n = nfp_cpp_read(pf->cpp, cpp_id, addr + NFP_MBOX_DATA,
- out_data, out_length);
+ n = nfp_rtsym_read(pf->cpp, pf->mbox, NFP_MBOX_DATA,
+ out_data, out_length);
if (n != out_length)
return -EIO;
/* Check if there is an error */
- err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_RET, &val);
+ err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_RET, &val);
if (err)
return err;
if (val)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
index bb8ed460086e..242c9363e9e8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
@@ -188,7 +188,6 @@ nfp_net_dump_load_dumpspec(struct nfp_cpp *cpp, struct nfp_rtsym_table *rtbl)
const struct nfp_rtsym *specsym;
struct nfp_dumpspec *dumpspec;
int bytes_read;
- u32 cpp_id;
specsym = nfp_rtsym_lookup(rtbl, NFP_DUMP_SPEC_RTSYM);
if (!specsym)
@@ -201,11 +200,8 @@ nfp_net_dump_load_dumpspec(struct nfp_cpp *cpp, struct nfp_rtsym_table *rtbl)
dumpspec->size = specsym->size;
- cpp_id = NFP_CPP_ISLAND_ID(specsym->target, NFP_CPP_ACTION_RW, 0,
- specsym->domain);
-
- bytes_read = nfp_cpp_read(cpp, cpp_id, specsym->addr, dumpspec->data,
- specsym->size);
+ bytes_read = nfp_rtsym_read(cpp, specsym, 0, dumpspec->data,
+ specsym->size);
if (bytes_read != specsym->size) {
vfree(dumpspec);
nfp_warn(cpp, "Debug dump specification read failed.\n");
@@ -644,7 +640,6 @@ nfp_dump_single_rtsym(struct nfp_pf *pf, struct nfp_dumpspec_rtsym *spec,
const struct nfp_rtsym *sym;
u32 tl_len, key_len;
int bytes_read;
- u32 cpp_id;
void *dest;
int err;
@@ -683,11 +678,9 @@ nfp_dump_single_rtsym(struct nfp_pf *pf, struct nfp_dumpspec_rtsym *spec,
cpp_params.action = NFP_CPP_ACTION_RW;
cpp_params.token = 0;
cpp_params.island = sym->domain;
- cpp_id = nfp_get_numeric_cpp_id(&cpp_params);
dump_header->cpp.cpp_id = cpp_params;
dump_header->cpp.offset = cpu_to_be32(sym->addr);
- bytes_read = nfp_cpp_read(pf->cpp, cpp_id, sym->addr, dest,
- sym_size);
+ bytes_read = nfp_rtsym_read(pf->cpp, sym, 0, dest, sym_size);
if (bytes_read != sym_size) {
if (bytes_read >= 0)
bytes_read = -EIO;
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 15/15] nfp: make RTsym users handle absolute symbols correctly
From: Jakub Kicinski @ 2018-08-28 20:20 UTC (permalink / raw)
To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20180828202047.1305-1-jakub.kicinski@netronome.com>
Make the RTsym users access the size via the helper, which
takes care of special handling of absolute symbols.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Francois H. Theron <francois.theron@netronome.com>
---
drivers/net/ethernet/netronome/nfp/abm/ctrl.c | 4 +-
drivers/net/ethernet/netronome/nfp/nfp_main.c | 6 +--
.../netronome/nfp/nfp_net_debugdump.c | 43 +++++++------------
3 files changed, 21 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
index 53fb40aa83db..5b06f07c78cd 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c
@@ -280,10 +280,10 @@ nfp_abm_ctrl_find_rtsym(struct nfp_pf *pf, const char *name, unsigned int size)
nfp_err(pf->cpp, "Symbol '%s' not found\n", name);
return ERR_PTR(-ENOENT);
}
- if (sym->size != size) {
+ if (nfp_rtsym_size(sym) != size) {
nfp_err(pf->cpp,
"Symbol '%s' wrong size: expected %u got %llu\n",
- name, size, sym->size);
+ name, size, nfp_rtsym_size(sym));
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index 61b4b2055784..9474a4eed8ce 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -124,7 +124,7 @@ int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
if (!pf->mbox)
return -EOPNOTSUPP;
- max_data_sz = pf->mbox->size - NFP_MBOX_SYM_MIN_SIZE;
+ max_data_sz = nfp_rtsym_size(pf->mbox) - NFP_MBOX_SYM_MIN_SIZE;
/* Check if cmd field is clear */
err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
@@ -566,9 +566,9 @@ static int nfp_pf_find_rtsyms(struct nfp_pf *pf)
/* Optional per-PCI PF mailbox */
snprintf(pf_symbol, sizeof(pf_symbol), NFP_MBOX_SYM_NAME, pf_id);
pf->mbox = nfp_rtsym_lookup(pf->rtbl, pf_symbol);
- if (pf->mbox && pf->mbox->size < NFP_MBOX_SYM_MIN_SIZE) {
+ if (pf->mbox && nfp_rtsym_size(pf->mbox) < NFP_MBOX_SYM_MIN_SIZE) {
nfp_err(pf->cpp, "PF mailbox symbol too small: %llu < %d\n",
- pf->mbox->size, NFP_MBOX_SYM_MIN_SIZE);
+ nfp_rtsym_size(pf->mbox), NFP_MBOX_SYM_MIN_SIZE);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
index 242c9363e9e8..b6b897840ac5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugdump.c
@@ -188,21 +188,21 @@ nfp_net_dump_load_dumpspec(struct nfp_cpp *cpp, struct nfp_rtsym_table *rtbl)
const struct nfp_rtsym *specsym;
struct nfp_dumpspec *dumpspec;
int bytes_read;
+ u64 sym_size;
specsym = nfp_rtsym_lookup(rtbl, NFP_DUMP_SPEC_RTSYM);
if (!specsym)
return NULL;
+ sym_size = nfp_rtsym_size(specsym);
/* expected size of this buffer is in the order of tens of kilobytes */
- dumpspec = vmalloc(sizeof(*dumpspec) + specsym->size);
+ dumpspec = vmalloc(sizeof(*dumpspec) + sym_size);
if (!dumpspec)
return NULL;
+ dumpspec->size = sym_size;
- dumpspec->size = specsym->size;
-
- bytes_read = nfp_rtsym_read(cpp, specsym, 0, dumpspec->data,
- specsym->size);
- if (bytes_read != specsym->size) {
+ bytes_read = nfp_rtsym_read(cpp, specsym, 0, dumpspec->data, sym_size);
+ if (bytes_read != sym_size) {
vfree(dumpspec);
nfp_warn(cpp, "Debug dump specification read failed.\n");
return NULL;
@@ -262,7 +262,6 @@ nfp_calc_rtsym_dump_sz(struct nfp_pf *pf, struct nfp_dump_tl *spec)
struct nfp_dumpspec_rtsym *spec_rtsym;
const struct nfp_rtsym *sym;
u32 tl_len, key_len;
- u32 size;
spec_rtsym = (struct nfp_dumpspec_rtsym *)spec;
tl_len = be32_to_cpu(spec->length);
@@ -274,13 +273,8 @@ nfp_calc_rtsym_dump_sz(struct nfp_pf *pf, struct nfp_dump_tl *spec)
if (!sym)
return nfp_dump_error_tlv_size(spec);
- if (sym->type == NFP_RTSYM_TYPE_ABS)
- size = sizeof(sym->addr);
- else
- size = sym->size;
-
return ALIGN8(offsetof(struct nfp_dump_rtsym, rtsym) + key_len + 1) +
- ALIGN8(size);
+ ALIGN8(nfp_rtsym_size(sym));
}
static int
@@ -652,11 +646,7 @@ nfp_dump_single_rtsym(struct nfp_pf *pf, struct nfp_dumpspec_rtsym *spec,
if (!sym)
return nfp_dump_error_tlv(&spec->tl, -ENOENT, dump);
- if (sym->type == NFP_RTSYM_TYPE_ABS)
- sym_size = sizeof(sym->addr);
- else
- sym_size = sym->size;
-
+ sym_size = nfp_rtsym_size(sym);
header_size =
ALIGN8(offsetof(struct nfp_dump_rtsym, rtsym) + key_len + 1);
total_size = header_size + ALIGN8(sym_size);
@@ -671,21 +661,20 @@ nfp_dump_single_rtsym(struct nfp_pf *pf, struct nfp_dumpspec_rtsym *spec,
memcpy(dump_header->rtsym, spec->rtsym, key_len + 1);
dump_header->cpp.dump_length = cpu_to_be32(sym_size);
- if (sym->type == NFP_RTSYM_TYPE_ABS) {
- *(u64 *)dest = sym->addr;
- } else {
+ if (sym->type != NFP_RTSYM_TYPE_ABS) {
cpp_params.target = sym->target;
cpp_params.action = NFP_CPP_ACTION_RW;
cpp_params.token = 0;
cpp_params.island = sym->domain;
dump_header->cpp.cpp_id = cpp_params;
dump_header->cpp.offset = cpu_to_be32(sym->addr);
- bytes_read = nfp_rtsym_read(pf->cpp, sym, 0, dest, sym_size);
- if (bytes_read != sym_size) {
- if (bytes_read >= 0)
- bytes_read = -EIO;
- dump_header->error = cpu_to_be32(bytes_read);
- }
+ }
+
+ bytes_read = nfp_rtsym_read(pf->cpp, sym, 0, dest, sym_size);
+ if (bytes_read != sym_size) {
+ if (bytes_read >= 0)
+ bytes_read = -EIO;
+ dump_header->error = cpu_to_be32(bytes_read);
}
return 0;
--
2.17.1
^ permalink raw reply related
* [PATCH] rtnetlink: expose value from SET_NETDEV_DEVTYPE via IFLA_DEVTYPE attribute
From: Marcel Holtmann @ 2018-08-28 20:58 UTC (permalink / raw)
To: netdev, davem
The name value from SET_NETDEV_DEVTYPE only ended up in the uevent sysfs
file as DEVTYPE= information. To avoid any kind of race conditions
between netlink messages and reading from sysfs, it is useful to add the
same string as new IFLA_DEVTYPE attribute included in the RTM_NEWLINK
messages.
For network managing daemons that have to classify ARPHRD_ETHER network
devices into different types (like Wireless LAN, Bluetooth etc.), this
avoids the extra round trip to sysfs and parsing of the uevent file.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/uapi/linux/if_link.h | 2 ++
net/core/rtnetlink.c | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 43391e2d1153..781294972bb4 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -166,6 +166,8 @@ enum {
IFLA_NEW_IFINDEX,
IFLA_MIN_MTU,
IFLA_MAX_MTU,
+ IFLA_DEVTYPE, /* Name value from SET_NETDEV_DEVTYPE */
+#define IFLA_DEVTYPE IFLA_DEVTYPE
__IFLA_MAX
};
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 24431e578310..bd288710f9bf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -970,6 +970,14 @@ static size_t rtnl_xdp_size(void)
return xdp_size;
}
+static size_t rtnl_devtype_size(const struct net_device *dev)
+{
+ if (!dev->dev.type || !dev->dev.type->name)
+ return 0;
+
+ return strlen(dev->dev.type->name) + 1;
+}
+
static noinline size_t if_nlmsg_size(const struct net_device *dev,
u32 ext_filter_mask)
{
@@ -1017,6 +1025,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
+ nla_total_size(4) /* IFLA_CARRIER_DOWN_COUNT */
+ nla_total_size(4) /* IFLA_MIN_MTU */
+ nla_total_size(4) /* IFLA_MAX_MTU */
+ + rtnl_devtype_size(dev) /* IFLA_DEVTYPE */
+ 0;
}
@@ -1679,6 +1688,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
nla_put_s32(skb, IFLA_NEW_IFINDEX, new_ifindex) < 0)
goto nla_put_failure;
+ if (dev->dev.type && dev->dev.type->name)
+ nla_put_string(skb, IFLA_DEVTYPE, dev->dev.type->name);
rcu_read_lock();
if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
@@ -1738,6 +1749,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_CARRIER_DOWN_COUNT] = { .type = NLA_U32 },
[IFLA_MIN_MTU] = { .type = NLA_U32 },
[IFLA_MAX_MTU] = { .type = NLA_U32 },
+ [IFLA_DEVTYPE] = { .type = NLA_STRING },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
--
2.14.4
^ permalink raw reply related
* [PATCH 3/3] Documentation/ABI: document /sys/class/net/*/dev_port
From: Arseny Maslennikov @ 2018-08-28 21:01 UTC (permalink / raw)
To: linux-rdma; +Cc: Arseny Maslennikov, Doug Ledford, Jason Gunthorpe, netdev
In-Reply-To: <20180828210117.6437-1-ar@cs.msu.ru>
The sysfs field was introduced 4 years ago along with fixes to various
drivers that erroneously used `dev_id' for that purpose, but it was not
properly documented anywhere.
See commit v3.14-rc3-739-g3f85944fe207.
Signed-off-by: Arseny Maslennikov <ar@cs.msu.ru>
---
Documentation/ABI/testing/sysfs-class-net | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-net b/Documentation/ABI/testing/sysfs-class-net
index 2f1788111cd9..1593d8997ade 100644
--- a/Documentation/ABI/testing/sysfs-class-net
+++ b/Documentation/ABI/testing/sysfs-class-net
@@ -91,6 +91,16 @@ Description:
stacked (e.g: VLAN interfaces) but still have the same MAC
address as their parent device.
+What: /sys/class/net/<iface>/dev_port
+Date: February 2014
+KernelVersion: 3.15
+Contact: netdev@vger.kernel.org
+Description:
+ Indicates the port number of this network device, formatted
+ as a decimal value. Some NICs have multiple independent ports
+ on the same PCI bus, device and function. This field allows
+ userspace to distinguish the respective interfaces.
+
What: /sys/class/net/<iface>/dormant
Date: March 2006
KernelVersion: 2.6.17
--
2.18.0
^ permalink raw reply related
* [PATCH 2/3] IB/ipoib: Stop using dev_id to expose port numbers
From: Arseny Maslennikov @ 2018-08-28 21:01 UTC (permalink / raw)
To: linux-rdma; +Cc: Arseny Maslennikov, Doug Ledford, Jason Gunthorpe, netdev
In-Reply-To: <20180828210117.6437-1-ar@cs.msu.ru>
Some InfiniBand network devices have multiple ports on the same PCI
function. Prior to this the kernel erroneously used the `dev_id' sysfs
field of those network interfaces to convey the port number to userspace.
`dev_id' is currently reserved for distinguishing stacked ifaces
(e.g: VLANs) with the same hardware address as their parent device.
Similar fixes to net/mlx4_en and many other drivers, which started
exporting this information through `dev_id' before 3.15, were accepted
into the kernel 4 years ago.
See 76a066f2a2a0268b565459c417b59724b5a3197b, commit message:
`net/mlx4_en: Expose port number through sysfs'.
This commit is separated from the previous one since we may wish to
preserve backwards compatibility with userspace being already dependent
on `dev_id' being different.
Signed-off-by: Arseny Maslennikov <ar@cs.msu.ru>
---
drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fcd69273de91..ba16a63ee303 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1880,7 +1880,6 @@ static int ipoib_parent_init(struct net_device *ndev)
sizeof(union ib_gid));
SET_NETDEV_DEV(priv->dev, priv->ca->dev.parent);
- priv->dev->dev_id = priv->port - 1;
priv->dev->dev_port = priv->port - 1;
return 0;
--
2.18.0
^ permalink raw reply related
* [PATCH 1/3] IB/ipoib: Use dev_port to expose network interface port numbers
From: Arseny Maslennikov @ 2018-08-28 21:01 UTC (permalink / raw)
To: linux-rdma; +Cc: Arseny Maslennikov, Doug Ledford, Jason Gunthorpe, netdev
In-Reply-To: <20180828210117.6437-1-ar@cs.msu.ru>
Some InfiniBand network devices have multiple ports on the same PCI
function. This initializes the `dev_port' sysfs field of those
network interfaces with their port number.
The use of `dev_id' was considered correct until Linux 3.15,
when another field, `dev_port', was defined for this particular
purpose and `dev_id' was reserved for distinguishing stacked ifaces
(e.g: VLANs) with the same hardware address as their parent device.
Similar fixes to net/mlx4_en and many other drivers, which started
exporting this information through `dev_id' before 3.15, were accepted
into the kernel 4 years ago.
See 76a066f2a2a0268b565459c417b59724b5a3197b, commit message:
`net/mlx4_en: Expose port number through sysfs'.
Signed-off-by: Arseny Maslennikov <ar@cs.msu.ru>
---
drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e3d28f9ad9c0..fcd69273de91 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1881,6 +1881,7 @@ static int ipoib_parent_init(struct net_device *ndev)
SET_NETDEV_DEV(priv->dev, priv->ca->dev.parent);
priv->dev->dev_id = priv->port - 1;
+ priv->dev->dev_port = priv->port - 1;
return 0;
}
--
2.18.0
^ permalink raw reply related
* [PATCH 0/3] IB/ipoib: Use dev_port to disambiguate port numbers
From: Arseny Maslennikov @ 2018-08-28 21:01 UTC (permalink / raw)
To: linux-rdma; +Cc: Arseny Maslennikov, Doug Ledford, Jason Gunthorpe, netdev
Pre-3.15 userspace had trouble distinguishing different ports
of a NIC on a single PCI bus/device/function. To solve this,
a sysfs field `dev_port' was introduced quite a while ago
(commit v3.14-rc3-739-g3f85944fe207), and some relevant device
drivers were fixed to use it, but not in case of IPoIB.
The convention for some reason never got documented in the kernel, but
was immediately adopted by userspace (notably udev[1][2], biosdevname[3])
3/3 documents the sysfs field — that's why I'm CC-ing netdev.
This series was tested on and applies to 4.19-rc1.
[1] https://lists.freedesktop.org/archives/systemd-devel/2014-June/020788.html
[2] https://lists.freedesktop.org/archives/systemd-devel/2014-July/020804.html
[3] https://github.com/CloudAutomationNTools/biosdevname/blob/c795d51dd93a5309652f0d635f12a3ecfabfaa72/src/eths.c#L38
Arseny Maslennikov (3):
IB/ipoib: Use dev_port to expose network interface port numbers
IB/ipoib: Stop using dev_id to expose port numbers
Documentation/ABI: document /sys/class/net/*/dev_port
Documentation/ABI/testing/sysfs-class-net | 10 ++++++++++
drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +-
2 files changed, 11 insertions(+), 1 deletion(-)
--
2.18.0
^ permalink raw reply
* Your reply
From: Ruby @ 2018-08-28 14:40 UTC (permalink / raw)
To: netdev
We provide photoshop services to some of the companies from around the
world.
We have worked on tons of images ever since our team establishment in 2009.
Many online retail companies use our services for retouching electronics,
jewelry, apparels, furniture
etc. by getting the images of their products enhanced.
Here are the details of what we provide:
Clipping path;
Deep etch process
Image masking
Remove background
Portrait retouching
Jewelry retouching
Fashion retouching
Please reply back for further info.
We can provide testing for your photos if needed.
Thanks,
Ruby
^ permalink raw reply
* [net-next 00/13][pull request] 10GbE Intel Wired LAN Driver Updates 2018-08-28
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Jeff Kirsher, netdev, nhorman, sassmann, jogreene
This series contains updates to ixgbe and ixgbevf only.
Sebastian adds support for firmware NVM recovery mode, which logs a
message when errors are detected and un-registers the device. Also
fixed RSS type recognition with VF to VF communication.
Shannon Nelson implements IPsec hardware offload for VF devices in
Intel's 10GbE x540 family of Ethernet devices.
The IPsec HW offload feature has been in the x540/Niantic family of
network devices since their release in 2009, but there was no Linux
kernel support for the offload until 2017. After the XFRM code added
support for the offload last year, the HW offload was added to the ixgbe
PF driver.
Since the related x540 VF device uses same setup as the PF for implementing
the offload, adding the feature to the ixgbevf seemed like a good idea.
In this case, the PF owns the device registers, so the VF simply packages
up the request information into a VF<->PF message and the PF does the
device configuration.
The following are changes since commit 050cdc6c9501abcd64720b8cc3e7941efee9547d:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 10GbE
Sebastian Basierski (2):
ixgbe: firmware recovery mode
ixgbevf: VF2VF TCP RSS
Shannon Nelson (11):
ixgbe: don't clear IPsec sa counters on HW clearing
ixgbe: reload IPsec IP table after sa tables
ixgbe: prep IPsec constants for later use
ixgbe: add VF IPsec management
ixgbe: add VF IPsec offload enable flag
ixgbe: add VF IPsec offload request message handling
ixgbevf: add defines for IPsec offload request
ixgbevf: add VF IPsec offload code
ixgbevf: enable VF IPsec offload operations
ixgbe: disallow IPsec Tx offload when in SR-IOV mode
ixgbe: fix the return value for unsupported VF offload
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 20 +-
.../net/ethernet/intel/ixgbe/ixgbe_common.c | 11 +
.../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 9 +
.../net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 282 +++++++-
.../net/ethernet/intel/ixgbe/ixgbe_ipsec.h | 13 +
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 41 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h | 5 +
.../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 17 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 +
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 15 +
drivers/net/ethernet/intel/ixgbevf/Makefile | 1 +
drivers/net/ethernet/intel/ixgbevf/defines.h | 10 +-
drivers/net/ethernet/intel/ixgbevf/ethtool.c | 2 +
drivers/net/ethernet/intel/ixgbevf/ipsec.c | 673 ++++++++++++++++++
.../{ixgbe/ixgbe_ipsec.h => ixgbevf/ipsec.h} | 40 +-
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 33 +
.../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 78 +-
drivers/net/ethernet/intel/ixgbevf/mbx.h | 5 +
drivers/net/ethernet/intel/ixgbevf/vf.c | 4 +
19 files changed, 1193 insertions(+), 70 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ixgbevf/ipsec.c
copy drivers/net/ethernet/intel/{ixgbe/ixgbe_ipsec.h => ixgbevf/ipsec.h} (59%)
--
2.17.1
^ permalink raw reply
* [net-next 02/13] ixgbevf: VF2VF TCP RSS
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem
Cc: Sebastian Basierski, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Sebastian Basierski <sebastianx.basierski@intel.com>
While VF2VF with RSS communication, RSS Type were wrongly recognized
and RSS hash was not calculated as it should be. Packets was
distributed on various queues by accident.
This commit fixes that behaviour and causes proper RSS Type recognition.
Signed-off-by: Sebastian Basierski <sebastianx.basierski@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index d86446d202d5..15deac07fd92 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -3849,6 +3849,10 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
skb_checksum_help(skb);
goto no_csum;
}
+
+ if (first->protocol == htons(ETH_P_IP))
+ type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+
/* update TX checksum flag */
first->tx_flags |= IXGBE_TX_FLAGS_CSUM;
vlan_macip_lens = skb_checksum_start_offset(skb) -
--
2.17.1
^ permalink raw reply related
* [net-next 01/13] ixgbe: firmware recovery mode
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem
Cc: Sebastian Basierski, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Sebastian Basierski <sebastianx.basierski@intel.com>
Add check for FW NVM recovery mode during driver initialization and
service task. If in recovery mode, log message and unregister device
Signed-off-by: Sebastian Basierski <sebastianx.basierski@intel.com>
Tested-by: Don Buchholz <donald.buchholz@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
.../net/ethernet/intel/ixgbe/ixgbe_common.c | 11 +++++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 41 +++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 15 +++++++
4 files changed, 71 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 0bd1294ba517..970f71d5da04 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -3484,6 +3484,17 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
}
+/**
+ * ixgbe_fw_recovery_mode - Check if in FW NVM recovery mode
+ * @hw: pointer to hardware structure
+ */
+bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw)
+{
+ if (hw->mac.ops.fw_recovery_mode)
+ return hw->mac.ops.fw_recovery_mode(hw);
+ return false;
+}
+
/**
* ixgbe_get_device_caps_generic - Get additional device capabilities
* @hw: pointer to hardware structure
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 9a23d33a47ed..604282f03d23 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7774,6 +7774,33 @@ static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
rtnl_unlock();
}
+/**
+ * ixgbe_check_fw_error - Check firmware for errors
+ * @adapter: the adapter private structure
+ *
+ * Check firmware errors in register FWSM
+ */
+static bool ixgbe_check_fw_error(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 fwsm;
+
+ /* read fwsm.ext_err_ind register and log errors */
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
+
+ if (fwsm & IXGBE_FWSM_EXT_ERR_IND_MASK ||
+ !(fwsm & IXGBE_FWSM_FW_VAL_BIT))
+ e_dev_warn("Warning firmware error detected FWSM: 0x%08X\n",
+ fwsm);
+
+ if (hw->mac.ops.fw_recovery_mode && hw->mac.ops.fw_recovery_mode(hw)) {
+ e_dev_err("Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
+ return true;
+ }
+
+ return false;
+}
+
/**
* ixgbe_service_task - manages and runs subtasks
* @work: pointer to work_struct containing our data
@@ -7792,6 +7819,15 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_service_event_complete(adapter);
return;
}
+ if (ixgbe_check_fw_error(adapter)) {
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ rtnl_lock();
+ unregister_netdev(adapter->netdev);
+ rtnl_unlock();
+ }
+ ixgbe_service_event_complete(adapter);
+ return;
+ }
if (adapter->flags2 & IXGBE_FLAG2_UDP_TUN_REREG_NEEDED) {
rtnl_lock();
adapter->flags2 &= ~IXGBE_FLAG2_UDP_TUN_REREG_NEEDED;
@@ -10716,6 +10752,11 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
netdev->features |= NETIF_F_LRO;
+ if (ixgbe_check_fw_error(adapter)) {
+ err = -EIO;
+ goto err_sw_init;
+ }
+
/* make sure the EEPROM is good */
if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
e_dev_err("The EEPROM Checksum Is Not Valid\n");
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 41bcbb337e83..84f2dba39e36 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -924,6 +924,9 @@ struct ixgbe_nvm_version {
/* Firmware Semaphore Register */
#define IXGBE_FWSM_MODE_MASK 0xE
#define IXGBE_FWSM_FW_MODE_PT 0x4
+#define IXGBE_FWSM_FW_NVM_RECOVERY_MODE BIT(5)
+#define IXGBE_FWSM_EXT_ERR_IND_MASK 0x01F80000
+#define IXGBE_FWSM_FW_VAL_BIT BIT(15)
/* ARC Subsystem registers */
#define IXGBE_HICR 0x15F00
@@ -3461,6 +3464,7 @@ struct ixgbe_mac_operations {
const char *);
s32 (*get_thermal_sensor_data)(struct ixgbe_hw *);
s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw);
+ bool (*fw_recovery_mode)(struct ixgbe_hw *hw);
void (*disable_rx)(struct ixgbe_hw *hw);
void (*enable_rx)(struct ixgbe_hw *hw);
void (*set_source_address_pruning)(struct ixgbe_hw *, bool,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
index a8148c7126e5..10dbaf4f6e80 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -1247,6 +1247,20 @@ static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
return 0;
}
+/**
+ * ixgbe_fw_recovery_mode - Check FW NVM recovery mode
+ * @hw: pointer t hardware structure
+ *
+ * Returns true if in FW NVM recovery mode.
+ */
+static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
+{
+ u32 fwsm;
+
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
+ return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
+}
+
/** ixgbe_disable_rx_x550 - Disable RX unit
*
* Enables the Rx DMA unit for x550
@@ -3816,6 +3830,7 @@ static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
.enable_rx_buff = &ixgbe_enable_rx_buff_generic, \
.get_thermal_sensor_data = NULL, \
.init_thermal_sensor_thresh = NULL, \
+ .fw_recovery_mode = &ixgbe_fw_recovery_mode_X550, \
.enable_rx = &ixgbe_enable_rx_generic, \
.disable_rx = &ixgbe_disable_rx_x550, \
--
2.17.1
^ permalink raw reply related
* [net-next 03/13] ixgbe: don't clear IPsec sa counters on HW clearing
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
The software SA record counters should not be cleared when clearing
the hardware tables. This causes the counters to be out of sync
after a driver reset.
Fixes: 63a67fe229ea ("ixgbe: add ipsec offload add and remove SA")
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index da4322e4daed..e515246d0bce 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -113,7 +113,6 @@ static void ixgbe_ipsec_set_rx_ip(struct ixgbe_hw *hw, u16 idx, __be32 addr[])
**/
static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
{
- struct ixgbe_ipsec *ipsec = adapter->ipsec;
struct ixgbe_hw *hw = &adapter->hw;
u32 buf[4] = {0, 0, 0, 0};
u16 idx;
@@ -132,9 +131,6 @@ static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
ixgbe_ipsec_set_tx_sa(hw, idx, buf, 0);
ixgbe_ipsec_set_rx_sa(hw, idx, 0, buf, 0, 0, 0);
}
-
- ipsec->num_rx_sa = 0;
- ipsec->num_tx_sa = 0;
}
/**
--
2.17.1
^ permalink raw reply related
* [net-next 05/13] ixgbe: prep IPsec constants for later use
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Pull out a couple of values from a function so they can be used
later elsewhere.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 434065109b8d..3afb1fe766cd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -5,6 +5,9 @@
#include <net/xfrm.h>
#include <crypto/aead.h>
+#define IXGBE_IPSEC_KEY_BITS 160
+static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
+
/**
* ixgbe_ipsec_set_tx_sa - set the Tx SA registers
* @hw: hw specific details
@@ -407,7 +410,6 @@ static int ixgbe_ipsec_parse_proto_keys(struct xfrm_state *xs,
struct net_device *dev = xs->xso.dev;
unsigned char *key_data;
char *alg_name = NULL;
- const char aes_gcm_name[] = "rfc4106(gcm(aes))";
int key_len;
if (!xs->aead) {
@@ -435,9 +437,9 @@ static int ixgbe_ipsec_parse_proto_keys(struct xfrm_state *xs,
* we don't need to do any byteswapping.
* 160 accounts for 16 byte key and 4 byte salt
*/
- if (key_len == 160) {
+ if (key_len == IXGBE_IPSEC_KEY_BITS) {
*mysalt = ((u32 *)key_data)[4];
- } else if (key_len != 128) {
+ } else if (key_len != (IXGBE_IPSEC_KEY_BITS - (sizeof(*mysalt) * 8))) {
netdev_err(dev, "IPsec hw offload only supports keys up to 128 bits with a 32 bit salt\n");
return -EINVAL;
} else {
--
2.17.1
^ permalink raw reply related
* [net-next 06/13] ixgbe: add VF IPsec management
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Add functions to translate VF IPsec offload add and delete requests
into something the existing code can work with.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
.../net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 256 +++++++++++++++++-
.../net/ethernet/intel/ixgbe/ixgbe_ipsec.h | 13 +
2 files changed, 260 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 3afb1fe766cd..80108e12ab86 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -8,6 +8,8 @@
#define IXGBE_IPSEC_KEY_BITS 160
static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
+static void ixgbe_ipsec_del_sa(struct xfrm_state *xs);
+
/**
* ixgbe_ipsec_set_tx_sa - set the Tx SA registers
* @hw: hw specific details
@@ -289,6 +291,13 @@ static void ixgbe_ipsec_start_engine(struct ixgbe_adapter *adapter)
/**
* ixgbe_ipsec_restore - restore the ipsec HW settings after a reset
* @adapter: board private structure
+ *
+ * Reload the HW tables from the SW tables after they've been bashed
+ * by a chip reset.
+ *
+ * Any VF entries are removed from the SW and HW tables since either
+ * (a) the VF also gets reset on PF reset and will ask again for the
+ * offloads, or (b) the VF has been removed by a change in the num_vfs.
**/
void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
{
@@ -306,16 +315,24 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
/* reload the Rx and Tx keys */
for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) {
- struct rx_sa *rsa = &ipsec->rx_tbl[i];
- struct tx_sa *tsa = &ipsec->tx_tbl[i];
-
- if (rsa->used)
- ixgbe_ipsec_set_rx_sa(hw, i, rsa->xs->id.spi,
- rsa->key, rsa->salt,
- rsa->mode, rsa->iptbl_ind);
+ struct rx_sa *r = &ipsec->rx_tbl[i];
+ struct tx_sa *t = &ipsec->tx_tbl[i];
+
+ if (r->used) {
+ if (r->mode & IXGBE_RXTXMOD_VF)
+ ixgbe_ipsec_del_sa(r->xs);
+ else
+ ixgbe_ipsec_set_rx_sa(hw, i, r->xs->id.spi,
+ r->key, r->salt,
+ r->mode, r->iptbl_ind);
+ }
- if (tsa->used)
- ixgbe_ipsec_set_tx_sa(hw, i, tsa->key, tsa->salt);
+ if (t->used) {
+ if (t->mode & IXGBE_RXTXMOD_VF)
+ ixgbe_ipsec_del_sa(t->xs);
+ else
+ ixgbe_ipsec_set_tx_sa(hw, i, t->key, t->salt);
+ }
}
/* reload the IP addrs */
@@ -381,6 +398,8 @@ static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
rcu_read_lock();
hash_for_each_possible_rcu(ipsec->rx_sa_list, rsa, hlist,
(__force u32)spi) {
+ if (rsa->mode & IXGBE_RXTXMOD_VF)
+ continue;
if (spi == rsa->xs->id.spi &&
((ip4 && *daddr == rsa->xs->id.daddr.a4) ||
(!ip4 && !memcmp(daddr, &rsa->xs->id.daddr.a6,
@@ -808,6 +827,225 @@ static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
};
+/**
+ * ixgbe_ipsec_vf_clear - clear the tables of data for a VF
+ * @adapter: board private structure
+ * @vf: VF id to be removed
+ **/
+void ixgbe_ipsec_vf_clear(struct ixgbe_adapter *adapter, u32 vf)
+{
+ struct ixgbe_ipsec *ipsec = adapter->ipsec;
+ int i;
+
+ /* search rx sa table */
+ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT && ipsec->num_rx_sa; i++) {
+ if (!ipsec->rx_tbl[i].used)
+ continue;
+ if (ipsec->rx_tbl[i].mode & IXGBE_RXTXMOD_VF &&
+ ipsec->rx_tbl[i].vf == vf)
+ ixgbe_ipsec_del_sa(ipsec->rx_tbl[i].xs);
+ }
+
+ /* search tx sa table */
+ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT && ipsec->num_tx_sa; i++) {
+ if (!ipsec->tx_tbl[i].used)
+ continue;
+ if (ipsec->tx_tbl[i].mode & IXGBE_RXTXMOD_VF &&
+ ipsec->tx_tbl[i].vf == vf)
+ ixgbe_ipsec_del_sa(ipsec->tx_tbl[i].xs);
+ }
+}
+
+/**
+ * ixgbe_ipsec_vf_add_sa - translate VF request to SA add
+ * @adapter: board private structure
+ * @msgbuf: The message buffer
+ * @vf: the VF index
+ *
+ * Make up a new xs and algorithm info from the data sent by the VF.
+ * We only need to sketch in just enough to set up the HW offload.
+ * Put the resulting offload_handle into the return message to the VF.
+ *
+ * Returns 0 or error value
+ **/
+int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+{
+ struct ixgbe_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_algo_desc *algo;
+ struct sa_mbx_msg *sam;
+ struct xfrm_state *xs;
+ size_t aead_len;
+ u16 sa_idx;
+ u32 pfsa;
+ int err;
+
+ sam = (struct sa_mbx_msg *)(&msgbuf[1]);
+ if (!adapter->vfinfo[vf].trusted) {
+ e_warn(drv, "VF %d attempted to add an IPsec SA\n", vf);
+ err = -EACCES;
+ goto err_out;
+ }
+
+ /* Tx IPsec offload doesn't seem to work on this
+ * device, so block these requests for now.
+ */
+ if (!(sam->flags & XFRM_OFFLOAD_INBOUND)) {
+ err = -ENXIO;
+ goto err_out;
+ }
+
+ xs = kzalloc(sizeof(*xs), GFP_KERNEL);
+ if (unlikely(!xs)) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ xs->xso.flags = sam->flags;
+ xs->id.spi = sam->spi;
+ xs->id.proto = sam->proto;
+ xs->props.family = sam->family;
+ if (xs->props.family == AF_INET6)
+ memcpy(&xs->id.daddr.a6, sam->addr, sizeof(xs->id.daddr.a6));
+ else
+ memcpy(&xs->id.daddr.a4, sam->addr, sizeof(xs->id.daddr.a4));
+ xs->xso.dev = adapter->netdev;
+
+ algo = xfrm_aead_get_byname(aes_gcm_name, IXGBE_IPSEC_AUTH_BITS, 1);
+ if (unlikely(!algo)) {
+ err = -ENOENT;
+ goto err_xs;
+ }
+
+ aead_len = sizeof(*xs->aead) + IXGBE_IPSEC_KEY_BITS / 8;
+ xs->aead = kzalloc(aead_len, GFP_KERNEL);
+ if (unlikely(!xs->aead)) {
+ err = -ENOMEM;
+ goto err_xs;
+ }
+
+ xs->props.ealgo = algo->desc.sadb_alg_id;
+ xs->geniv = algo->uinfo.aead.geniv;
+ xs->aead->alg_icv_len = IXGBE_IPSEC_AUTH_BITS;
+ xs->aead->alg_key_len = IXGBE_IPSEC_KEY_BITS;
+ memcpy(xs->aead->alg_key, sam->key, sizeof(sam->key));
+ memcpy(xs->aead->alg_name, aes_gcm_name, sizeof(aes_gcm_name));
+
+ /* set up the HW offload */
+ err = ixgbe_ipsec_add_sa(xs);
+ if (err)
+ goto err_aead;
+
+ pfsa = xs->xso.offload_handle;
+ if (pfsa < IXGBE_IPSEC_BASE_TX_INDEX) {
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_RX_INDEX;
+ ipsec->rx_tbl[sa_idx].vf = vf;
+ ipsec->rx_tbl[sa_idx].mode |= IXGBE_RXTXMOD_VF;
+ } else {
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_TX_INDEX;
+ ipsec->tx_tbl[sa_idx].vf = vf;
+ ipsec->tx_tbl[sa_idx].mode |= IXGBE_RXTXMOD_VF;
+ }
+
+ msgbuf[1] = xs->xso.offload_handle;
+
+ return 0;
+
+err_aead:
+ memset(xs->aead, 0, sizeof(*xs->aead));
+ kfree(xs->aead);
+err_xs:
+ memset(xs, 0, sizeof(*xs));
+ kfree(xs);
+err_out:
+ msgbuf[1] = err;
+ return err;
+}
+
+/**
+ * ixgbe_ipsec_vf_del_sa - translate VF request to SA delete
+ * @adapter: board private structure
+ * @msgbuf: The message buffer
+ * @vf: the VF index
+ *
+ * Given the offload_handle sent by the VF, look for the related SA table
+ * entry and use its xs field to call for a delete of the SA.
+ *
+ * Note: We silently ignore requests to delete entries that are already
+ * set to unused because when a VF is set to "DOWN", the PF first
+ * gets a reset and clears all the VF's entries; then the VF's
+ * XFRM stack sends individual deletes for each entry, which the
+ * reset already removed. In the future it might be good to try to
+ * optimize this so not so many unnecessary delete messages are sent.
+ *
+ * Returns 0 or error value
+ **/
+int ixgbe_ipsec_vf_del_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+{
+ struct ixgbe_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_state *xs;
+ u32 pfsa = msgbuf[1];
+ u16 sa_idx;
+
+ if (!adapter->vfinfo[vf].trusted) {
+ e_err(drv, "vf %d attempted to delete an SA\n", vf);
+ return -EPERM;
+ }
+
+ if (pfsa < IXGBE_IPSEC_BASE_TX_INDEX) {
+ struct rx_sa *rsa;
+
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_RX_INDEX;
+ if (sa_idx >= IXGBE_IPSEC_MAX_SA_COUNT) {
+ e_err(drv, "vf %d SA index %d out of range\n",
+ vf, sa_idx);
+ return -EINVAL;
+ }
+
+ rsa = &ipsec->rx_tbl[sa_idx];
+
+ if (!rsa->used)
+ return 0;
+
+ if (!(rsa->mode & IXGBE_RXTXMOD_VF) ||
+ rsa->vf != vf) {
+ e_err(drv, "vf %d bad Rx SA index %d\n", vf, sa_idx);
+ return -ENOENT;
+ }
+
+ xs = ipsec->rx_tbl[sa_idx].xs;
+ } else {
+ struct tx_sa *tsa;
+
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_TX_INDEX;
+ if (sa_idx >= IXGBE_IPSEC_MAX_SA_COUNT) {
+ e_err(drv, "vf %d SA index %d out of range\n",
+ vf, sa_idx);
+ return -EINVAL;
+ }
+
+ tsa = &ipsec->tx_tbl[sa_idx];
+
+ if (!tsa->used)
+ return 0;
+
+ if (!(tsa->mode & IXGBE_RXTXMOD_VF) ||
+ tsa->vf != vf) {
+ e_err(drv, "vf %d bad Tx SA index %d\n", vf, sa_idx);
+ return -ENOENT;
+ }
+
+ xs = ipsec->tx_tbl[sa_idx].xs;
+ }
+
+ ixgbe_ipsec_del_sa(xs);
+
+ /* remove the xs that was made-up in the add request */
+ memset(xs, 0, sizeof(*xs));
+ kfree(xs);
+
+ return 0;
+}
+
/**
* ixgbe_ipsec_tx - setup Tx flags for ipsec offload
* @tx_ring: outgoing context
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h
index 9ef7faadda69..d2b64ff8eb4e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h
@@ -26,6 +26,7 @@ enum ixgbe_ipsec_tbl_sel {
#define IXGBE_RXMOD_PROTO_ESP 0x00000004
#define IXGBE_RXMOD_DECRYPT 0x00000008
#define IXGBE_RXMOD_IPV6 0x00000010
+#define IXGBE_RXTXMOD_VF 0x00000020
struct rx_sa {
struct hlist_node hlist;
@@ -37,6 +38,7 @@ struct rx_sa {
u8 iptbl_ind;
bool used;
bool decrypt;
+ u32 vf;
};
struct rx_ip_sa {
@@ -49,8 +51,10 @@ struct tx_sa {
struct xfrm_state *xs;
u32 key[4];
u32 salt;
+ u32 mode;
bool encrypt;
bool used;
+ u32 vf;
};
struct ixgbe_ipsec_tx_data {
@@ -67,4 +71,13 @@ struct ixgbe_ipsec {
struct tx_sa *tx_tbl;
DECLARE_HASHTABLE(rx_sa_list, 10);
};
+
+struct sa_mbx_msg {
+ __be32 spi;
+ u8 flags;
+ u8 proto;
+ u16 family;
+ __be32 addr[4];
+ u32 key[5];
+};
#endif /* _IXGBE_IPSEC_H_ */
--
2.17.1
^ permalink raw reply related
* [net-next 03/13] ixgbe: don't clear IPsec sa counters on HW clearing
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
The software SA record counters should not be cleared when clearing
the hardware tables. This causes the counters to be out of sync
after a driver reset.
Fixes: 63a67fe229ea ("ixgbe: add ipsec offload add and remove SA")
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index da4322e4daed..e515246d0bce 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -113,7 +113,6 @@ static void ixgbe_ipsec_set_rx_ip(struct ixgbe_hw *hw, u16 idx, __be32 addr[])
**/
static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
{
- struct ixgbe_ipsec *ipsec = adapter->ipsec;
struct ixgbe_hw *hw = &adapter->hw;
u32 buf[4] = {0, 0, 0, 0};
u16 idx;
@@ -132,9 +131,6 @@ static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
ixgbe_ipsec_set_tx_sa(hw, idx, buf, 0);
ixgbe_ipsec_set_rx_sa(hw, idx, 0, buf, 0, 0, 0);
}
-
- ipsec->num_rx_sa = 0;
- ipsec->num_tx_sa = 0;
}
/**
--
2.17.1
^ permalink raw reply related
* [net-next 11/13] ixgbevf: enable VF IPsec offload operations
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Add the IPsec initialization into the driver startup and
add the Rx and Tx processing hooks.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbevf/defines.h | 2 +-
drivers/net/ethernet/intel/ixgbevf/ethtool.c | 2 +
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 25 +++++++
.../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 74 ++++++++++++++-----
drivers/net/ethernet/intel/ixgbevf/vf.c | 4 +
5 files changed, 86 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index dd9cd4541d7a..6bace746eaac 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -234,7 +234,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;
};
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index 631c91046f39..5399787e07af 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -55,6 +55,8 @@ static struct ixgbe_stats ixgbevf_gstrings_stats[] = {
IXGBEVF_STAT("alloc_rx_page", alloc_rx_page),
IXGBEVF_STAT("alloc_rx_page_failed", alloc_rx_page_failed),
IXGBEVF_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed),
+ IXGBEVF_STAT("tx_ipsec", tx_ipsec),
+ IXGBEVF_STAT("rx_ipsec", rx_ipsec),
};
#define IXGBEVF_QUEUE_STATS_LEN ( \
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 172637e2f2e6..e399e1c0c54a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -459,6 +459,31 @@ int ethtool_ioctl(struct ifreq *ifr);
extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector);
+#ifdef CONFIG_XFRM_OFFLOAD
+void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter);
+void ixgbevf_stop_ipsec_offload(struct ixgbevf_adapter *adapter);
+void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter);
+void ixgbevf_ipsec_rx(struct ixgbevf_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb);
+int ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring,
+ struct ixgbevf_tx_buffer *first,
+ struct ixgbevf_ipsec_tx_data *itd);
+#else
+static inline void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter)
+{ }
+static inline void ixgbevf_stop_ipsec_offload(struct ixgbevf_adapter *adapter)
+{ }
+static inline void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter) { }
+static inline void ixgbevf_ipsec_rx(struct ixgbevf_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb) { }
+static inline int ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring,
+ struct ixgbevf_tx_buffer *first,
+ struct ixgbevf_ipsec_tx_data *itd)
+{ return 0; }
+#endif /* CONFIG_XFRM_OFFLOAD */
+
void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter);
void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 15deac07fd92..17e23f609d74 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -40,7 +40,7 @@ static const char ixgbevf_driver_string[] =
#define DRV_VERSION "4.1.0-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
- "Copyright (c) 2009 - 2015 Intel Corporation.";
+ "Copyright (c) 2009 - 2018 Intel Corporation.";
static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
[board_82599_vf] = &ixgbevf_82599_vf_info,
@@ -268,7 +268,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
struct ixgbevf_adapter *adapter = q_vector->adapter;
struct ixgbevf_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 = tx_ring->count / 2;
unsigned int i = tx_ring->next_to_clean;
@@ -299,6 +299,8 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_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))
@@ -361,6 +363,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_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) && ixgbevf_check_tx_hang(tx_ring)) {
struct ixgbe_hw *hw = &adapter->hw;
@@ -516,6 +519,9 @@ static void ixgbevf_process_skb_fields(struct ixgbevf_ring *rx_ring,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
}
+ if (ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_STAT_SECP))
+ ixgbevf_ipsec_rx(rx_ring, rx_desc, skb);
+
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
}
@@ -1012,7 +1018,7 @@ static int ixgbevf_xmit_xdp_ring(struct ixgbevf_ring *ring,
context_desc = IXGBEVF_TX_CTXTDESC(ring, 0);
context_desc->vlan_macip_lens =
cpu_to_le32(ETH_HLEN << IXGBE_ADVTXD_MACLEN_SHIFT);
- context_desc->seqnum_seed = 0;
+ context_desc->fceof_saidx = 0;
context_desc->type_tucmd_mlhl =
cpu_to_le32(IXGBE_TXD_CMD_DEXT |
IXGBE_ADVTXD_DTYP_CTXT);
@@ -2200,6 +2206,7 @@ static void ixgbevf_configure(struct ixgbevf_adapter *adapter)
ixgbevf_set_rx_mode(adapter->netdev);
ixgbevf_restore_vlan(adapter);
+ ixgbevf_ipsec_restore(adapter);
ixgbevf_configure_tx(adapter);
ixgbevf_configure_rx(adapter);
@@ -2246,7 +2253,8 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- int api[] = { ixgbe_mbox_api_13,
+ int api[] = { ixgbe_mbox_api_14,
+ ixgbe_mbox_api_13,
ixgbe_mbox_api_12,
ixgbe_mbox_api_11,
ixgbe_mbox_api_10,
@@ -2605,6 +2613,7 @@ static void ixgbevf_set_num_queues(struct ixgbevf_adapter *adapter)
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
if (adapter->xdp_prog &&
hw->mac.max_tx_queues == rss)
rss = rss > 3 ? 2 : 1;
@@ -3700,8 +3709,8 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter)
}
static void ixgbevf_tx_ctxtdesc(struct ixgbevf_ring *tx_ring,
- u32 vlan_macip_lens, u32 type_tucmd,
- u32 mss_l4len_idx)
+ u32 vlan_macip_lens, 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;
@@ -3715,14 +3724,15 @@ static void ixgbevf_tx_ctxtdesc(struct ixgbevf_ring *tx_ring,
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 = 0;
+ 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);
}
static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
struct ixgbevf_tx_buffer *first,
- u8 *hdr_len)
+ u8 *hdr_len,
+ struct ixgbevf_ipsec_tx_data *itd)
{
u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
struct sk_buff *skb = first->skb;
@@ -3736,6 +3746,7 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
unsigned char *hdr;
} l4;
u32 paylen, l4_offset;
+ u32 fceof_saidx = 0;
int err;
if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -3761,13 +3772,15 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
if (ip.v4->version == 4) {
unsigned char *csum_start = skb_checksum_start(skb);
unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
+ int len = csum_start - trans_start;
/* IP header will have to cancel out any data that
- * is not a part of the outer IP header
+ * is not a part of the outer IP header, so set to
+ * a reverse csum if needed, else init check to 0.
*/
- ip.v4->check = csum_fold(csum_partial(trans_start,
- csum_start - trans_start,
- 0));
+ ip.v4->check = (skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) ?
+ csum_fold(csum_partial(trans_start,
+ len, 0)) : 0;
type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
ip.v4->tot_len = 0;
@@ -3799,13 +3812,16 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
mss_l4len_idx |= (1u << IXGBE_ADVTXD_IDX_SHIFT);
+ fceof_saidx |= itd->pfsa;
+ type_tucmd |= itd->flags | itd->trailer_len;
+
/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
vlan_macip_lens = l4.hdr - ip.hdr;
vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT;
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
- ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens,
- type_tucmd, mss_l4len_idx);
+ ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, fceof_saidx, type_tucmd,
+ mss_l4len_idx);
return 1;
}
@@ -3820,10 +3836,12 @@ static inline bool ixgbevf_ipv6_csum_is_sctp(struct sk_buff *skb)
}
static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
- struct ixgbevf_tx_buffer *first)
+ struct ixgbevf_tx_buffer *first,
+ struct ixgbevf_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)
@@ -3862,7 +3880,11 @@ static void ixgbevf_tx_csum(struct ixgbevf_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;
- ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, 0);
+ fceof_saidx |= itd->pfsa;
+ type_tucmd |= itd->flags | itd->trailer_len;
+
+ ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens,
+ fceof_saidx, type_tucmd, 0);
}
static __le32 ixgbevf_tx_cmd_type(u32 tx_flags)
@@ -3896,8 +3918,12 @@ static void ixgbevf_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc,
if (tx_flags & IXGBE_TX_FLAGS_IPV4)
olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IXSM);
- /* use index 1 context for TSO/FSO/FCOE */
- if (tx_flags & IXGBE_TX_FLAGS_TSO)
+ /* enable IPsec */
+ if (tx_flags & IXGBE_TX_FLAGS_IPSEC)
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IPSEC);
+
+ /* use index 1 context for TSO/FSO/FCOE/IPSEC */
+ if (tx_flags & (IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_IPSEC))
olinfo_status |= cpu_to_le32(1u << IXGBE_ADVTXD_IDX_SHIFT);
/* Check Context must be set if Tx switch is enabled, which it
@@ -4079,6 +4105,7 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb,
int tso;
u32 tx_flags = 0;
u16 count = TXD_USE_COUNT(skb_headlen(skb));
+ struct ixgbevf_ipsec_tx_data ipsec_tx = { 0 };
#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
unsigned short f;
#endif
@@ -4123,11 +4150,15 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb,
first->tx_flags = tx_flags;
first->protocol = vlan_get_protocol(skb);
- tso = ixgbevf_tso(tx_ring, first, &hdr_len);
+#ifdef CONFIG_XFRM_OFFLOAD
+ if (skb->sp && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
+ goto out_drop;
+#endif
+ tso = ixgbevf_tso(tx_ring, first, &hdr_len, &ipsec_tx);
if (tso < 0)
goto out_drop;
else if (!tso)
- ixgbevf_tx_csum(tx_ring, first);
+ ixgbevf_tx_csum(tx_ring, first, &ipsec_tx);
ixgbevf_tx_map(tx_ring, first, hdr_len);
@@ -4638,6 +4669,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
(ETH_HLEN + ETH_FCS_LEN);
break;
@@ -4673,6 +4705,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, netdev);
netif_carrier_off(netdev);
+ ixgbevf_init_ipsec_offload(adapter);
ixgbevf_init_last_counter_stats(adapter);
@@ -4739,6 +4772,7 @@ static void ixgbevf_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
+ ixgbevf_stop_ipsec_offload(adapter);
ixgbevf_clear_interrupt_scheme(adapter);
ixgbevf_reset_interrupt_capability(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index bf0577e819e1..cd3b81300cc7 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -309,6 +309,7 @@ int ixgbevf_get_reta_locked(struct ixgbe_hw *hw, u32 *reta, int num_rx_queues)
* is not supported for this device type.
*/
switch (hw->api_version) {
+ case ixgbe_mbox_api_14:
case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12:
if (hw->mac.type < ixgbe_mac_X550_vf)
@@ -376,6 +377,7 @@ int ixgbevf_get_rss_key_locked(struct ixgbe_hw *hw, u8 *rss_key)
* or if the operation is not supported for this device type.
*/
switch (hw->api_version) {
+ case ixgbe_mbox_api_14:
case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12:
if (hw->mac.type < ixgbe_mac_X550_vf)
@@ -540,6 +542,7 @@ static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
return -EOPNOTSUPP;
/* Fall threw */
+ case ixgbe_mbox_api_14:
case ixgbe_mbox_api_13:
break;
default:
@@ -890,6 +893,7 @@ int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
break;
default:
return 0;
--
2.17.1
^ permalink raw reply related
* [net-next 10/13] ixgbevf: add VF IPsec offload code
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Add the IPsec offload support code. This is based off of the similar
code in ixgbe, but instead of writing the SA registers, the VF asks
the PF to setup the offload by sending the offload information to the
PF via the standard mailbox.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbevf/Makefile | 1 +
drivers/net/ethernet/intel/ixgbevf/ipsec.c | 673 +++++++++++++++++++
drivers/net/ethernet/intel/ixgbevf/ipsec.h | 66 ++
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 8 +
4 files changed, 748 insertions(+)
create mode 100644 drivers/net/ethernet/intel/ixgbevf/ipsec.c
create mode 100644 drivers/net/ethernet/intel/ixgbevf/ipsec.h
diff --git a/drivers/net/ethernet/intel/ixgbevf/Makefile b/drivers/net/ethernet/intel/ixgbevf/Makefile
index aba1e6a37a6a..297d0f0858b5 100644
--- a/drivers/net/ethernet/intel/ixgbevf/Makefile
+++ b/drivers/net/ethernet/intel/ixgbevf/Makefile
@@ -10,4 +10,5 @@ ixgbevf-objs := vf.o \
mbx.o \
ethtool.o \
ixgbevf_main.o
+ixgbevf-$(CONFIG_XFRM_OFFLOAD) += ipsec.o
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
new file mode 100644
index 000000000000..997cea675a37
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2018 Oracle and/or its affiliates. All rights reserved. */
+
+#include "ixgbevf.h"
+#include <net/xfrm.h>
+#include <crypto/aead.h>
+
+#define IXGBE_IPSEC_KEY_BITS 160
+static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
+
+/**
+ * ixgbevf_ipsec_set_pf_sa - ask the PF to set up an SA
+ * @adapter: board private structure
+ * @xs: xfrm info to be sent to the PF
+ *
+ * Returns: positive offload handle from the PF, or negative error code
+ **/
+static int ixgbevf_ipsec_set_pf_sa(struct ixgbevf_adapter *adapter,
+ struct xfrm_state *xs)
+{
+ u32 msgbuf[IXGBE_VFMAILBOX_SIZE] = { 0 };
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct sa_mbx_msg *sam;
+ u16 msglen;
+ int ret;
+
+ /* send the important bits to the PF */
+ sam = (struct sa_mbx_msg *)(&msgbuf[1]);
+ sam->flags = xs->xso.flags;
+ sam->spi = xs->id.spi;
+ sam->proto = xs->id.proto;
+ sam->family = xs->props.family;
+
+ if (xs->props.family == AF_INET6)
+ memcpy(sam->addr, &xs->id.daddr.a6, sizeof(xs->id.daddr.a6));
+ else
+ memcpy(sam->addr, &xs->id.daddr.a4, sizeof(xs->id.daddr.a4));
+ memcpy(sam->key, xs->aead->alg_key, sizeof(sam->key));
+
+ msgbuf[0] = IXGBE_VF_IPSEC_ADD;
+ msglen = sizeof(*sam) + sizeof(msgbuf[0]);
+
+ spin_lock_bh(&adapter->mbx_lock);
+
+ ret = hw->mbx.ops.write_posted(hw, msgbuf, msglen);
+ if (ret)
+ goto out;
+
+ msglen = sizeof(msgbuf[0]) * 2;
+ ret = hw->mbx.ops.read_posted(hw, msgbuf, msglen);
+ if (ret)
+ goto out;
+
+ ret = (int)msgbuf[1];
+ if (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK && ret >= 0)
+ ret = -1;
+
+out:
+ spin_unlock_bh(&adapter->mbx_lock);
+
+ return ret;
+}
+
+/**
+ * ixgbevf_ipsec_del_pf_sa - ask the PF to delete an SA
+ * @adapter: board private structure
+ * @pfsa: sa index returned from PF when created, -1 for all
+ *
+ * Returns: 0 on success, or negative error code
+ **/
+static int ixgbevf_ipsec_del_pf_sa(struct ixgbevf_adapter *adapter, int pfsa)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 msgbuf[2];
+ int err;
+
+ memset(msgbuf, 0, sizeof(msgbuf));
+ msgbuf[0] = IXGBE_VF_IPSEC_DEL;
+ msgbuf[1] = (u32)pfsa;
+
+ spin_lock_bh(&adapter->mbx_lock);
+
+ err = hw->mbx.ops.write_posted(hw, msgbuf, sizeof(msgbuf));
+ if (err)
+ goto out;
+
+ err = hw->mbx.ops.read_posted(hw, msgbuf, sizeof(msgbuf));
+ if (err)
+ goto out;
+
+out:
+ spin_unlock_bh(&adapter->mbx_lock);
+ return err;
+}
+
+/**
+ * ixgbevf_ipsec_restore - restore the IPsec HW settings after a reset
+ * @adapter: board private structure
+ *
+ * Reload the HW tables from the SW tables after they've been bashed
+ * by a chip reset. While we're here, make sure any stale VF data is
+ * removed, since we go through reset when num_vfs changes.
+ **/
+void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter)
+{
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+ struct net_device *netdev = adapter->netdev;
+ int i;
+
+ if (!(adapter->netdev->features & NETIF_F_HW_ESP))
+ return;
+
+ /* reload the Rx and Tx keys */
+ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) {
+ struct rx_sa *r = &ipsec->rx_tbl[i];
+ struct tx_sa *t = &ipsec->tx_tbl[i];
+ int ret;
+
+ if (r->used) {
+ ret = ixgbevf_ipsec_set_pf_sa(adapter, r->xs);
+ if (ret < 0)
+ netdev_err(netdev, "reload rx_tbl[%d] failed = %d\n",
+ i, ret);
+ }
+
+ if (t->used) {
+ ret = ixgbevf_ipsec_set_pf_sa(adapter, t->xs);
+ if (ret < 0)
+ netdev_err(netdev, "reload tx_tbl[%d] failed = %d\n",
+ i, ret);
+ }
+ }
+}
+
+/**
+ * ixgbevf_ipsec_find_empty_idx - find the first unused security parameter index
+ * @ipsec: pointer to IPsec struct
+ * @rxtable: true if we need to look in the Rx table
+ *
+ * Returns the first unused index in either the Rx or Tx SA table
+ **/
+static
+int ixgbevf_ipsec_find_empty_idx(struct ixgbevf_ipsec *ipsec, bool rxtable)
+{
+ u32 i;
+
+ if (rxtable) {
+ if (ipsec->num_rx_sa == IXGBE_IPSEC_MAX_SA_COUNT)
+ return -ENOSPC;
+
+ /* search rx sa table */
+ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) {
+ if (!ipsec->rx_tbl[i].used)
+ return i;
+ }
+ } else {
+ if (ipsec->num_tx_sa == IXGBE_IPSEC_MAX_SA_COUNT)
+ return -ENOSPC;
+
+ /* search tx sa table */
+ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) {
+ if (!ipsec->tx_tbl[i].used)
+ return i;
+ }
+ }
+
+ return -ENOSPC;
+}
+
+/**
+ * ixgbevf_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
+ * @ip4: true if using an IPv4 address
+ *
+ * Returns a pointer to the matching SA state information
+ **/
+static
+struct xfrm_state *ixgbevf_ipsec_find_rx_state(struct ixgbevf_ipsec *ipsec,
+ __be32 *daddr, u8 proto,
+ __be32 spi, bool ip4)
+{
+ struct xfrm_state *ret = NULL;
+ struct rx_sa *rsa;
+
+ rcu_read_lock();
+ hash_for_each_possible_rcu(ipsec->rx_sa_list, rsa, hlist,
+ (__force u32)spi) {
+ if (spi == rsa->xs->id.spi &&
+ ((ip4 && *daddr == rsa->xs->id.daddr.a4) ||
+ (!ip4 && !memcmp(daddr, &rsa->xs->id.daddr.a6,
+ sizeof(rsa->xs->id.daddr.a6)))) &&
+ proto == rsa->xs->id.proto) {
+ ret = rsa->xs;
+ xfrm_state_hold(ret);
+ break;
+ }
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
+/**
+ * ixgbevf_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
+ * @mysalt: pointer to salt value to populate
+ *
+ * This copies the protocol keys and salt to our own data tables. The
+ * 82599 family only supports the one algorithm.
+ **/
+static int ixgbevf_ipsec_parse_proto_keys(struct xfrm_state *xs,
+ u32 *mykey, u32 *mysalt)
+{
+ struct net_device *dev = xs->xso.dev;
+ unsigned char *key_data;
+ char *alg_name = NULL;
+ int key_len;
+
+ if (!xs->aead) {
+ netdev_err(dev, "Unsupported IPsec algorithm\n");
+ return -EINVAL;
+ }
+
+ if (xs->aead->alg_icv_len != IXGBE_IPSEC_AUTH_BITS) {
+ netdev_err(dev, "IPsec offload requires %d bit authentication\n",
+ IXGBE_IPSEC_AUTH_BITS);
+ return -EINVAL;
+ }
+
+ key_data = &xs->aead->alg_key[0];
+ key_len = xs->aead->alg_key_len;
+ alg_name = xs->aead->alg_name;
+
+ if (strcmp(alg_name, aes_gcm_name)) {
+ netdev_err(dev, "Unsupported IPsec algorithm - please use %s\n",
+ aes_gcm_name);
+ return -EINVAL;
+ }
+
+ /* The key bytes come down in a big endian array of bytes, so
+ * we don't need to do any byte swapping.
+ * 160 accounts for 16 byte key and 4 byte salt
+ */
+ if (key_len > IXGBE_IPSEC_KEY_BITS) {
+ *mysalt = ((u32 *)key_data)[4];
+ } else if (key_len == IXGBE_IPSEC_KEY_BITS) {
+ *mysalt = 0;
+ } else {
+ netdev_err(dev, "IPsec hw offload only supports keys up to 128 bits with a 32 bit salt\n");
+ return -EINVAL;
+ }
+ memcpy(mykey, key_data, 16);
+
+ return 0;
+}
+
+/**
+ * ixgbevf_ipsec_add_sa - program device with a security association
+ * @xs: pointer to transformer state struct
+ **/
+static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)
+{
+ struct net_device *dev = xs->xso.dev;
+ struct ixgbevf_adapter *adapter = netdev_priv(dev);
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+ u16 sa_idx;
+ int ret;
+
+ if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
+ netdev_err(dev, "Unsupported protocol 0x%04x for IPsec offload\n",
+ xs->id.proto);
+ return -EINVAL;
+ }
+
+ if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
+ struct rx_sa rsa;
+
+ if (xs->calg) {
+ netdev_err(dev, "Compression offload not supported\n");
+ return -EINVAL;
+ }
+
+ /* find the first unused index */
+ ret = ixgbevf_ipsec_find_empty_idx(ipsec, true);
+ if (ret < 0) {
+ netdev_err(dev, "No space for SA in Rx table!\n");
+ return ret;
+ }
+ sa_idx = (u16)ret;
+
+ memset(&rsa, 0, sizeof(rsa));
+ rsa.used = true;
+ rsa.xs = xs;
+
+ if (rsa.xs->id.proto & IPPROTO_ESP)
+ rsa.decrypt = xs->ealg || xs->aead;
+
+ /* get the key and salt */
+ ret = ixgbevf_ipsec_parse_proto_keys(xs, rsa.key, &rsa.salt);
+ if (ret) {
+ netdev_err(dev, "Failed to get key data for Rx SA table\n");
+ return ret;
+ }
+
+ /* get ip for rx sa table */
+ if (xs->props.family == AF_INET6)
+ memcpy(rsa.ipaddr, &xs->id.daddr.a6, 16);
+ else
+ memcpy(&rsa.ipaddr[3], &xs->id.daddr.a4, 4);
+
+ rsa.mode = IXGBE_RXMOD_VALID;
+ if (rsa.xs->id.proto & IPPROTO_ESP)
+ rsa.mode |= IXGBE_RXMOD_PROTO_ESP;
+ if (rsa.decrypt)
+ rsa.mode |= IXGBE_RXMOD_DECRYPT;
+ if (rsa.xs->props.family == AF_INET6)
+ rsa.mode |= IXGBE_RXMOD_IPV6;
+
+ ret = ixgbevf_ipsec_set_pf_sa(adapter, xs);
+ if (ret < 0)
+ return ret;
+ rsa.pfsa = ret;
+
+ /* the preparations worked, so save the info */
+ memcpy(&ipsec->rx_tbl[sa_idx], &rsa, sizeof(rsa));
+
+ xs->xso.offload_handle = sa_idx + IXGBE_IPSEC_BASE_RX_INDEX;
+
+ ipsec->num_rx_sa++;
+
+ /* hash the new entry for faster search in Rx path */
+ hash_add_rcu(ipsec->rx_sa_list, &ipsec->rx_tbl[sa_idx].hlist,
+ (__force u32)rsa.xs->id.spi);
+ } else {
+ struct tx_sa tsa;
+
+ /* find the first unused index */
+ ret = ixgbevf_ipsec_find_empty_idx(ipsec, false);
+ if (ret < 0) {
+ netdev_err(dev, "No space for SA in Tx table\n");
+ return ret;
+ }
+ sa_idx = (u16)ret;
+
+ memset(&tsa, 0, sizeof(tsa));
+ tsa.used = true;
+ tsa.xs = xs;
+
+ if (xs->id.proto & IPPROTO_ESP)
+ tsa.encrypt = xs->ealg || xs->aead;
+
+ ret = ixgbevf_ipsec_parse_proto_keys(xs, tsa.key, &tsa.salt);
+ if (ret) {
+ netdev_err(dev, "Failed to get key data for Tx SA table\n");
+ memset(&tsa, 0, sizeof(tsa));
+ return ret;
+ }
+
+ ret = ixgbevf_ipsec_set_pf_sa(adapter, xs);
+ if (ret < 0)
+ return ret;
+ tsa.pfsa = ret;
+
+ /* the preparations worked, so save the info */
+ memcpy(&ipsec->tx_tbl[sa_idx], &tsa, sizeof(tsa));
+
+ xs->xso.offload_handle = sa_idx + IXGBE_IPSEC_BASE_TX_INDEX;
+
+ ipsec->num_tx_sa++;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbevf_ipsec_del_sa - clear out this specific SA
+ * @xs: pointer to transformer state struct
+ **/
+static void ixgbevf_ipsec_del_sa(struct xfrm_state *xs)
+{
+ struct net_device *dev = xs->xso.dev;
+ struct ixgbevf_adapter *adapter = netdev_priv(dev);
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+ u16 sa_idx;
+
+ if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
+ sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_RX_INDEX;
+
+ if (!ipsec->rx_tbl[sa_idx].used) {
+ netdev_err(dev, "Invalid Rx SA selected sa_idx=%d offload_handle=%lu\n",
+ sa_idx, xs->xso.offload_handle);
+ return;
+ }
+
+ ixgbevf_ipsec_del_pf_sa(adapter, ipsec->rx_tbl[sa_idx].pfsa);
+ hash_del_rcu(&ipsec->rx_tbl[sa_idx].hlist);
+ memset(&ipsec->rx_tbl[sa_idx], 0, sizeof(struct rx_sa));
+ ipsec->num_rx_sa--;
+ } else {
+ sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX;
+
+ if (!ipsec->tx_tbl[sa_idx].used) {
+ netdev_err(dev, "Invalid Tx SA selected sa_idx=%d offload_handle=%lu\n",
+ sa_idx, xs->xso.offload_handle);
+ return;
+ }
+
+ ixgbevf_ipsec_del_pf_sa(adapter, ipsec->tx_tbl[sa_idx].pfsa);
+ memset(&ipsec->tx_tbl[sa_idx], 0, sizeof(struct tx_sa));
+ ipsec->num_tx_sa--;
+ }
+}
+
+/**
+ * ixgbevf_ipsec_offload_ok - can this packet use the xfrm hw offload
+ * @skb: current data packet
+ * @xs: pointer to transformer state struct
+ **/
+static bool ixgbevf_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 ixgbevf_xfrmdev_ops = {
+ .xdo_dev_state_add = ixgbevf_ipsec_add_sa,
+ .xdo_dev_state_delete = ixgbevf_ipsec_del_sa,
+ .xdo_dev_offload_ok = ixgbevf_ipsec_offload_ok,
+};
+
+/**
+ * ixgbevf_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 ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring,
+ struct ixgbevf_tx_buffer *first,
+ struct ixgbevf_ipsec_tx_data *itd)
+{
+ struct ixgbevf_adapter *adapter = netdev_priv(tx_ring->netdev);
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_state *xs;
+ struct tx_sa *tsa;
+ u16 sa_idx;
+
+ if (unlikely(!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 (unlikely(!xs)) {
+ netdev_err(tx_ring->netdev, "%s: no xfrm_input_state() xs = %p\n",
+ __func__, xs);
+ return 0;
+ }
+
+ sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX;
+ if (unlikely(sa_idx > IXGBE_IPSEC_MAX_SA_COUNT)) {
+ netdev_err(tx_ring->netdev, "%s: bad sa_idx=%d handle=%lu\n",
+ __func__, sa_idx, xs->xso.offload_handle);
+ return 0;
+ }
+
+ tsa = &ipsec->tx_tbl[sa_idx];
+ if (unlikely(!tsa->used)) {
+ netdev_err(tx_ring->netdev, "%s: unused sa_idx=%d\n",
+ __func__, sa_idx);
+ return 0;
+ }
+
+ itd->pfsa = tsa->pfsa - IXGBE_IPSEC_BASE_TX_INDEX;
+
+ first->tx_flags |= IXGBE_TX_FLAGS_IPSEC | IXGBE_TX_FLAGS_CSUM;
+
+ 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;
+
+ /* The actual trailer length is authlen (16 bytes) plus
+ * 2 bytes for the proto and the padlen values, plus
+ * padlen bytes of padding. This ends up not the same
+ * as the static value found in xs->props.trailer_len (21).
+ *
+ * ... but if we're doing GSO, don't bother as the stack
+ * doesn't add a trailer for those.
+ */
+ if (!skb_is_gso(first->skb)) {
+ /* The "correct" way to get the auth length would be
+ * to use
+ * authlen = crypto_aead_authsize(xs->data);
+ * but since we know we only have one size to worry
+ * about * we can let the compiler use the constant
+ * and save us a few CPU cycles.
+ */
+ const int authlen = IXGBE_IPSEC_AUTH_BITS / 8;
+ struct sk_buff *skb = first->skb;
+ u8 padlen;
+ int ret;
+
+ ret = skb_copy_bits(skb, skb->len - (authlen + 2),
+ &padlen, 1);
+ if (unlikely(ret))
+ return 0;
+ itd->trailer_len = authlen + 2 + padlen;
+ }
+ }
+ if (tsa->encrypt)
+ itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN;
+
+ return 1;
+}
+
+/**
+ * ixgbevf_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 ixgbevf_ipsec_rx(struct ixgbevf_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct ixgbevf_adapter *adapter = netdev_priv(rx_ring->netdev);
+ __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+ __le16 ipsec_pkt_types = cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_AH |
+ IXGBE_RXDADV_PKTTYPE_IPSEC_ESP);
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+ struct xfrm_offload *xo = NULL;
+ struct xfrm_state *xs = NULL;
+ struct ipv6hdr *ip6 = NULL;
+ struct iphdr *ip4 = NULL;
+ void *daddr;
+ __be32 spi;
+ u8 *c_hdr;
+ u8 proto;
+
+ /* Find the IP and crypto headers in the data.
+ * 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.
+ */
+ if (pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPV4)) {
+ ip4 = (struct iphdr *)(skb->data + ETH_HLEN);
+ daddr = &ip4->daddr;
+ c_hdr = (u8 *)ip4 + ip4->ihl * 4;
+ } else if (pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPV6)) {
+ ip6 = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+ daddr = &ip6->daddr;
+ c_hdr = (u8 *)ip6 + sizeof(struct ipv6hdr);
+ } else {
+ return;
+ }
+
+ switch (pkt_info & ipsec_pkt_types) {
+ case cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_AH):
+ spi = ((struct ip_auth_hdr *)c_hdr)->spi;
+ proto = IPPROTO_AH;
+ break;
+ case cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_ESP):
+ spi = ((struct ip_esp_hdr *)c_hdr)->spi;
+ proto = IPPROTO_ESP;
+ break;
+ default:
+ return;
+ }
+
+ xs = ixgbevf_ipsec_find_rx_state(ipsec, daddr, proto, spi, !!ip4);
+ 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;
+
+ adapter->rx_ipsec++;
+}
+
+/**
+ * ixgbevf_init_ipsec_offload - initialize registers for IPsec operation
+ * @adapter: board private structure
+ **/
+void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter)
+{
+ struct ixgbevf_ipsec *ipsec;
+ size_t size;
+
+ switch (adapter->hw.api_version) {
+ case ixgbe_mbox_api_14:
+ break;
+ default:
+ return;
+ }
+
+ ipsec = kzalloc(sizeof(*ipsec), GFP_KERNEL);
+ if (!ipsec)
+ goto err1;
+ hash_init(ipsec->rx_sa_list);
+
+ size = sizeof(struct rx_sa) * IXGBE_IPSEC_MAX_SA_COUNT;
+ ipsec->rx_tbl = kzalloc(size, GFP_KERNEL);
+ if (!ipsec->rx_tbl)
+ goto err2;
+
+ size = sizeof(struct tx_sa) * IXGBE_IPSEC_MAX_SA_COUNT;
+ ipsec->tx_tbl = kzalloc(size, GFP_KERNEL);
+ if (!ipsec->tx_tbl)
+ goto err2;
+
+ ipsec->num_rx_sa = 0;
+ ipsec->num_tx_sa = 0;
+
+ adapter->ipsec = ipsec;
+
+ adapter->netdev->xfrmdev_ops = &ixgbevf_xfrmdev_ops;
+
+#define IXGBEVF_ESP_FEATURES (NETIF_F_HW_ESP | \
+ NETIF_F_HW_ESP_TX_CSUM | \
+ NETIF_F_GSO_ESP)
+
+ adapter->netdev->features |= IXGBEVF_ESP_FEATURES;
+ adapter->netdev->hw_enc_features |= IXGBEVF_ESP_FEATURES;
+
+ return;
+
+err2:
+ kfree(ipsec->rx_tbl);
+ kfree(ipsec->tx_tbl);
+ kfree(ipsec);
+err1:
+ netdev_err(adapter->netdev, "Unable to allocate memory for SA tables");
+}
+
+/**
+ * ixgbevf_stop_ipsec_offload - tear down the IPsec offload
+ * @adapter: board private structure
+ **/
+void ixgbevf_stop_ipsec_offload(struct ixgbevf_adapter *adapter)
+{
+ struct ixgbevf_ipsec *ipsec = adapter->ipsec;
+
+ adapter->ipsec = NULL;
+ if (ipsec) {
+ kfree(ipsec->rx_tbl);
+ kfree(ipsec->tx_tbl);
+ kfree(ipsec);
+ }
+}
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.h b/drivers/net/ethernet/intel/ixgbevf/ipsec.h
new file mode 100644
index 000000000000..3740725041c3
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2018 Oracle and/or its affiliates. All rights reserved. */
+
+#ifndef _IXGBEVF_IPSEC_H_
+#define _IXGBEVF_IPSEC_H_
+
+#define IXGBE_IPSEC_MAX_SA_COUNT 1024
+#define IXGBE_IPSEC_BASE_RX_INDEX 0
+#define IXGBE_IPSEC_BASE_TX_INDEX IXGBE_IPSEC_MAX_SA_COUNT
+#define IXGBE_IPSEC_AUTH_BITS 128
+
+#define IXGBE_RXMOD_VALID 0x00000001
+#define IXGBE_RXMOD_PROTO_ESP 0x00000004
+#define IXGBE_RXMOD_DECRYPT 0x00000008
+#define IXGBE_RXMOD_IPV6 0x00000010
+
+struct rx_sa {
+ struct hlist_node hlist;
+ struct xfrm_state *xs;
+ __be32 ipaddr[4];
+ u32 key[4];
+ u32 salt;
+ u32 mode;
+ u32 pfsa;
+ bool used;
+ bool decrypt;
+};
+
+struct rx_ip_sa {
+ __be32 ipaddr[4];
+ u32 ref_cnt;
+ bool used;
+};
+
+struct tx_sa {
+ struct xfrm_state *xs;
+ u32 key[4];
+ u32 salt;
+ u32 pfsa;
+ bool encrypt;
+ bool used;
+};
+
+struct ixgbevf_ipsec_tx_data {
+ u32 flags;
+ u16 trailer_len;
+ u16 pfsa;
+};
+
+struct ixgbevf_ipsec {
+ u16 num_rx_sa;
+ u16 num_tx_sa;
+ struct rx_sa *rx_tbl;
+ struct tx_sa *tx_tbl;
+ DECLARE_HASHTABLE(rx_sa_list, 10);
+};
+
+struct sa_mbx_msg {
+ __be32 spi;
+ u8 flags;
+ u8 proto;
+ u16 family;
+ __be32 addr[4];
+ u32 key[5];
+};
+#endif /* _IXGBEVF_IPSEC_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 56a1031dcc07..172637e2f2e6 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -14,6 +14,7 @@
#include <net/xdp.h>
#include "vf.h"
+#include "ipsec.h"
#define IXGBE_MAX_TXD_PWR 14
#define IXGBE_MAX_DATA_PER_TXD BIT(IXGBE_MAX_TXD_PWR)
@@ -163,6 +164,7 @@ struct ixgbevf_ring {
#define IXGBE_TX_FLAGS_VLAN BIT(1)
#define IXGBE_TX_FLAGS_TSO BIT(2)
#define IXGBE_TX_FLAGS_IPV4 BIT(3)
+#define IXGBE_TX_FLAGS_IPSEC BIT(4)
#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000
#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
@@ -338,6 +340,7 @@ struct ixgbevf_adapter {
struct ixgbevf_ring *tx_ring[MAX_TX_QUEUES]; /* One per active queue */
u64 restart_queue;
u32 tx_timeout_count;
+ u64 tx_ipsec;
/* RX */
int num_rx_queues;
@@ -348,6 +351,7 @@ struct ixgbevf_adapter {
u64 alloc_rx_page_failed;
u64 alloc_rx_buff_failed;
u64 alloc_rx_page;
+ u64 rx_ipsec;
struct msix_entry *msix_entries;
@@ -384,6 +388,10 @@ struct ixgbevf_adapter {
u8 rss_indir_tbl[IXGBEVF_X550_VFRETA_SIZE];
u32 flags;
#define IXGBEVF_FLAGS_LEGACY_RX BIT(1)
+
+#ifdef CONFIG_XFRM
+ struct ixgbevf_ipsec *ipsec;
+#endif /* CONFIG_XFRM */
};
enum ixbgevf_state_t {
--
2.17.1
^ permalink raw reply related
* [net-next 04/13] ixgbe: reload IPsec IP table after sa tables
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Restore the IPsec hardware IP table after reloading the SA tables.
This doesn't make much difference now, but will matter when we add
support for VF IPsec offloads.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index e515246d0bce..434065109b8d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -301,14 +301,6 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
ixgbe_ipsec_clear_hw_tables(adapter);
ixgbe_ipsec_start_engine(adapter);
- /* reload the IP addrs */
- for (i = 0; i < IXGBE_IPSEC_MAX_RX_IP_COUNT; i++) {
- struct rx_ip_sa *ipsa = &ipsec->ip_tbl[i];
-
- if (ipsa->used)
- ixgbe_ipsec_set_rx_ip(hw, i, ipsa->ipaddr);
- }
-
/* reload the Rx and Tx keys */
for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) {
struct rx_sa *rsa = &ipsec->rx_tbl[i];
@@ -322,6 +314,14 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
if (tsa->used)
ixgbe_ipsec_set_tx_sa(hw, i, tsa->key, tsa->salt);
}
+
+ /* reload the IP addrs */
+ for (i = 0; i < IXGBE_IPSEC_MAX_RX_IP_COUNT; i++) {
+ struct rx_ip_sa *ipsa = &ipsec->ip_tbl[i];
+
+ if (ipsa->used)
+ ixgbe_ipsec_set_rx_ip(hw, i, ipsa->ipaddr);
+ }
}
/**
--
2.17.1
^ permalink raw reply related
* [net-next 07/13] ixgbe: add VF IPsec offload enable flag
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Add a private flag to expressly enable support for VF IPsec offload.
The VF will have to be "trusted" in order to use the hardware offload,
but because of the general concerns of managing VF access, we want to
be sure the user specifically is enabling the feature.
This is likely a candidate for becoming a netdev feature flag.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 +
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 9 +++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 3 ++-
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 4fc906c6166b..89e709ce1947 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -605,6 +605,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_EEE_ENABLED BIT(15)
#define IXGBE_FLAG2_RX_LEGACY BIT(16)
#define IXGBE_FLAG2_IPSEC_ENABLED BIT(17)
+#define IXGBE_FLAG2_VF_IPSEC_ENABLED BIT(18)
/* Tx fast path data */
int num_tx_queues;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index e5a8461fe6a9..732b1e6ecc43 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -136,6 +136,8 @@ static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = {
static const char ixgbe_priv_flags_strings[][ETH_GSTRING_LEN] = {
#define IXGBE_PRIV_FLAGS_LEGACY_RX BIT(0)
"legacy-rx",
+#define IXGBE_PRIV_FLAGS_VF_IPSEC_EN BIT(1)
+ "vf-ipsec",
};
#define IXGBE_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbe_priv_flags_strings)
@@ -3409,6 +3411,9 @@ static u32 ixgbe_get_priv_flags(struct net_device *netdev)
if (adapter->flags2 & IXGBE_FLAG2_RX_LEGACY)
priv_flags |= IXGBE_PRIV_FLAGS_LEGACY_RX;
+ if (adapter->flags2 & IXGBE_FLAG2_VF_IPSEC_ENABLED)
+ priv_flags |= IXGBE_PRIV_FLAGS_VF_IPSEC_EN;
+
return priv_flags;
}
@@ -3421,6 +3426,10 @@ static int ixgbe_set_priv_flags(struct net_device *netdev, u32 priv_flags)
if (priv_flags & IXGBE_PRIV_FLAGS_LEGACY_RX)
flags2 |= IXGBE_FLAG2_RX_LEGACY;
+ flags2 &= ~IXGBE_FLAG2_VF_IPSEC_ENABLED;
+ if (priv_flags & IXGBE_PRIV_FLAGS_VF_IPSEC_EN)
+ flags2 |= IXGBE_FLAG2_VF_IPSEC_ENABLED;
+
if (flags2 != adapter->flags2) {
adapter->flags2 = flags2;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 80108e12ab86..ecd01fade960 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -880,7 +880,8 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
int err;
sam = (struct sa_mbx_msg *)(&msgbuf[1]);
- if (!adapter->vfinfo[vf].trusted) {
+ if (!adapter->vfinfo[vf].trusted ||
+ !(adapter->flags2 & IXGBE_FLAG2_VF_IPSEC_ENABLED)) {
e_warn(drv, "VF %d attempted to add an IPsec SA\n", vf);
err = -EACCES;
goto err_out;
--
2.17.1
^ permalink raw reply related
* [net-next 08/13] ixgbe: add VF IPsec offload request message handling
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Add an add and a delete message for IPsec offload requests from
the VF. These call into the IPsec functions that can translate
the message buffer into a useful IPsec offload.
These new messages bump the mbox API version to 1.4.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 19 ++++++++++++++-----
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h | 5 +++++
.../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 17 ++++++++++++++++-
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 89e709ce1947..5c6fd42e90ed 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -1004,15 +1004,24 @@ void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
struct sk_buff *skb);
int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first,
struct ixgbe_ipsec_tx_data *itd);
+void ixgbe_ipsec_vf_clear(struct ixgbe_adapter *adapter, u32 vf);
+int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *mbuf, u32 vf);
+int ixgbe_ipsec_vf_del_sa(struct ixgbe_adapter *adapter, u32 *mbuf, u32 vf);
#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_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) { };
+ 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; };
+ struct ixgbe_ipsec_tx_data *itd) { return 0; }
+static inline void ixgbe_ipsec_vf_clear(struct ixgbe_adapter *adapter,
+ u32 vf) { }
+static inline int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter,
+ u32 *mbuf, u32 vf) { return -EACCES; }
+static inline int ixgbe_ipsec_vf_del_sa(struct ixgbe_adapter *adapter,
+ u32 *mbuf, u32 vf) { return -EACCES; }
#endif /* CONFIG_XFRM_OFFLOAD */
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index e085b6520dac..a148534d7256 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -50,6 +50,7 @@ enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
ixgbe_mbox_api_13, /* API version 1.3, linux/freebsd VF driver */
+ ixgbe_mbox_api_14, /* API version 1.4, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -80,6 +81,10 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c
+/* mailbox API, version 1.4 VF requests */
+#define IXGBE_VF_IPSEC_ADD 0x0d
+#define IXGBE_VF_IPSEC_DEL 0x0e
+
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 3c6f01c41b78..af25a8fffeb8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -496,6 +496,7 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
/* Version 1.1 supports jumbo frames on VFs if PF has
* jumbo frames enabled which means legacy VFs are
* disabled
@@ -728,6 +729,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
/* reset multicast table array for vf */
adapter->vfinfo[vf].num_vf_mc_hashes = 0;
+ /* clear any ipsec table info */
+ ixgbe_ipsec_vf_clear(adapter, vf);
+
/* Flush and reset the mta with the new values */
ixgbe_set_rx_mode(adapter->netdev);
@@ -1000,6 +1004,7 @@ static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
adapter->vfinfo[vf].vf_api = api;
return 0;
default:
@@ -1025,6 +1030,7 @@ static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
break;
default:
return -1;
@@ -1065,6 +1071,7 @@ static int ixgbe_get_vf_reta(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
/* verify the PF is supporting the correct API */
switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_14:
case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12:
break;
@@ -1097,6 +1104,7 @@ static int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter,
/* verify the PF is supporting the correct API */
switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_14:
case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12:
break;
@@ -1122,8 +1130,9 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter,
/* promisc introduced in 1.3 version */
if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
return -EOPNOTSUPP;
- /* Fall threw */
+ /* Fall through */
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_14:
break;
default:
return -EOPNOTSUPP;
@@ -1249,6 +1258,12 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
case IXGBE_VF_UPDATE_XCAST_MODE:
retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf);
break;
+ case IXGBE_VF_IPSEC_ADD:
+ retval = ixgbe_ipsec_vf_add_sa(adapter, msgbuf, vf);
+ break;
+ case IXGBE_VF_IPSEC_DEL:
+ retval = ixgbe_ipsec_vf_del_sa(adapter, msgbuf, vf);
+ break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
retval = IXGBE_ERR_MBX;
--
2.17.1
^ permalink raw reply related
* [net-next 09/13] ixgbevf: add defines for IPsec offload request
From: Jeff Kirsher @ 2018-08-28 21:35 UTC (permalink / raw)
To: davem; +Cc: Shannon Nelson, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20180828213558.19273-1-jeffrey.t.kirsher@intel.com>
From: Shannon Nelson <shannon.nelson@oracle.com>
Fix up the register definitions for using IPsec offloads and
add the new mailbox message IDs.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbevf/defines.h | 8 ++++++++
drivers/net/ethernet/intel/ixgbevf/mbx.h | 5 +++++
2 files changed, 13 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index 700d8eb2f6f8..dd9cd4541d7a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -133,9 +133,14 @@ typedef u32 ixgbe_link_speed;
#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */
#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */
#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */
+#define IXGBE_RXDADV_STAT_SECP 0x00020000 /* IPsec/MACsec pkt found */
#define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F
#define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0
+#define IXGBE_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPv4 hdr present */
+#define IXGBE_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPv6 hdr present */
+#define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
+#define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
#define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0
#define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0
#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000
@@ -250,9 +255,12 @@ struct ixgbe_adv_tx_context_desc {
#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
+#define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
+#define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000 /* ESP Encrypt Enable */
#define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
#define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */
#define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */
+#define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
#define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \
IXGBE_ADVTXD_POPTS_SHIFT)
#define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index bfd9ae150808..853796c8ef0e 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -62,6 +62,7 @@ enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
ixgbe_mbox_api_13, /* API version 1.3, linux/freebsd VF driver */
+ ixgbe_mbox_api_14, /* API version 1.4, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -92,6 +93,10 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c
+/* mailbox API, version 1.4 VF requests */
+#define IXGBE_VF_IPSEC_ADD 0x0d
+#define IXGBE_VF_IPSEC_DEL 0x0e
+
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
--
2.17.1
^ 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