* [PATCH] mac80211: aggregation: Convert timers to use timer_setup()
From: Kees Cook @ 2017-10-17 20:25 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, David S. Miller, netdev, linux-kernel
In preparation for unconditionally passing the struct timer_list pointer to
all timer callbacks, switch to using the new timer_setup() and from_timer()
to pass the timer pointer explicitly.
This removes the tid mapping array and expands the tid structures to
add a pointer back to the station, along with the tid index itself.
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
Resend, with linux-wireless in Cc (no idea how it got missed before)
---
net/mac80211/agg-rx.c | 41 +++++++++++++++++------------------------
net/mac80211/agg-tx.c | 42 ++++++++++++++++--------------------------
net/mac80211/sta_info.c | 8 --------
net/mac80211/sta_info.h | 12 ++++++++++--
4 files changed, 43 insertions(+), 60 deletions(-)
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 88cc1ae935ea..63aba6dbc92a 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -151,21 +151,17 @@ EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
* After accepting the AddBA Request we activated a timer,
* resetting it after each frame that arrives from the originator.
*/
-static void sta_rx_agg_session_timer_expired(unsigned long data)
+static void sta_rx_agg_session_timer_expired(struct timer_list *t)
{
- /* not an elegant detour, but there is no choice as the timer passes
- * only one argument, and various sta_info are needed here, so init
- * flow in sta_info_create gives the TID as data, while the timer_to_id
- * array gives the sta through container_of */
- u8 *ptid = (u8 *)data;
- u8 *timer_to_id = ptid - *ptid;
- struct sta_info *sta = container_of(timer_to_id, struct sta_info,
- timer_to_tid[0]);
+ struct tid_ampdu_rx *tid_rx_timer =
+ from_timer(tid_rx_timer, t, session_timer);
+ struct sta_info *sta = tid_rx_timer->sta;
+ u16 tid = tid_rx_timer->tid;
struct tid_ampdu_rx *tid_rx;
unsigned long timeout;
rcu_read_lock();
- tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]);
+ tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
if (!tid_rx) {
rcu_read_unlock();
return;
@@ -180,21 +176,18 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
rcu_read_unlock();
ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
- sta->sta.addr, (u16)*ptid);
+ sta->sta.addr, tid);
- set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired);
+ set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
}
-static void sta_rx_agg_reorder_timer_expired(unsigned long data)
+static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
{
- u8 *ptid = (u8 *)data;
- u8 *timer_to_id = ptid - *ptid;
- struct sta_info *sta = container_of(timer_to_id, struct sta_info,
- timer_to_tid[0]);
+ struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
rcu_read_lock();
- ieee80211_release_reorder_timeout(sta, *ptid);
+ ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
rcu_read_unlock();
}
@@ -356,14 +349,12 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
spin_lock_init(&tid_agg_rx->reorder_lock);
/* rx timer */
- setup_deferrable_timer(&tid_agg_rx->session_timer,
- sta_rx_agg_session_timer_expired,
- (unsigned long)&sta->timer_to_tid[tid]);
+ timer_setup(&tid_agg_rx->session_timer,
+ sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
/* rx reorder timer */
- setup_timer(&tid_agg_rx->reorder_timer,
- sta_rx_agg_reorder_timer_expired,
- (unsigned long)&sta->timer_to_tid[tid]);
+ timer_setup(&tid_agg_rx->reorder_timer,
+ sta_rx_agg_reorder_timer_expired, 0);
/* prepare reordering buffer */
tid_agg_rx->reorder_buf =
@@ -399,6 +390,8 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
tid_agg_rx->auto_seq = auto_seq;
tid_agg_rx->started = false;
tid_agg_rx->reorder_buf_filtered = 0;
+ tid_agg_rx->tid = tid;
+ tid_agg_rx->sta = sta;
status = WLAN_STATUS_SUCCESS;
/* activate it for RX */
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index bef516ec47f9..dedbb1fb10e7 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -422,15 +422,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
* add Block Ack response will arrive from the recipient.
* If this timer expires sta_addba_resp_timer_expired will be executed.
*/
-static void sta_addba_resp_timer_expired(unsigned long data)
+static void sta_addba_resp_timer_expired(struct timer_list *t)
{
- /* not an elegant detour, but there is no choice as the timer passes
- * only one argument, and both sta_info and TID are needed, so init
- * flow in sta_info_create gives the TID as data, while the timer_to_id
- * array gives the sta through container_of */
- u16 tid = *(u8 *)data;
- struct sta_info *sta = container_of((void *)data,
- struct sta_info, timer_to_tid[tid]);
+ struct tid_ampdu_tx *tid_tx_timer =
+ from_timer(tid_tx_timer, t, addba_resp_timer);
+ struct sta_info *sta = tid_tx_timer->sta;
+ u16 tid = tid_tx_timer->tid;
struct tid_ampdu_tx *tid_tx;
/* check if the TID waits for addBA response */
@@ -525,21 +522,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
* After accepting the AddBA Response we activated a timer,
* resetting it after each frame that we send.
*/
-static void sta_tx_agg_session_timer_expired(unsigned long data)
+static void sta_tx_agg_session_timer_expired(struct timer_list *t)
{
- /* not an elegant detour, but there is no choice as the timer passes
- * only one argument, and various sta_info are needed here, so init
- * flow in sta_info_create gives the TID as data, while the timer_to_id
- * array gives the sta through container_of */
- u8 *ptid = (u8 *)data;
- u8 *timer_to_id = ptid - *ptid;
- struct sta_info *sta = container_of(timer_to_id, struct sta_info,
- timer_to_tid[0]);
+ struct tid_ampdu_tx *tid_tx_timer =
+ from_timer(tid_tx_timer, t, session_timer);
+ struct sta_info *sta = tid_tx_timer->sta;
+ u16 tid = tid_tx_timer->tid;
struct tid_ampdu_tx *tid_tx;
unsigned long timeout;
rcu_read_lock();
- tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[*ptid]);
+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
if (!tid_tx || test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
rcu_read_unlock();
return;
@@ -555,9 +548,9 @@ static void sta_tx_agg_session_timer_expired(unsigned long data)
rcu_read_unlock();
ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
- sta->sta.addr, (u16)*ptid);
+ sta->sta.addr, tid);
- ieee80211_stop_tx_ba_session(&sta->sta, *ptid);
+ ieee80211_stop_tx_ba_session(&sta->sta, tid);
}
int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
@@ -672,14 +665,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
tid_tx->timeout = timeout;
/* response timer */
- setup_timer(&tid_tx->addba_resp_timer,
- sta_addba_resp_timer_expired,
- (unsigned long)&sta->timer_to_tid[tid]);
+ timer_setup(&tid_tx->addba_resp_timer, sta_addba_resp_timer_expired, 0);
/* tx timer */
- setup_deferrable_timer(&tid_tx->session_timer,
- sta_tx_agg_session_timer_expired,
- (unsigned long)&sta->timer_to_tid[tid]);
+ timer_setup(&tid_tx->session_timer,
+ sta_tx_agg_session_timer_expired, TIMER_DEFERRABLE);
/* assign a dialog token */
sta->ampdu_mlme.dialog_token_allocator++;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 877d35796776..b5add1464aeb 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -379,14 +379,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
if (sta_prepare_rate_control(local, sta, gfp))
goto free_txq;
- for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
- /*
- * timer_to_tid must be initialized with identity mapping
- * to enable session_timer's data differentiation. See
- * sta_rx_agg_session_timer_expired for usage.
- */
- sta->timer_to_tid[i] = i;
- }
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
skb_queue_head_init(&sta->ps_tx_buf[i]);
skb_queue_head_init(&sta->tx_filtered[i]);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5c54acd10562..1b9c1e81495d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -126,6 +126,8 @@ enum ieee80211_agg_stop_reason {
AGG_STOP_DESTROY_STA,
};
+struct sta_info;
+
/**
* struct tid_ampdu_tx - TID aggregation information (Tx).
*
@@ -133,8 +135,10 @@ enum ieee80211_agg_stop_reason {
* @session_timer: check if we keep Tx-ing on the TID (by timeout value)
* @addba_resp_timer: timer for peer's response to addba request
* @pending: pending frames queue -- use sta's spinlock to protect
+ * @sta: station we are attached to
* @dialog_token: dialog token for aggregation session
* @timeout: session timeout value to be filled in ADDBA requests
+ * @tid: index in station tid list
* @state: session state (see above)
* @last_tx: jiffies of last tx activity
* @stop_initiator: initiator of a session stop
@@ -158,9 +162,11 @@ struct tid_ampdu_tx {
struct timer_list session_timer;
struct timer_list addba_resp_timer;
struct sk_buff_head pending;
+ struct sta_info *sta;
unsigned long state;
unsigned long last_tx;
u16 timeout;
+ u16 tid;
u8 dialog_token;
u8 stop_initiator;
bool tx_stop;
@@ -181,12 +187,14 @@ struct tid_ampdu_tx {
* @reorder_time: jiffies when skb was added
* @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
* @reorder_timer: releases expired frames from the reorder buffer.
+ * @sta: station we are attached to
* @last_rx: jiffies of last rx activity
* @head_seq_num: head sequence number in reordering buffer.
* @stored_mpdu_num: number of MPDUs in reordering buffer
* @ssn: Starting Sequence Number expected to be aggregated.
* @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value (in TUs).
+ * @tid: index in station tid list
* @rcu_head: RCU head used for freeing this struct
* @reorder_lock: serializes access to reorder buffer, see below.
* @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
@@ -208,6 +216,7 @@ struct tid_ampdu_rx {
u64 reorder_buf_filtered;
struct sk_buff_head *reorder_buf;
unsigned long *reorder_time;
+ struct sta_info *sta;
struct timer_list session_timer;
struct timer_list reorder_timer;
unsigned long last_rx;
@@ -216,6 +225,7 @@ struct tid_ampdu_rx {
u16 ssn;
u16 buf_size;
u16 timeout;
+ u16 tid;
u8 auto_seq:1,
removed:1,
started:1;
@@ -447,7 +457,6 @@ struct ieee80211_sta_rx_stats {
* plus one for non-QoS frames)
* @tid_seq: per-TID sequence numbers for sending to this STA
* @ampdu_mlme: A-MPDU state machine state
- * @timer_to_tid: identity mapping to ID timers
* @mesh: mesh STA information
* @debugfs_dir: debug filesystem directory dentry
* @dead: set to true when sta is unlinked
@@ -554,7 +563,6 @@ struct sta_info {
* Aggregation information, locked with lock.
*/
struct sta_ampdu_mlme ampdu_mlme;
- u8 timer_to_tid[IEEE80211_NUM_TIDS];
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *debugfs_dir;
--
2.7.4
--
Kees Cook
Pixel Security
^ permalink raw reply related
* (unknown),
From: kelley @ 2017-10-17 20:28 UTC (permalink / raw)
To: netdev
[-- Attachment #1: 30998342.doc --]
[-- Type: application/msword, Size: 64000 bytes --]
^ permalink raw reply
* Re: [PATCH v3 net-next] tcp: Remove use of daddr_cache in tracepoint
From: Cong Wang @ 2017-10-17 20:34 UTC (permalink / raw)
To: David Ahern; +Cc: Linux Kernel Network Developers, Eric Dumazet
In-Reply-To: <1508270973-23789-1-git-send-email-dsahern@gmail.com>
On Tue, Oct 17, 2017 at 1:09 PM, David Ahern <dsahern@gmail.com> wrote:
> Running perf in one window to capture tcp_retransmit_skb tracepoint:
> $ perf record -e tcp:tcp_retransmit_skb -a
>
> And causing a retransmission on an active TCP session (e.g., dropping
> packets in the receiver, changing MTU on the interface to 500 and back
> to 1500) triggers a panic:
>
> [ 58.543144] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
> [ 58.545300] IP: perf_trace_tcp_retransmit_skb+0xd0/0x145
> [ 58.546770] PGD 0 P4D 0
> [ 58.547472] Oops: 0000 [#1] SMP
> [ 58.548328] Modules linked in: vrf
> [ 58.549262] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.0-rc4+ #26
> [ 58.551004] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
> [ 58.554560] task: ffffffff81a0e540 task.stack: ffffffff81a00000
> [ 58.555817] RIP: 0010:perf_trace_tcp_retransmit_skb+0xd0/0x145
> [ 58.557137] RSP: 0018:ffff88003fc03d68 EFLAGS: 00010282
> [ 58.558292] RAX: 0000000000000000 RBX: ffffe8ffffc0ec80 RCX: ffff880038543098
> [ 58.559850] RDX: 0400000000000000 RSI: ffff88003fc03d70 RDI: ffff88003fc14b68
> [ 58.561099] RBP: ffff88003fc03da8 R08: 0000000000000000 R09: ffffea0000d3224a
> [ 58.562005] R10: ffff88003fc03db8 R11: 0000000000000010 R12: ffff8800385428c0
> [ 58.562930] R13: ffffe8ffffc0e478 R14: ffffffff81a93a40 R15: ffff88003d4f0c00
> [ 58.563845] FS: 0000000000000000(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
> [ 58.564873] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 58.565613] CR2: 0000000000000008 CR3: 000000003d68f004 CR4: 00000000000606f0
> [ 58.566538] Call Trace:
> [ 58.566865] <IRQ>
> [ 58.567140] __tcp_retransmit_skb+0x4ab/0x4c6
> [ 58.567704] ? tcp_set_ca_state+0x22/0x3f
> [ 58.568231] tcp_retransmit_skb+0x14/0xa3
> [ 58.568754] tcp_retransmit_timer+0x472/0x5e3
> [ 58.569324] ? tcp_write_timer_handler+0x1e9/0x1e9
> [ 58.569946] tcp_write_timer_handler+0x95/0x1e9
> [ 58.570548] tcp_write_timer+0x2a/0x58
>
> Remove use of ipv6_pinfo in favor of data in sock_common.
>
> Fixes: e086101b150a ("tcp: add a tracepoint for tcp retransmission")
> Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
^ permalink raw reply
* [PATCH 0/7] Adding permanent config get/set to devlink
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
DIFFERENCES FROM RFC:
Implemented most of the changes suggested by Jiri and others.
Thanks for the valuable feedback!
Adds a devlink command for getting & setting permanent
(persistent / NVRAM) device configuration parameters, and
enumerates the parameters as nested devlink attributes.
bnxt driver patches make use of these new devlink cmds/
attributes.
Steve Lin (7):
devlink: Add permanent config parameter get/set operations
devlink: Adding NPAR permanent config parameters
devlink: Adding high level dev perm config params
devlink: Adding perm config of link settings
devlink: Adding pre-boot permanent config parameters
bnxt: Move generic devlink code to new file
bnxt: Add devlink support for config get/set
drivers/net/ethernet/broadcom/bnxt/Makefile | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 363 ++++++++++++++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 56 ++++
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 100 ++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 53 +---
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h | 37 +--
include/net/devlink.h | 4 +
include/uapi/linux/devlink.h | 113 +++++++
net/core/devlink.c | 300 ++++++++++++++++++
10 files changed, 944 insertions(+), 85 deletions(-)
create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
--
2.7.4
^ permalink raw reply
* [PATCH 1/7] devlink: Add permanent config parameter get/set operations
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Add support for permanent config parameter get/set commands. Used
for parameters held in NVRAM, persistent device configuration.
The config_get() and config_set() operations operate as expected, but
note that the driver implementation of the config_set() operation can
indicate whether a restart is necessary for the setting to take
effect. This indication of a necessary restart is passed via the
DEVLINK_ATTR_PERM_CFG_RESTART_REQUIRED attribute.
First set of parameters defined are PCI SR-IOV and per-VF
configuration:
DEVLINK_ATTR_PERM_CFG_SRIOV_ENABLED: Enable SR-IOV capability.
DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF: Maximum number of VFs per PF, in
SR-IOV mode.
DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT: Maximum number of
MSI-X vectors assigned per PF.
DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF: Number of MSI-X vectors
allocated per VF.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
include/net/devlink.h | 4 +
include/uapi/linux/devlink.h | 20 ++++
net/core/devlink.c | 266 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 290 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index b9654e1..952966c 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -270,6 +270,10 @@ struct devlink_ops {
int (*eswitch_inline_mode_set)(struct devlink *devlink, u8 inline_mode);
int (*eswitch_encap_mode_get)(struct devlink *devlink, u8 *p_encap_mode);
int (*eswitch_encap_mode_set)(struct devlink *devlink, u8 encap_mode);
+ int (*config_get)(struct devlink *devlink, enum devlink_attr attr,
+ u32 *value);
+ int (*config_set)(struct devlink *devlink, enum devlink_attr attr,
+ u32 value, u8 *restart_reqd);
};
static inline void *devlink_priv(struct devlink *devlink)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 0cbca96..34de44d 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -70,6 +70,9 @@ enum devlink_command {
DEVLINK_CMD_DPIPE_HEADERS_GET,
DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
+ DEVLINK_CMD_CONFIG_GET,
+ DEVLINK_CMD_CONFIG_SET,
+
/* add new commands above here */
__DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
@@ -202,6 +205,23 @@ enum devlink_attr {
DEVLINK_ATTR_ESWITCH_ENCAP_MODE, /* u8 */
+ /* Permanent Configuration Parameters */
+ DEVLINK_ATTR_PERM_CFG, /* nested */
+
+ /* When config doesn't take effect until next reboot (config
+ * just changed NVM which isn't read until boot, for example),
+ * this attribute should be set by the driver.
+ */
+ DEVLINK_ATTR_PERM_CFG_RESTART_REQUIRED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_SRIOV_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_FIRST = DEVLINK_ATTR_PERM_CFG_SRIOV_ENABLED,
+ DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF, /* u32 */
+
+ /* Add new permanent config parameters above here */
+ DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF,
+
/* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 7d430c1..427a65e 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -1566,6 +1566,254 @@ static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
return 0;
}
+static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1];
+
+static int devlink_nl_sing_param_get(struct sk_buff *msg,
+ struct devlink *devlink,
+ enum devlink_attr attr)
+{
+ struct nla_policy policy;
+ u32 value;
+ int err;
+ const struct devlink_ops *ops = devlink->ops;
+
+ policy = devlink_nl_policy[attr];
+ err = ops->config_get(devlink, attr, &value);
+ if (err)
+ return err;
+
+ switch (policy.type) {
+ case NLA_U8:
+ err = nla_put_u8(msg, attr, value);
+ break;
+ case NLA_U16:
+ err = nla_put_u16(msg, attr, value);
+ break;
+ case NLA_U32:
+ err = nla_put_u32(msg, attr, value);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int devlink_nl_config_get_fill(struct sk_buff *msg,
+ struct devlink *devlink,
+ enum devlink_command cmd,
+ struct genl_info *info)
+{
+ const struct devlink_ops *ops = devlink->ops;
+ void *hdr;
+ int err;
+ enum devlink_attr attr;
+ int param_count = 0;
+ struct nlattr *cfgparam_attr;
+
+ if (!ops->config_get)
+ return -EOPNOTSUPP;
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &devlink_nl_family, 0, cmd);
+ if (!hdr) {
+ err = -EMSGSIZE;
+ goto nla_msg_failure;
+ }
+
+ err = devlink_nl_put_handle(msg, devlink);
+ if (err)
+ goto nla_put_failure;
+
+ cfgparam_attr = nla_nest_start(msg, DEVLINK_ATTR_PERM_CFG);
+
+ /* Were specific parameter(s) requested? */
+ for (attr = DEVLINK_ATTR_PERM_CFG_FIRST;
+ attr <= DEVLINK_ATTR_PERM_CFG_LAST; attr++) {
+ if (info->attrs[attr]) {
+ err = devlink_nl_sing_param_get(msg, devlink, attr);
+ if (err)
+ goto nla_nest_failure;
+ param_count++;
+ break;
+ }
+ }
+
+ if (param_count == 0) {
+ /* return all parameter values */
+ for (attr = DEVLINK_ATTR_PERM_CFG_FIRST;
+ attr <= DEVLINK_ATTR_PERM_CFG_LAST; attr++) {
+ err = devlink_nl_sing_param_get(msg, devlink, attr);
+ if (err)
+ goto nla_nest_failure;
+ }
+ }
+ nla_nest_end(msg, cfgparam_attr);
+
+ genlmsg_end(msg, hdr);
+ return 0;
+
+nla_nest_failure:
+ nla_nest_cancel(msg, cfgparam_attr);
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+nla_msg_failure:
+ return err;
+}
+
+static int devlink_nl_cmd_config_get_doit(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct devlink *devlink = info->user_ptr[0];
+ struct sk_buff *msg;
+ int err;
+
+ if (!devlink->ops)
+ return -EOPNOTSUPP;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ err = devlink_nl_config_get_fill(msg, devlink, DEVLINK_CMD_CONFIG_GET,
+ info);
+
+ if (err) {
+ nlmsg_free(msg);
+ return err;
+ }
+
+ return genlmsg_reply(msg, info);
+}
+
+static int devlink_nl_sing_param_set(struct sk_buff *msg,
+ struct devlink *devlink,
+ struct genl_info *info,
+ enum devlink_attr attr,
+ u8 *restart_reqd)
+{
+ struct nla_policy policy;
+ u32 orig_value;
+ u32 new_value;
+ u8 need_restart;
+ u8 *val8;
+ u16 *val16;
+ u32 *val32;
+ int err;
+ const struct devlink_ops *ops = devlink->ops;
+
+ policy = devlink_nl_policy[attr];
+
+ /* First get current value of parameter */
+ err = ops->config_get(devlink, attr, &orig_value);
+ if (err)
+ return err;
+
+ /* Now set parameter */
+ switch (policy.type) {
+ case NLA_U8:
+ val8 = nla_data(info->attrs[attr]);
+ new_value = *val8;
+ break;
+ case NLA_U16:
+ val16 = nla_data(info->attrs[attr]);
+ new_value = *val16;
+ break;
+ case NLA_U32:
+ val32 = nla_data(info->attrs[attr]);
+ new_value = *val32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = ops->config_set(devlink, attr, new_value, &need_restart);
+ if (err)
+ return err;
+
+ /* Update restart reqd - if any param needs restart, should be set */
+ *restart_reqd |= need_restart;
+
+ /* Since set was successful, write attr back to msg with orig val */
+ switch (policy.type) {
+ case NLA_U8:
+ err = nla_put_u8(msg, attr, orig_value);
+ break;
+ case NLA_U16:
+ err = nla_put_u16(msg, attr, orig_value);
+ break;
+ case NLA_U32:
+ err = nla_put_u32(msg, attr, orig_value);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int devlink_nl_cmd_config_set_doit(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct devlink *devlink = info->user_ptr[0];
+ struct sk_buff *msg;
+ void *hdr;
+ enum devlink_attr attr;
+ int err;
+ u8 restart_reqd = 0;
+ struct nlattr *cfgparam_attr;
+
+ if (!devlink->ops || !devlink->ops->config_set)
+ return -EOPNOTSUPP;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &devlink_nl_family, 0, DEVLINK_CMD_CONFIG_SET);
+ if (!hdr) {
+ err = -EMSGSIZE;
+ goto nla_msg_failure;
+ }
+
+ err = devlink_nl_put_handle(msg, devlink);
+ if (err)
+ goto nla_put_failure;
+
+ cfgparam_attr = nla_nest_start(msg, DEVLINK_ATTR_PERM_CFG);
+
+ /* Find attribute(s) being set */
+ for (attr = DEVLINK_ATTR_PERM_CFG_FIRST;
+ attr <= DEVLINK_ATTR_PERM_CFG_LAST; attr++) {
+ if (info->attrs[attr]) {
+ err = devlink_nl_sing_param_set(msg, devlink, info,
+ attr, &restart_reqd);
+ if (err)
+ goto nla_nest_failure;
+ }
+ }
+
+ nla_nest_end(msg, cfgparam_attr);
+
+ if (restart_reqd) {
+ err = nla_put_u8(msg, DEVLINK_ATTR_PERM_CFG_RESTART_REQUIRED,
+ restart_reqd);
+ if (err)
+ goto nla_put_failure;
+ }
+
+ genlmsg_end(msg, hdr);
+ return genlmsg_reply(msg, info);
+
+nla_nest_failure:
+ nla_nest_cancel(msg, cfgparam_attr);
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+nla_msg_failure:
+ return err;
+}
+
int devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match)
{
@@ -2291,6 +2539,10 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_SRIOV_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF] = { .type = NLA_U32 },
};
static const struct genl_ops devlink_nl_ops[] = {
@@ -2451,6 +2703,20 @@ static const struct genl_ops devlink_nl_ops[] = {
.flags = GENL_ADMIN_PERM,
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
},
+ {
+ .cmd = DEVLINK_CMD_CONFIG_GET,
+ .doit = devlink_nl_cmd_config_get_doit,
+ .policy = devlink_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
+ },
+ {
+ .cmd = DEVLINK_CMD_CONFIG_SET,
+ .doit = devlink_nl_cmd_config_set_doit,
+ .policy = devlink_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
+ },
};
static struct genl_family devlink_nl_family __ro_after_init = {
--
2.7.4
^ permalink raw reply related
* [PATCH 2/7] devlink: Adding NPAR permanent config parameters
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Extending DEVLINK_ATTR_PERM_CFG (permanent/NVRAM device configuration)
to include NPAR settings:
DEVLINK_ATTR_PERM_CFG_NPAR_NUM_PARTITIONS_PER_PORT: Number of NIC
Partitions (NPAR) per port.
DEVLINK_ATTR_PERM_CFG_NPAR_BW_IN_PERCENT: 1 if BW_RESERVATION and
BW_LIMIT is in percent; /0 if BW_RESERVATION and BW_LIMIT is in
100 Mbps units.
DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION: Configures NPAR bandwidth
or weight reservation, in percent or 100 Mbps units, depending on
BW_IN_PERCENT.
DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID: 1 to use
BW_RESERVATION setting, 0 to ignore.
DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT: Configures NPAR bandwidth or
weight limit, in percent or 100 Mbps units, depending on
BW_IN_PERCENT.
DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID: 1 to use BW_LIMIT
setting, 0 to ignore.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
include/uapi/linux/devlink.h | 8 +++++++-
net/core/devlink.c | 7 +++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 34de44d..21cfb37 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -218,9 +218,15 @@ enum devlink_attr {
DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF, /* u32 */
DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT, /* u32 */
DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_NUM_PARTITIONS_PER_PORT, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_BW_IN_PERCENT, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID,/* u8 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID, /* u8 */
/* Add new permanent config parameters above here */
- DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF,
+ DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID,
/* add new attributes above here, update the policy in devlink.c */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 427a65e..76bb6d4 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2543,6 +2543,13 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF] = { .type = NLA_U32 },
[DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT] = { .type = NLA_U32 },
[DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_NUM_PARTITIONS_PER_PORT] = {
+ .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_BW_IN_PERCENT] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID] = { .type = NLA_U8 },
};
static const struct genl_ops devlink_nl_ops[] = {
--
2.7.4
^ permalink raw reply related
* [PATCH 3/7] devlink: Adding high level dev perm config params
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Extending DEVLINK_ATTR_PERM_CFG (permanent/NVRAM device configuration)
to include some high level device configuration settings:
DEVLINK_ATTR_PERM_CFG_DCBX_MODE: Data Center Bridging Exchange
(DCBX) protocol mode; use enum devlink_dcbx_mode.
DEVLINK_ATTR_PERM_CFG_RDMA_ENABLED: 1 to enable RDMA, 0 to disable.
DEVLINK_ATTR_PERM_CFG_MULTIFUNC_MODE: Configure multi-function
mode; use devlink_multifunc_mode.
DEVLINK_ATTR_PERM_CFG_SECURE_NIC_ENABLED: 1 to enable Secure NIC
functionality, 0 to disable.
DEVLINK_ATTR_PERM_CFG_IGNORE_ARI_CAPABILITY: 1 to ignore ARI
(Alternate Routing ID) interpretation, 0 to honor ARI.
DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_BRIDGE_ENABLED: 1 to enable
Link Layer Data Protocol (LLDP) on Nearest Bridge, 0 to
disable.
DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_NONTPMR_BRIDGE_ENABLED: 1 to
enable Link Layer Data Protocol (LLDP) on Non Two Port MAC
Relay (non-TPMR) Bridge, 0 to disable.
DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED: 1 to enable Power
Management Events (PME) functionality, 0 to disable.
DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED: 1 to enable
Magic Packet Wake on Lan using ACPI pattern, 0 to disable.
DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED: 1 to enable Energy
Efficient Ethernet (EEE), 0 to disable.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
include/uapi/linux/devlink.h | 27 ++++++++++++++++++++++++++-
net/core/devlink.c | 12 ++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 21cfb37..4a9eafd 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -127,6 +127,21 @@ enum devlink_eswitch_encap_mode {
DEVLINK_ESWITCH_ENCAP_MODE_BASIC,
};
+enum devlink_dcbx_mode {
+ DEVLINK_DCBX_MODE_DISABLED,
+ DEVLINK_DCBX_MODE_IEEE,
+ DEVLINK_DCBX_MODE_CEE,
+ DEVLINK_DCBX_MODE_IEEE_CEE,
+};
+
+enum devlink_multifunc_mode {
+ DEVLINK_MULTIFUNC_MODE_ALLOWED, /* Ext switch activates MF */
+ DEVLINK_MULTIFUNC_MODE_FORCE_SINGFUNC,
+ DEVLINK_MULTIFUNC_MODE_NPAR10, /* NPAR 1.0 */
+ DEVLINK_MULTIFUNC_MODE_NPAR15, /* NPAR 1.5 */
+ DEVLINK_MULTIFUNC_MODE_NPAR20, /* NPAR 2.0 */
+};
+
enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,
@@ -224,9 +239,19 @@ enum devlink_attr {
DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID,/* u8 */
DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT, /* u32 */
DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_DCBX_MODE, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_RDMA_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_MULTIFUNC_MODE, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_SECURE_NIC_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_IGNORE_ARI_CAPABILITY, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_BRIDGE_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_NONTPMR_BRIDGE_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED, /* u8 */
/* Add new permanent config parameters above here */
- DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID,
+ DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED,
/* add new attributes above here, update the policy in devlink.c */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 76bb6d4..d611154 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2550,6 +2550,18 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID] = { .type = NLA_U8 },
[DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT] = { .type = NLA_U32 },
[DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_DCBX_MODE] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_RDMA_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_MULTIFUNC_MODE] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_SECURE_NIC_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_IGNORE_ARI_CAPABILITY] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_BRIDGE_ENABLED] = {
+ .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_NONTPMR_BRIDGE_ENABLED] = {
+ .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED] = { .type = NLA_U8 },
};
static const struct genl_ops devlink_nl_ops[] = {
--
2.7.4
^ permalink raw reply related
* [PATCH 4/7] devlink: Adding perm config of link settings
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Extending DEVLINK_ATTR_PERM_CFG (permanent/NVRAM device configuration)
to include persistent configuration of device link settings:
DEVLINK_ATTR_PERM_CFG_AUTONEG_PROTOCOL: Configure default autoneg
protocol; use enum devlink_autoneg_protocol.
DEVLINK_ATTR_PERM_CFG_MEDIA_AUTO_DETECT: Configure default
auto-detection of attached media connector (1 = enable, 0 =
disable).
DEVLINK_ATTR_PERM_CFG_PHY_SELECT: Configure default external PHY
selection (0 = PHY 0, 1 = PHY 1).
DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0: Configure default
pre-OS link speed in full power (D0) state; use enum
devlink_pre_os_link_speed.
DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3: Configure default
pre-OS link speed in sleep (D3) state; use enum
devlink_pre_os_link_speed.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
include/uapi/linux/devlink.h | 27 ++++++++++++++++++++++++++-
net/core/devlink.c | 5 +++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 4a9eafd..2e1c006 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -142,6 +142,26 @@ enum devlink_multifunc_mode {
DEVLINK_MULTIFUNC_MODE_NPAR20, /* NPAR 2.0 */
};
+enum devlink_autoneg_protocol {
+ DEVLINK_AUTONEG_PROTOCOL_IEEE8023BY_BAM,
+ DEVLINK_AUTONEG_PROTOCOL_IEEE8023BY_CONSORTIUM,
+ DEVLINK_AUTONEG_PROTOCOL_IEEE8023BY,
+ DEVLINK_AUTONEG_PROTOCOL_BAM, /* Broadcom Autoneg Mode */
+ DEVLINK_AUTONEG_PROTOCOL_CONSORTIUM, /* Consortium Autoneg Mode */
+};
+
+enum devlink_pre_os_link_speed {
+ DEVLINK_PRE_OS_LINK_SPEED_AUTONEG,
+ DEVLINK_PRE_OS_LINK_SPEED_1G,
+ DEVLINK_PRE_OS_LINK_SPEED_10G,
+ DEVLINK_PRE_OS_LINK_SPEED_25G,
+ DEVLINK_PRE_OS_LINK_SPEED_40G,
+ DEVLINK_PRE_OS_LINK_SPEED_50G,
+ DEVLINK_PRE_OS_LINK_SPEED_100G,
+ DEVLINK_PRE_OS_LINK_SPEED_5G = 0xe,
+ DEVLINK_PRE_OS_LINK_SPEED_100M = 0xf,
+};
+
enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,
@@ -249,9 +269,14 @@ enum devlink_attr {
DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED, /* u8 */
DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED, /* u8 */
DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_AUTONEG_PROTOCOL, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MEDIA_AUTO_DETECT, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_PHY_SELECT, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3, /* u32 */
/* Add new permanent config parameters above here */
- DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED,
+ DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3,
/* add new attributes above here, update the policy in devlink.c */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index d611154..80a2a50 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2562,6 +2562,11 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED] = { .type = NLA_U8 },
[DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED] = { .type = NLA_U8 },
[DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_AUTONEG_PROTOCOL] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MEDIA_AUTO_DETECT] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_PHY_SELECT] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3] = { .type = NLA_U32 },
};
static const struct genl_ops devlink_nl_ops[] = {
--
2.7.4
^ permalink raw reply related
* [PATCH 5/7] devlink: Adding pre-boot permanent config parameters
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Extending DEVLINK_ATTR_PERM_CFG (permanent/NVRAM device configuration)
to include some pre-boot device configuration settings:
DEVLINK_ATTR_PERM_CFG_MBA_ENABLED: 1 to enable Multiple Boot
Agent (BMA), 0 to disable.
DEVLINK_ATTR_PERM_CFG_MBA_BOOT_TYPE: Controls mechanism MBA will
use to insert itself into the list of devices recognized by the
BIOS; use enum devlink_mba_boot_type.
DEVLINK_ATTR_PERM_CFG_MBA_DELAY_TIME: Controls how long MBA
banner display and ability to enter MBA setup will persist
during initialization, in seconds.
DEVLINK_ATTR_PERM_CFG_MBA_SETUP_HOT_KEY: Configures which hot-key
will be used to enter MBA setup; use enum devlink_mba_setup_hot_key.
DEVLINK_ATTR_PERM_CFG_MBA_HIDE_SETUP_PROMPT: 1 to enable hiding
of 'enter setup' prompt during initialization, 0 to disable.
DEVLINK_ATTR_PERM_CFG_MBA_BOOT_RETRY_COUNT: MBA retries booting
this number of times, if it fails initially.
DEVLINK_ATTR_PERM_CFG_MBA_VLAN_ENABLED: 1 to enable using VLAN
when executing MBA host software (PXE/iSCSI), 0 to disable.
DEVLINK_ATTR_PERM_CFG_MBA_VLAN_TAG: The 16 bit VLAN tag to use
if MBA_VLAN_ENABLED is set.
DEVLINK_ATTR_PERM_CFG_MBA_BOOT_PROTOCOL: Selects MBA boot
protocol; use enum devlink_mba_boot_protocol.
DEVLINK_ATTR_PERM_CFG_MBA_LINK_SPEED: Configured link speed
while executing MBA host software (PXI/iSCSI); use enum
devlink_mba_link_speed.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
include/uapi/linux/devlink.h | 39 ++++++++++++++++++++++++++++++++++++++-
net/core/devlink.c | 10 ++++++++++
2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 2e1c006..609784a 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -162,6 +162,33 @@ enum devlink_pre_os_link_speed {
DEVLINK_PRE_OS_LINK_SPEED_100M = 0xf,
};
+enum devlink_mba_boot_type {
+ DEVLINK_MBA_BOOT_TYPE_AUTO_DETECT,
+ DEVLINK_MBA_BOOT_TYPE_BBS, /* BIOS Boot Specification */
+ DEVLINK_MBA_BOOT_TYPE_INTR18, /* Hook interrupt 0x18 */
+ DEVLINK_MBA_BOOT_TYPE_INTR19, /* Hook interrupt 0x19 */
+};
+
+enum devlink_mba_setup_hot_key {
+ DEVLINK_MBA_SETUP_HOT_KEY_CTRL_S,
+ DEVLINK_MBA_SETUP_HOT_KEY_CTRL_B,
+};
+
+enum devlink_mba_boot_protocol {
+ DEVLINK_MBA_BOOT_PROTOCOL_PXE,
+ DEVLINK_MBA_BOOT_PROTOCOL_ISCSI,
+ DEVLINK_MBA_BOOT_PROTOCOL_NONE = 0x7,
+};
+
+enum devlink_mba_link_speed {
+ DEVLINK_MBA_LINK_SPEED_AUTONEG,
+ DEVLINK_MBA_LINK_SPEED_1G,
+ DEVLINK_MBA_LINK_SPEED_10G,
+ DEVLINK_MBA_LINK_SPEED_25G,
+ DEVLINK_MBA_LINK_SPEED_40G,
+ DEVLINK_MBA_LINK_SPEED_50G,
+};
+
enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,
@@ -274,9 +301,19 @@ enum devlink_attr {
DEVLINK_ATTR_PERM_CFG_PHY_SELECT, /* u8 */
DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0, /* u32 */
DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_MBA_BOOT_TYPE, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_DELAY_TIME, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_SETUP_HOT_KEY, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_HIDE_SETUP_PROMPT, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_MBA_BOOT_RETRY_COUNT, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_VLAN_ENABLED, /* u8 */
+ DEVLINK_ATTR_PERM_CFG_MBA_VLAN_TAG, /* u16 */
+ DEVLINK_ATTR_PERM_CFG_MBA_BOOT_PROTOCOL, /* u32 */
+ DEVLINK_ATTR_PERM_CFG_MBA_LINK_SPEED, /* u32 */
/* Add new permanent config parameters above here */
- DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3,
+ DEVLINK_ATTR_PERM_CFG_LAST = DEVLINK_ATTR_PERM_CFG_MBA_LINK_SPEED,
/* add new attributes above here, update the policy in devlink.c */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 80a2a50..2eaa566 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2567,6 +2567,16 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_PERM_CFG_PHY_SELECT] = { .type = NLA_U8 },
[DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0] = { .type = NLA_U32 },
[DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_BOOT_TYPE] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_DELAY_TIME] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_SETUP_HOT_KEY] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_HIDE_SETUP_PROMPT] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_BOOT_RETRY_COUNT] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_VLAN_ENABLED] = { .type = NLA_U8 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_VLAN_TAG] = { .type = NLA_U16 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_BOOT_PROTOCOL] = { .type = NLA_U32 },
+ [DEVLINK_ATTR_PERM_CFG_MBA_LINK_SPEED] = { .type = NLA_U32 },
};
static const struct genl_ops devlink_nl_ops[] = {
--
2.7.4
^ permalink raw reply related
* [PATCH 6/7] bnxt: Move generic devlink code to new file
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Moving generic devlink code (registration) out of VR-R code
into new bnxt_devlink file.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
drivers/net/ethernet/broadcom/bnxt/Makefile | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 65 +++++++++++++++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 39 ++++++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 53 ++----------------
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h | 37 ++-----------
6 files changed, 112 insertions(+), 85 deletions(-)
create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile
index 457201f..59c8ec9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/Makefile
+++ b/drivers/net/ethernet/broadcom/bnxt/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_BNXT) += bnxt_en.o
-bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_vfr.o
+bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_vfr.o bnxt_devlink.o
bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 5ba4993..52cc38d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -61,6 +61,7 @@
#include "bnxt_xdp.h"
#include "bnxt_vfr.h"
#include "bnxt_tc.h"
+#include "bnxt_devlink.h"
#define BNXT_TX_TIMEOUT (5 * HZ)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
new file mode 100644
index 0000000..f3f6aa8
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -0,0 +1,65 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2017 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_vfr.h"
+#include "bnxt_devlink.h"
+
+static const struct devlink_ops bnxt_dl_ops = {
+#ifdef CONFIG_BNXT_SRIOV
+ .eswitch_mode_set = bnxt_dl_eswitch_mode_set,
+ .eswitch_mode_get = bnxt_dl_eswitch_mode_get,
+#endif /* CONFIG_BNXT_SRIOV */
+};
+
+int bnxt_dl_register(struct bnxt *bp)
+{
+ struct devlink *dl;
+ int rc;
+
+ if (!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
+ return 0;
+
+ if (bp->hwrm_spec_code < 0x10800) {
+ netdev_warn(bp->dev, "Firmware does not support SR-IOV E-Switch SWITCHDEV mode.\n");
+ return -ENOTSUPP;
+ }
+
+ dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
+ if (!dl) {
+ netdev_warn(bp->dev, "devlink_alloc failed");
+ return -ENOMEM;
+ }
+
+ bnxt_link_bp_to_dl(bp, dl);
+ bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
+ rc = devlink_register(dl, &bp->pdev->dev);
+ if (rc) {
+ bnxt_link_bp_to_dl(bp, NULL);
+ devlink_free(dl);
+ netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+void bnxt_dl_unregister(struct bnxt *bp)
+{
+ struct devlink *dl = bp->dl;
+
+ if (!dl)
+ return;
+
+ devlink_unregister(dl);
+ devlink_free(dl);
+}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
new file mode 100644
index 0000000..e92a35d
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
@@ -0,0 +1,39 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2017 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef BNXT_DEVLINK_H
+#define BNXT_DEVLINK_H
+
+/* Struct to hold housekeeping info needed by devlink interface */
+struct bnxt_dl {
+ struct bnxt *bp; /* back ptr to the controlling dev */
+};
+
+static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl)
+{
+ return ((struct bnxt_dl *)devlink_priv(dl))->bp;
+}
+
+/* To clear devlink pointer from bp, pass NULL dl */
+static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
+{
+ bp->dl = dl;
+
+ /* add a back pointer in dl to bp */
+ if (dl) {
+ struct bnxt_dl *bp_dl = devlink_priv(dl);
+
+ bp_dl->bp = bp;
+ }
+}
+
+int bnxt_dl_register(struct bnxt *bp);
+void bnxt_dl_unregister(struct bnxt *bp);
+
+#endif /* BNXT_DEVLINK_H */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index e75db04..b76849f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -16,6 +16,7 @@
#include "bnxt_hsi.h"
#include "bnxt.h"
#include "bnxt_vfr.h"
+#include "bnxt_devlink.h"
#include "bnxt_tc.h"
#ifdef CONFIG_BNXT_SRIOV
@@ -416,7 +417,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
}
/* Devlink related routines */
-static int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
+int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
{
struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
@@ -424,7 +425,7 @@ static int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
return 0;
}
-static int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
+int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
{
struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
int rc = 0;
@@ -462,52 +463,4 @@ static int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
return rc;
}
-static const struct devlink_ops bnxt_dl_ops = {
- .eswitch_mode_set = bnxt_dl_eswitch_mode_set,
- .eswitch_mode_get = bnxt_dl_eswitch_mode_get
-};
-
-int bnxt_dl_register(struct bnxt *bp)
-{
- struct devlink *dl;
- int rc;
-
- if (!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
- return 0;
-
- if (bp->hwrm_spec_code < 0x10800) {
- netdev_warn(bp->dev, "Firmware does not support SR-IOV E-Switch SWITCHDEV mode.\n");
- return -ENOTSUPP;
- }
-
- dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
- if (!dl) {
- netdev_warn(bp->dev, "devlink_alloc failed");
- return -ENOMEM;
- }
-
- bnxt_link_bp_to_dl(bp, dl);
- bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
- rc = devlink_register(dl, &bp->pdev->dev);
- if (rc) {
- bnxt_link_bp_to_dl(bp, NULL);
- devlink_free(dl);
- netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
- return rc;
- }
-
- return 0;
-}
-
-void bnxt_dl_unregister(struct bnxt *bp)
-{
- struct devlink *dl = bp->dl;
-
- if (!dl)
- return;
-
- devlink_unregister(dl);
- devlink_free(dl);
-}
-
#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
index 7787cd24..fb06bbe 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
@@ -14,31 +14,6 @@
#define MAX_CFA_CODE 65536
-/* Struct to hold housekeeping info needed by devlink interface */
-struct bnxt_dl {
- struct bnxt *bp; /* back ptr to the controlling dev */
-};
-
-static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl)
-{
- return ((struct bnxt_dl *)devlink_priv(dl))->bp;
-}
-
-/* To clear devlink pointer from bp, pass NULL dl */
-static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
-{
- bp->dl = dl;
-
- /* add a back pointer in dl to bp */
- if (dl) {
- struct bnxt_dl *bp_dl = devlink_priv(dl);
-
- bp_dl->bp = bp;
- }
-}
-
-int bnxt_dl_register(struct bnxt *bp);
-void bnxt_dl_unregister(struct bnxt *bp);
void bnxt_vf_reps_destroy(struct bnxt *bp);
void bnxt_vf_reps_close(struct bnxt *bp);
void bnxt_vf_reps_open(struct bnxt *bp);
@@ -53,16 +28,10 @@ static inline u16 bnxt_vf_rep_get_fid(struct net_device *dev)
return bp->pf.vf[vf_rep->vf_idx].fw_fid;
}
-#else
-
-static inline int bnxt_dl_register(struct bnxt *bp)
-{
- return 0;
-}
+int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode);
+int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode);
-static inline void bnxt_dl_unregister(struct bnxt *bp)
-{
-}
+#else
static inline void bnxt_vf_reps_close(struct bnxt *bp)
{
--
2.7.4
^ permalink raw reply related
* [PATCH 7/7] bnxt: Add devlink support for config get/set
From: Steve Lin @ 2017-10-17 20:44 UTC (permalink / raw)
To: netdev; +Cc: jiri, davem, michael.chan, linville, gospo, steven.lin1
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
Implements get and set of configuration parameters using new devlink
config get/set API.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Acked-by: Andy Gospodarek <gospo@broadcom.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 310 +++++++++++++++++++++-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 17 ++
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 100 +++++++
3 files changed, 421 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index f3f6aa8..e247cae 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -14,11 +14,309 @@
#include "bnxt_vfr.h"
#include "bnxt_devlink.h"
-static const struct devlink_ops bnxt_dl_ops = {
+struct bnxt_drv_cfgparam bnxt_drv_cfgparam_list[] = {
+ {DEVLINK_ATTR_PERM_CFG_MAX_NUM_PF_MSIX_VECT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 10, 108},
+ {DEVLINK_ATTR_PERM_CFG_IGNORE_ARI_CAPABILITY, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 164},
+ {DEVLINK_ATTR_PERM_CFG_PME_CAPABILITY_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 166},
+ {DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_BRIDGE_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 269},
+ {DEVLINK_ATTR_PERM_CFG_LLDP_NEAREST_NONTPMR_BRIDGE_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 270},
+ {DEVLINK_ATTR_PERM_CFG_SECURE_NIC_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 162},
+ {DEVLINK_ATTR_PERM_CFG_PHY_SELECT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 329},
+ {DEVLINK_ATTR_PERM_CFG_SRIOV_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_SHARED, 1, 401},
+
+ {DEVLINK_ATTR_PERM_CFG_MBA_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 351},
+ {DEVLINK_ATTR_PERM_CFG_MBA_BOOT_TYPE, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 2, 352},
+ {DEVLINK_ATTR_PERM_CFG_MBA_DELAY_TIME, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 4, 353},
+ {DEVLINK_ATTR_PERM_CFG_MBA_SETUP_HOT_KEY, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 354},
+ {DEVLINK_ATTR_PERM_CFG_MBA_HIDE_SETUP_PROMPT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 355},
+ {DEVLINK_ATTR_PERM_CFG_MBA_VLAN_TAG, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 16, 357},
+ {DEVLINK_ATTR_PERM_CFG_MBA_VLAN_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 358},
+ {DEVLINK_ATTR_PERM_CFG_MBA_LINK_SPEED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 4, 359},
+ {DEVLINK_ATTR_PERM_CFG_MBA_BOOT_RETRY_COUNT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 3, 360},
+ {DEVLINK_ATTR_PERM_CFG_MBA_BOOT_PROTOCOL, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 3, 361},
+ {DEVLINK_ATTR_PERM_CFG_NUM_VF_PER_PF, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 8, 404},
+ {DEVLINK_ATTR_PERM_CFG_MSIX_VECTORS_PER_VF, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 10, 406},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 10, 501},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 10, 502},
+ {DEVLINK_ATTR_PERM_CFG_RDMA_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 506},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_BW_IN_PERCENT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 507},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_BW_RESERVATION_VALID, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 508},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_BW_LIMIT_VALID, BNXT_DRV_PF,
+ BNXT_DRV_APPL_FUNCTION, 1, 509},
+
+ {DEVLINK_ATTR_PERM_CFG_MAGIC_PACKET_WOL_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 1, 152},
+ {DEVLINK_ATTR_PERM_CFG_DCBX_MODE, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 4, 155},
+ {DEVLINK_ATTR_PERM_CFG_MULTIFUNC_MODE, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 5, 157},
+ {DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D0, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 4, 205},
+ {DEVLINK_ATTR_PERM_CFG_EEE_PWR_SAVE_ENABLED, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 1, 208},
+ {DEVLINK_ATTR_PERM_CFG_PRE_OS_LINK_SPEED_D3, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 4, 210},
+ {DEVLINK_ATTR_PERM_CFG_MEDIA_AUTO_DETECT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 1, 213},
+ {DEVLINK_ATTR_PERM_CFG_AUTONEG_PROTOCOL, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 8, 312},
+ {DEVLINK_ATTR_PERM_CFG_NPAR_NUM_PARTITIONS_PER_PORT, BNXT_DRV_PF,
+ BNXT_DRV_APPL_PORT, 8, 503},
+};
+
+#define BNXT_NUM_DRV_CFGPARAM ARRAY_SIZE(bnxt_drv_cfgparam_list)
+
+static int bnxt_nvm_read(struct bnxt *bp, int nvm_param, int idx,
+ void *buf, int size)
+{
+ struct hwrm_nvm_get_variable_input req = {0};
+ void *dest_data_addr = NULL;
+ dma_addr_t dest_data_dma_addr;
+ int rc;
+ int bytesize;
+
+ bytesize = (size + 7) / 8;
+ dest_data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
+ &dest_data_dma_addr, GFP_KERNEL);
+ if (!dest_data_addr) {
+ netdev_err(bp->dev, "dma_alloc_coherent failure\n");
+ return -ENOMEM;
+ }
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
+ req.dest_data_addr = cpu_to_le64(dest_data_dma_addr);
+ req.data_len = cpu_to_le16(size);
+ req.option_num = cpu_to_le16(nvm_param);
+ req.index_0 = cpu_to_le16(idx);
+ if (idx != 0)
+ req.dimensions = cpu_to_le16(1);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+
+ memcpy(buf, dest_data_addr, bytesize);
+
+ dma_free_coherent(&bp->pdev->dev, bytesize, dest_data_addr,
+ dest_data_dma_addr);
+
+ return rc;
+}
+
+static int bnxt_nvm_write(struct bnxt *bp, int nvm_param, int idx,
+ const void *buf, int size)
+{
+ struct hwrm_nvm_set_variable_input req = {0};
+ void *src_data_addr = NULL;
+ dma_addr_t src_data_dma_addr;
+ int rc;
+ int bytesize;
+
+ bytesize = (size + 7) / 8;
+
+ src_data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
+ &src_data_dma_addr, GFP_KERNEL);
+ if (!src_data_addr) {
+ netdev_err(bp->dev, "dma_alloc_coherent failure\n");
+ return -ENOMEM;
+ }
+
+ memcpy(src_data_addr, buf, bytesize);
+
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1);
+ req.src_data_addr = cpu_to_le64(src_data_dma_addr);
+ req.data_len = cpu_to_le16(size);
+ req.option_num = cpu_to_le16(nvm_param);
+ req.index_0 = cpu_to_le16(idx);
+ if (idx != 0)
+ req.dimensions = cpu_to_le16(1);
+
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+
+ dma_free_coherent(&bp->pdev->dev, bytesize, src_data_addr,
+ src_data_dma_addr);
+
+ return 0;
+}
+
+static int bnxt_dl_config_set(struct devlink *devlink,
+ enum devlink_attr attr, u32 value,
+ u8 *restart_reqd)
+{
+ struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
+ int i;
+ int idx = 0;
+ void *data;
+ int ret = 0;
+ u32 bytesize;
+ struct bnxt_drv_cfgparam *entry;
+
+ *restart_reqd = 0;
+
+ /* Find parameter in table */
+ for (i = 0; i < BNXT_NUM_DRV_CFGPARAM; i++) {
+ if (attr == bnxt_drv_cfgparam_list[i].attr) {
+ entry = &bnxt_drv_cfgparam_list[i];
+ break;
+ }
+ }
+
+ /* Not found */
+ if (i == BNXT_NUM_DRV_CFGPARAM)
+ return -EINVAL;
+
+ /* Check to see if this func type can access variable */
+ if (BNXT_PF(bp) && !(entry->func & BNXT_DRV_PF))
+ return -EOPNOTSUPP;
+ if (BNXT_VF(bp) && !(entry->func & BNXT_DRV_VF))
+ return -EOPNOTSUPP;
+
+ /* If parameter is per port or function, compute index */
+ if (entry->appl == BNXT_DRV_APPL_PORT) {
+ idx = bp->pf.port_id;
+ } else if (entry->appl == BNXT_DRV_APPL_FUNCTION) {
+ if (BNXT_PF(bp))
+ idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
+#ifdef CONFIG_BNXT_SRIOV
+ else
+ idx = bp->vf.fw_fid - BNXT_FIRST_VF_FID;
+#endif /* CONFIG_BNXT_SRIOV */
+ }
+
+ bytesize = (entry->bitlength + 7) / 8;
+ data = kmalloc(bytesize, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ if (bytesize == 1) {
+ u8 val8 = (value & 0xff);
+
+ memcpy(data, &val8, sizeof(u8));
+ } else if (bytesize == 2) {
+ u16 val16 = (value & 0xffff);
+
+ memcpy(data, &val16, sizeof(u16));
+ } else {
+ memcpy(data, &value, sizeof(u32));
+ }
+
+ ret = bnxt_nvm_write(bp, entry->nvm_param, idx, data,
+ entry->bitlength);
+
+ /* Restart required for all nvm parameter writes */
+ *restart_reqd = 1;
+
+ kfree(data);
+
+ return ret;
+}
+
+static int bnxt_dl_config_get(struct devlink *devlink,
+ enum devlink_attr attr, u32 *value)
+{
+ struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
+
+ int i;
+ int idx = 0;
+ void *data;
+ int ret = 0;
+ u32 bytesize;
+ struct bnxt_drv_cfgparam *entry;
+
+ /* Find parameter in table */
+ for (i = 0; i < BNXT_NUM_DRV_CFGPARAM; i++) {
+ if (attr == bnxt_drv_cfgparam_list[i].attr) {
+ entry = &bnxt_drv_cfgparam_list[i];
+ break;
+ }
+ }
+
+ /* Not found */
+ if (i == BNXT_NUM_DRV_CFGPARAM)
+ return -EINVAL;
+
+ /* Check to see if this func type can access variable */
+ if (BNXT_PF(bp) && !(entry->func & BNXT_DRV_PF))
+ return -EOPNOTSUPP;
+ if (BNXT_VF(bp) && !(entry->func & BNXT_DRV_VF))
+ return -EOPNOTSUPP;
+
+ /* If parameter is per port or function, compute index */
+ if (entry->appl == BNXT_DRV_APPL_PORT) {
+ idx = bp->pf.port_id;
+ } else if (entry->appl == BNXT_DRV_APPL_FUNCTION) {
+ if (BNXT_PF(bp))
+ idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
+#ifdef CONFIG_BNXT_SRIOV
+ else
+ idx = bp->vf.fw_fid - BNXT_FIRST_VF_FID;
+#endif /* CONFIG_BNXT_SRIOV */
+ }
+
+ /* Allocate space, retrieve value, and copy to result */
+ bytesize = (entry->bitlength + 7) / 8;
+ data = kmalloc(bytesize, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ ret = bnxt_nvm_read(bp, entry->nvm_param, idx, data, entry->bitlength);
+
+ if (ret) {
+ kfree(data);
+ return ret;
+ }
+
+ if (bytesize == 1) {
+ u8 val;
+
+ memcpy(&val, data, sizeof(u8));
+ *value = val;
+ } else if (bytesize == 2) {
+ u16 val;
+
+ memcpy(&val, data, sizeof(u16));
+ *value = val;
+ } else {
+ u32 val;
+
+ memcpy(&val, data, sizeof(u32));
+ *value = val;
+ }
+
+ kfree(data);
+
+ return 0;
+}
+
+static struct devlink_ops bnxt_dl_ops = {
#ifdef CONFIG_BNXT_SRIOV
.eswitch_mode_set = bnxt_dl_eswitch_mode_set,
.eswitch_mode_get = bnxt_dl_eswitch_mode_get,
#endif /* CONFIG_BNXT_SRIOV */
+ .config_get = bnxt_dl_config_get,
+ .config_set = bnxt_dl_config_set,
};
int bnxt_dl_register(struct bnxt *bp)
@@ -26,12 +324,12 @@ int bnxt_dl_register(struct bnxt *bp)
struct devlink *dl;
int rc;
- if (!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
- return 0;
-
- if (bp->hwrm_spec_code < 0x10800) {
+ if ((!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV)) ||
+ bp->hwrm_spec_code < 0x10800) {
+ /* eswitch switchdev mode not supported */
+ bnxt_dl_ops.eswitch_mode_set = NULL;
+ bnxt_dl_ops.eswitch_mode_get = NULL;
netdev_warn(bp->dev, "Firmware does not support SR-IOV E-Switch SWITCHDEV mode.\n");
- return -ENOTSUPP;
}
dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
index e92a35d..ee28890 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
@@ -10,6 +10,23 @@
#ifndef BNXT_DEVLINK_H
#define BNXT_DEVLINK_H
+#define BNXT_DRV_PF 1
+#define BNXT_DRV_VF 2
+
+enum bnxt_drv_appl {
+ BNXT_DRV_APPL_SHARED,
+ BNXT_DRV_APPL_PORT,
+ BNXT_DRV_APPL_FUNCTION
+};
+
+struct bnxt_drv_cfgparam {
+ enum devlink_attr attr;
+ u8 func; /* BNXT_DRV_PF | BNXT_DRV_VF */
+ enum bnxt_drv_appl appl; /* applicability (shared, func, port) */
+ u32 bitlength; /* length, in bits */
+ u32 nvm_param;
+};
+
/* Struct to hold housekeeping info needed by devlink interface */
struct bnxt_dl {
struct bnxt *bp; /* back ptr to the controlling dev */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
index cb04cc7..8c25731 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -5676,6 +5676,106 @@ struct hwrm_nvm_install_update_cmd_err {
u8 unused_0[7];
};
+/* hwrm_nvm_get_variable */
+/* Input (40 bytes) */
+struct hwrm_nvm_get_variable_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 dest_data_addr;
+ __le16 data_len;
+ __le16 option_num;
+ #define NVM_GET_VARIABLE_REQ_OPTION_NUM_RSVD_0 0x0UL
+ #define NVM_GET_VARIABLE_REQ_OPTION_NUM_RSVD_FFFF 0xffffUL
+ __le16 dimensions;
+ __le16 index_0;
+ __le16 index_1;
+ __le16 index_2;
+ __le16 index_3;
+ u8 flags;
+ #define NVM_GET_VARIABLE_REQ_FLAGS_FACTORY_DFLT 0x1UL
+ u8 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_get_variable_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le16 data_len;
+ __le16 option_num;
+ #define NVM_GET_VARIABLE_RESP_OPTION_NUM_RSVD_0 0x0UL
+ #define NVM_GET_VARIABLE_RESP_OPTION_NUM_RSVD_FFFF 0xffffUL
+ u8 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 valid;
+};
+
+/* Command specific Error Codes (8 bytes) */
+struct hwrm_nvm_get_variable_cmd_err {
+ u8 code;
+ #define NVM_GET_VARIABLE_CMD_ERR_CODE_UNKNOWN 0x0UL
+ #define NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST 0x1UL
+ #define NVM_GET_VARIABLE_CMD_ERR_CODE_CORRUPT_VAR 0x2UL
+ #define NVM_GET_VARIABLE_CMD_ERR_CODE_LEN_TOO_SHORT 0x3UL
+ u8 unused_0[7];
+};
+
+/* hwrm_nvm_set_variable */
+/* Input (40 bytes) */
+struct hwrm_nvm_set_variable_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le64 src_data_addr;
+ __le16 data_len;
+ __le16 option_num;
+ #define NVM_SET_VARIABLE_REQ_OPTION_NUM_RSVD_0 0x0UL
+ #define NVM_SET_VARIABLE_REQ_OPTION_NUM_RSVD_FFFF 0xffffUL
+ __le16 dimensions;
+ __le16 index_0;
+ __le16 index_1;
+ __le16 index_2;
+ __le16 index_3;
+ u8 flags;
+ #define NVM_SET_VARIABLE_REQ_FLAGS_FORCE_FLUSH 0x1UL
+ #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_MASK 0xeUL
+ #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_SFT 1
+ #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_NONE (0x0UL << 1)
+ #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1 (0x1UL << 1)
+ #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_LAST \
+ NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1
+ u8 unused_0;
+};
+
+/* Output (16 bytes) */
+struct hwrm_nvm_set_variable_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 unused_0;
+ u8 unused_1;
+ u8 unused_2;
+ u8 unused_3;
+ u8 valid;
+};
+
+/* Command specific Error Codes (8 bytes) */
+struct hwrm_nvm_set_variable_cmd_err {
+ u8 code;
+ #define NVM_SET_VARIABLE_CMD_ERR_CODE_UNKNOWN 0x0UL
+ #define NVM_SET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST 0x1UL
+ #define NVM_SET_VARIABLE_CMD_ERR_CODE_CORRUPT_VAR 0x2UL
+ u8 unused_0[7];
+};
+
/* hwrm_selftest_qlist */
/* Input (16 bytes) */
struct hwrm_selftest_qlist_input {
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 3/3] ipv6: obsolete cached dst when removing them from fib tree
From: Wei Wang @ 2017-10-17 20:48 UTC (permalink / raw)
To: Paolo Abeni, Eric Dumazet, Martin KaFai Lau
Cc: Linux Kernel Network Developers, David S. Miller,
Hannes Frederic Sowa
In-Reply-To: <1508270578.2548.22.camel@redhat.com>
On Tue, Oct 17, 2017 at 1:02 PM, Paolo Abeni <pabeni@redhat.com> wrote:
> On Tue, 2017-10-17 at 11:58 -0700, Wei Wang wrote:
>> On Tue, Oct 17, 2017 at 10:40 AM, Paolo Abeni <pabeni@redhat.com> wrote:
>> > The commit 2b760fcf5cfb ("ipv6: hook up exception table to store
>> > dst cache") partially reverted 1e2ea8ad37be ("ipv6: set
>> > dst.obsolete when a cached route has expired").
>> >
>> > This change brings back the dst obsoleting and push it a step
>> > farther: cached dst are always obsoleted when removed from the
>> > fib tree, and removal by time expiration is now performed
>> > regardless of dst->__refcnt, to be consistent with what we
>> > already do for RTF_GATEWAY dst.
>> >
>> > Fixes: 2b760fcf5cfb ("ipv6: hook up exception table to store dst cache")
>> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>> > ---
>> > net/ipv6/route.c | 13 +++++++++++--
>> > 1 file changed, 11 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/net/ipv6/route.c b/net/ipv6/route.c
>> > index 8b25a31b6b03..fce740049e3e 100644
>> > --- a/net/ipv6/route.c
>> > +++ b/net/ipv6/route.c
>> > @@ -1147,6 +1147,12 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
>> > if (!bucket || !rt6_ex)
>> > return;
>> >
>> > + /* sockets, flow cache, etc. can hold a refence to this dst, be sure
>> > + * they will drop it.
>> > + */
>> > + if (rt6_ex->rt6i)
>> > + rt6_ex->rt6i->dst.obsolete = DST_OBSOLETE_FORCE_CHK;
>> > +
>>
>> Hmm... I don't really think it is needed. rt6 is created with
>> rt6->dst.obsolete set to DST_OBSOLETE_FORCE_CHK. And by the time the
>> above function is called, it should still be that value.
>> Furthermore, the later call rt6_release() calls dst_dev_put() which
>> sets rt6->dst.obsolete to DST_OBSOLETE_DEAD to indicate this route has
>> been removed from the tree.
>
> You are right, this looks as not needed, if we keep the chunck below.
>
>> > net = dev_net(rt6_ex->rt6i->dst.dev);
>> > rt6_ex->rt6i->rt6i_node = NULL;
>> > hlist_del_rcu(&rt6_ex->hlist);
>> > @@ -1575,8 +1581,11 @@ static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
>> > {
>> > struct rt6_info *rt = rt6_ex->rt6i;
>> >
>> > - if (atomic_read(&rt->dst.__refcnt) == 1 &&
>> > - time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
>> > + /* we are pruning and obsoleting the exception route even if others
>> > + * have still reference to it, so that on next dst_check() such
>> > + * reference can be dropped
>> > + */
>> > + if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
>>
>> Why do we want to change this behavior? Before my patch series, cached
>> routes were only deleted from the tree in fib6_age() when
>> rt->dst.__refcnt == 1, isn't it?
>
> yes, but that really looks like a relic from ancient past more than
> something really needed. We already remove from the dst from fib tree
> regardless of the refcnt if the gateway validation fails - a few lines
> below in the same function.
>
> Waiting for __refcnt going down will let the kernel keep the exception
> entry around for much longer - potentially forever, if e.g. we have a
> reference in a socket dst cache and the application stops processing
> packets.
>
True. If the socket is idle and doesn't send/receive packets,
dst_check() won't get triggered and the socket will keep holding
refcnt on the obsolete dst.
> Meanwhile others sockets may grab more references to (and use) the same
> aged-out dst.
>
I don't think other sockets could grab more reference to this dst
because this dst should already be removed from the fib6 tree.
> The commit 1e2ea8ad37be ("ipv6: set dst.obsolete when a cached route
> has expired") was the solution to the above issue prior to the recent
> refactor.
>
I don't really understand how this commit is solving the above issue.
This commit still only ages out cached route if &rt->dst.__refcnt ==
1. So if socket is holding refcnt to this dst and dst_check() is not
getting called, this cached route still won't get deleted.
> Cheers,
>
> Paolo
^ permalink raw reply
* [RFC PATCH next 0/2] Add support for macvlan offload
From: Shannon Nelson @ 2017-10-17 21:18 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher; +Cc: netdev
The XL710 and family was originally designed as a device to support the
growing "cloud" networking needs. With its large number of queues,
filters, VFs, and other features, it can be a very handy device for
sorting traffic in a variety of ways. However, one early design point
was to support macvlan offloads, and this was never really worked out;
as the Intel group knows, this has bothered me for a rather long time.
The original intent was to use a separate VSI for each macvlan offloaded.
This would make multiple queues and various other features available for
the new pseudo-device. Unfortunately, there are 2 problems with this
approach: (1) the interraction between the stack and the driver makes it
hard to figure out which VSI:queue pair to transmit through, and (2) there
are a lot more queues available for offload duties than there are VSIs.
Using a simpler design, we can partition off some of the queues in the
PF's primary VSI and use the XL710's macaddr-to-queue filtering capability
to make a large number of macvlan offload channels available.
This RFC is with code that has been shown to get packets in and out of the
right queues, but has gone through very little testing. In the spirit
of fail fast, I wanted to get this out quickly for comments and get the
rework cycle started.
Shannon Nelson (2):
i40e: add ToQueue specific handling for mac filters
i40e: add support for macvlan hardware offload
drivers/net/ethernet/intel/i40e/i40e.h | 27 ++-
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 15 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 311 ++++++++++++++++++--
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 10 +-
6 files changed, 327 insertions(+), 41 deletions(-)
^ permalink raw reply
* [RFC PATCH next 1/2] i40e: add ToQueue specific handling for mac filters
From: Shannon Nelson @ 2017-10-17 21:18 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher; +Cc: netdev
In-Reply-To: <1508275089-430113-1-git-send-email-shannon.nelson@oracle.com>
Add the concept of queue-specific filters to the filter handling. This
will be used in the near future for macvlan offload filters. In
general, filters for standard use will use a queue of 0, which we'll
take to mean the filter applies to the whole VSI. Only the filters for
macvlan offload will use a non-zero queue.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
drivers/net/ethernet/intel/i40e/i40e.h | 17 +++--
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 72 ++++++++++++-------
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 10 ++--
4 files changed, 63 insertions(+), 40 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 18c453a..a187f53 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -539,14 +539,17 @@ struct i40e_pf {
/**
* i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key
* @macaddr: the MAC Address as the base key
+ * @queue: if non-zero, the queue to receive packets with this mac address
*
* Simply copies the address and returns it as a u64 for hashing
**/
-static inline u64 i40e_addr_to_hkey(const u8 *macaddr)
+static inline u64 i40e_addr_to_hkey(const u8 *macaddr, u16 queue)
{
u64 key = 0;
+ u16 *k = (u16 *)&key;
ether_addr_copy((u8 *)&key, macaddr);
+ k[3] = queue;
return key;
}
@@ -563,6 +566,7 @@ struct i40e_mac_filter {
u8 macaddr[ETH_ALEN];
#define I40E_VLAN_ANY -1
s16 vlan;
+ u16 queue;
enum i40e_filter_state state;
};
@@ -892,10 +896,11 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
u32 i40e_get_global_fd_count(struct i40e_pf *pf);
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
void i40e_set_ethtool_ops(struct net_device *netdev);
-struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
- const u8 *macaddr, s16 vlan);
+struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+ s16 vlan, u16 queue);
void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f);
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+ s16 vlan, u16 queue);
int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
u16 uplink, u32 param1);
@@ -971,8 +976,8 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, u16 vid);
struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
- const u8 *macaddr);
-int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
+ const u8 *macaddr, u16 queue);
+int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr, u16 queue);
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 6f2725f..cf173e1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -171,8 +171,8 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
pf->hw.mac.port_addr);
hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
dev_info(&pf->pdev->dev,
- " mac_filter_hash: %pM vid=%d, state %s\n",
- f->macaddr, f->vlan,
+ " mac_filter_hash: %pM vid=%d q=%d, state %s\n",
+ f->macaddr, f->vlan, f->queue,
i40e_filter_state_string[f->state]);
}
dev_info(&pf->pdev->dev, " active_filters %u, promisc_threshold %u, overflow promisc %s\n",
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 84c5087..e4b8a4b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1114,11 +1114,13 @@ void i40e_update_stats(struct i40e_vsi *vsi)
* @vsi: the VSI to be searched
* @macaddr: the MAC address
* @vlan: the vlan
+ * @queue: the queue
*
* Returns ptr to the filter object or NULL
**/
static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
- const u8 *macaddr, s16 vlan)
+ const u8 *macaddr, s16 vlan,
+ u16 queue)
{
struct i40e_mac_filter *f;
u64 key;
@@ -1126,10 +1128,10 @@ void i40e_update_stats(struct i40e_vsi *vsi)
if (!vsi || !macaddr)
return NULL;
- key = i40e_addr_to_hkey(macaddr);
+ key = i40e_addr_to_hkey(macaddr, queue);
hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
if ((ether_addr_equal(macaddr, f->macaddr)) &&
- (vlan == f->vlan))
+ (vlan == f->vlan) && (queue == f->queue))
return f;
}
return NULL;
@@ -1151,7 +1153,7 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)
if (!vsi || !macaddr)
return NULL;
- key = i40e_addr_to_hkey(macaddr);
+ key = i40e_addr_to_hkey(macaddr, 0);
hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
if ((ether_addr_equal(macaddr, f->macaddr)))
return f;
@@ -1277,7 +1279,8 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
new_vlan = I40E_VLAN_ANY;
/* Create the new filter */
- add_head = i40e_add_filter(vsi, f->macaddr, new_vlan);
+ add_head = i40e_add_filter(vsi, f->macaddr,
+ new_vlan, f->queue);
if (!add_head)
return -ENOMEM;
@@ -1342,14 +1345,15 @@ static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
* @vsi: the VSI to be searched
* @macaddr: the MAC address
* @vlan: the vlan
+ * @queue: if non-zero, the specific queue to receive for this mac address
*
* Returns ptr to the filter object or NULL when no memory available.
*
* NOTE: This function is expected to be called with mac_filter_hash_lock
* being held.
**/
-struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
- const u8 *macaddr, s16 vlan)
+struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+ s16 vlan, u16 queue)
{
struct i40e_mac_filter *f;
u64 key;
@@ -1357,7 +1361,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
if (!vsi || !macaddr)
return NULL;
- f = i40e_find_filter(vsi, macaddr, vlan);
+ f = i40e_find_filter(vsi, macaddr, vlan, queue);
if (!f) {
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
@@ -1371,6 +1375,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
ether_addr_copy(f->macaddr, macaddr);
f->vlan = vlan;
+ f->queue = queue;
/* If we're in overflow promisc mode, set the state directly
* to failed, so we don't bother to try sending the filter
* to the hardware.
@@ -1381,7 +1386,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
f->state = I40E_FILTER_NEW;
INIT_HLIST_NODE(&f->hlist);
- key = i40e_addr_to_hkey(macaddr);
+ key = i40e_addr_to_hkey(macaddr, queue);
hash_add(vsi->mac_filter_hash, &f->hlist, key);
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -1443,6 +1448,7 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
* @vsi: the VSI to be searched
* @macaddr: the MAC address
* @vlan: the VLAN
+ * @queue: if non-zero, the specific queue to receive for this mac address
*
* NOTE: This function is expected to be called with mac_filter_hash_lock
* being held.
@@ -1450,14 +1456,15 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
* instead of list_for_each_entry().
**/
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+ s16 vlan, u16 queue)
{
struct i40e_mac_filter *f;
if (!vsi || !macaddr)
return;
- f = i40e_find_filter(vsi, macaddr, vlan);
+ f = i40e_find_filter(vsi, macaddr, vlan, queue);
__i40e_del_filter(vsi, f);
}
@@ -1465,6 +1472,7 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
* i40e_add_mac_filter - Add a MAC filter for all active VLANs
* @vsi: the VSI to be searched
* @macaddr: the mac address to be filtered
+ * @queue: if non-zero, the target ToQueue
*
* If we're not in VLAN mode, just add the filter to I40E_VLAN_ANY. Otherwise,
* go through all the macvlan filters and add a macvlan filter for each
@@ -1474,7 +1482,7 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
* Returns last filter added on success, else NULL
**/
struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
- const u8 *macaddr)
+ const u8 *macaddr, u16 queue)
{
struct i40e_mac_filter *f, *add = NULL;
struct hlist_node *h;
@@ -1482,15 +1490,15 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
if (vsi->info.pvid)
return i40e_add_filter(vsi, macaddr,
- le16_to_cpu(vsi->info.pvid));
+ le16_to_cpu(vsi->info.pvid), queue);
if (!i40e_is_vsi_in_vlan(vsi))
- return i40e_add_filter(vsi, macaddr, I40E_VLAN_ANY);
+ return i40e_add_filter(vsi, macaddr, I40E_VLAN_ANY, queue);
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
if (f->state == I40E_FILTER_REMOVE)
continue;
- add = i40e_add_filter(vsi, macaddr, f->vlan);
+ add = i40e_add_filter(vsi, macaddr, f->vlan, queue);
if (!add)
return NULL;
}
@@ -1502,13 +1510,14 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
* i40e_del_mac_filter - Remove a MAC filter from all VLANs
* @vsi: the VSI to be searched
* @macaddr: the mac address to be removed
+ * @queue: if non-zero, the target ToQueue
*
* Removes a given MAC address from a VSI regardless of what VLAN it has been
* associated with.
*
* Returns 0 for success, or error
**/
-int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr)
+int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr, u16 queue)
{
struct i40e_mac_filter *f;
struct hlist_node *h;
@@ -1518,7 +1527,8 @@ int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr)
WARN(!spin_is_locked(&vsi->mac_filter_hash_lock),
"Missing mac_filter_hash_lock\n");
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
- if (ether_addr_equal(macaddr, f->macaddr)) {
+ if (ether_addr_equal(macaddr, f->macaddr) &&
+ queue == f->queue) {
__i40e_del_filter(vsi, f);
found = true;
}
@@ -1565,8 +1575,8 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
spin_lock_bh(&vsi->mac_filter_hash_lock);
- i40e_del_mac_filter(vsi, netdev->dev_addr);
- i40e_add_mac_filter(vsi, addr->sa_data);
+ i40e_del_mac_filter(vsi, netdev->dev_addr, 0);
+ i40e_add_mac_filter(vsi, addr->sa_data, 0);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
ether_addr_copy(netdev->dev_addr, addr->sa_data);
if (vsi->type == I40E_VSI_MAIN) {
@@ -1731,7 +1741,7 @@ static int i40e_addr_sync(struct net_device *netdev, const u8 *addr)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
- if (i40e_add_mac_filter(vsi, addr))
+ if (i40e_add_mac_filter(vsi, addr, 0))
return 0;
else
return -ENOMEM;
@@ -1750,7 +1760,7 @@ static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
- i40e_del_mac_filter(vsi, addr);
+ i40e_del_mac_filter(vsi, addr, 0);
return 0;
}
@@ -1793,7 +1803,7 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
struct hlist_node *h;
hlist_for_each_entry_safe(f, h, from, hlist) {
- u64 key = i40e_addr_to_hkey(f->macaddr);
+ u64 key = i40e_addr_to_hkey(f->macaddr, f->queue);
/* Move the element back into MAC filter list*/
hlist_del(&f->hlist);
@@ -2194,7 +2204,15 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
add_list[num_add].vlan_tag =
cpu_to_le16((u16)(new->f->vlan));
}
- add_list[num_add].queue_number = 0;
+
+ if (new->f->queue) {
+ add_list[num_add].queue_number =
+ cpu_to_le16(new->f->queue);
+ cmd_flags |= I40E_AQC_MACVLAN_ADD_TO_QUEUE;
+ } else {
+ add_list[num_add].queue_number = 0;
+ }
+
/* set invalid match method for later detection */
add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;
cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
@@ -2580,7 +2598,7 @@ int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
if (f->state == I40E_FILTER_REMOVE)
continue;
- add_f = i40e_add_filter(vsi, f->macaddr, vid);
+ add_f = i40e_add_filter(vsi, f->macaddr, vid, 0);
if (!add_f) {
dev_info(&vsi->back->pdev->dev,
"Could not add vlan filter %d for %pM\n",
@@ -9772,7 +9790,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
*/
i40e_rm_default_mac_filter(vsi, mac_addr);
spin_lock_bh(&vsi->mac_filter_hash_lock);
- i40e_add_mac_filter(vsi, mac_addr);
+ i40e_add_mac_filter(vsi, mac_addr, 0);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
} else {
/* Relate the VSI_VMDQ name to the VSI_MAIN name. Note that we
@@ -9786,7 +9804,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
random_ether_addr(mac_addr);
spin_lock_bh(&vsi->mac_filter_hash_lock);
- i40e_add_mac_filter(vsi, mac_addr);
+ i40e_add_mac_filter(vsi, mac_addr, 0);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
}
@@ -9805,7 +9823,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
*/
eth_broadcast_addr(broadcast);
spin_lock_bh(&vsi->mac_filter_hash_lock);
- i40e_add_mac_filter(vsi, broadcast);
+ i40e_add_mac_filter(vsi, broadcast, 0);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
ether_addr_copy(netdev->dev_addr, mac_addr);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 0456813..d2ed218 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -709,14 +709,14 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
spin_lock_bh(&vsi->mac_filter_hash_lock);
if (is_valid_ether_addr(vf->default_lan_addr.addr)) {
f = i40e_add_mac_filter(vsi,
- vf->default_lan_addr.addr);
+ vf->default_lan_addr.addr, 0);
if (!f)
dev_info(&pf->pdev->dev,
"Could not add MAC filter %pM for VF %d\n",
vf->default_lan_addr.addr, vf->vf_id);
}
eth_broadcast_addr(broadcast);
- f = i40e_add_mac_filter(vsi, broadcast);
+ f = i40e_add_mac_filter(vsi, broadcast, 0);
if (!f)
dev_info(&pf->pdev->dev,
"Could not allocate VF broadcast filter\n");
@@ -2217,7 +2217,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
f = i40e_find_mac(vsi, al->list[i].addr);
if (!f)
- f = i40e_add_mac_filter(vsi, al->list[i].addr);
+ f = i40e_add_mac_filter(vsi, al->list[i].addr, 0);
if (!f) {
dev_err(&pf->pdev->dev,
@@ -2282,7 +2282,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
spin_lock_bh(&vsi->mac_filter_hash_lock);
/* delete addresses from the list */
for (i = 0; i < al->num_elements; i++)
- if (i40e_del_mac_filter(vsi, al->list[i].addr)) {
+ if (i40e_del_mac_filter(vsi, al->list[i].addr, 0)) {
ret = I40E_ERR_INVALID_MAC_ADDR;
spin_unlock_bh(&vsi->mac_filter_hash_lock);
goto error_param;
@@ -2916,7 +2916,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
/* delete the temporary mac address */
if (!is_zero_ether_addr(vf->default_lan_addr.addr))
- i40e_del_mac_filter(vsi, vf->default_lan_addr.addr);
+ i40e_del_mac_filter(vsi, vf->default_lan_addr.addr, 0);
/* Delete all the filters for this VSI - we're going to kill it
* anyway.
--
1.7.1
^ permalink raw reply related
* [RFC PATCH next 2/2] i40e: add support for macvlan hardware offload
From: Shannon Nelson @ 2017-10-17 21:18 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher; +Cc: netdev
In-Reply-To: <1508275089-430113-1-git-send-email-shannon.nelson@oracle.com>
This patch adds support for macvlan hardware offload (l2-fwd-offload)
feature using the XL710's macvlan-to-queue filtering machanism. These
are most useful for supporting separate mac addresses for Container
virtualization using Docker and similar configurations.
The basic design is to partition off some of the PF's general LAN queues
outside of the standard RSS pool and use them as the offload queues.
This especially makes sense on machines with more than 64 CPUs: since
the RSS pool is limited to a maximum of 64, the queues assigned to the
remaining CPUs essentially go unused. When on a machine with fewer than
64 CPUs, we shrink the RSS pool and use the upper queues for the offload.
If the user has added Flow Director filters, enabling of macvlan offload
is disallowed.
To use this feature, use ethtool to enable l2-fwd-offload
ethtool -K ethX l2-fwd-offload on
When the next macvlan devices are created on ethX, the macvlan driver
will automatically attempt to setup the hardweare offload.
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
drivers/net/ethernet/intel/i40e/i40e.h | 10 +
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 15 ++
drivers/net/ethernet/intel/i40e/i40e_main.c | 239 +++++++++++++++++++++++-
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
4 files changed, 264 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index a187f53..4868ae2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -365,6 +365,10 @@ struct i40e_pf {
u8 atr_sample_rate;
bool wol_en;
+ u16 macvlan_hint;
+ u16 macvlan_used;
+ u16 macvlan_num;
+
struct hlist_head fdir_filter_list;
u16 fdir_pf_active_filters;
unsigned long fd_flush_timestamp;
@@ -712,6 +716,12 @@ struct i40e_netdev_priv {
struct i40e_vsi *vsi;
};
+struct i40e_fwd {
+ struct net_device *vdev;
+ u16 tx_base_queue;
+ /* future expansion here might include number of queues */
+};
+
/* struct that defines an interrupt vector */
struct i40e_q_vector {
struct i40e_vsi *vsi;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index afd3ca8..e1628c1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -3817,6 +3817,13 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
struct i40e_pf *pf = vsi->back;
int ret = -EOPNOTSUPP;
+ if (pf->macvlan_num) {
+ dev_warn(&pf->pdev->dev,
+ "Remove %d remaining macvlan offloads to change filter options\n",
+ pf->macvlan_used);
+ return -EBUSY;
+ }
+
switch (cmd->cmd) {
case ETHTOOL_SRXFH:
ret = i40e_set_rss_hash_opt(pf, cmd);
@@ -3909,6 +3916,14 @@ static int i40e_set_channels(struct net_device *dev,
if (count > i40e_max_channels(vsi))
return -EINVAL;
+ /* verify that macvlan offloads are not in use */
+ if (pf->macvlan_num) {
+ dev_warn(&pf->pdev->dev,
+ "Remove %d remaining macvlan offloads to change channel count\n",
+ pf->macvlan_used);
+ return -EBUSY;
+ }
+
/* verify that the number of channels does not invalidate any current
* flow director rules
*/
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index e4b8a4b..7b26c6f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9221,6 +9221,66 @@ static void i40e_clear_rss_lut(struct i40e_vsi *vsi)
}
/**
+ * i40e_fix_features - fix the proposed netdev feature flags
+ * @netdev: ptr to the netdev being adjusted
+ * @features: the feature set that the stack is suggesting
+ * Note: expects to be called while under rtnl_lock()
+ **/
+static netdev_features_t i40e_fix_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_vsi *vsi = np->vsi;
+
+ /* make sure there are queues to be used for macvlan offload */
+ if (features & NETIF_F_HW_L2FW_DOFFLOAD &&
+ !(netdev->features & NETIF_F_HW_L2FW_DOFFLOAD)) {
+ const u8 drop = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
+ struct i40e_fdir_filter *rule;
+ struct hlist_node *node2;
+ u16 rss, unused;
+
+ /* Find a set of queues to be used for macvlan offload.
+ * If there aren't many queues outside of the RSS set
+ * that could be used for macvlan, try shrinking the
+ * set to free up some queues, after checking if there
+ * are any Flow Director rules we might break.
+ */
+
+ rss = vsi->rss_size;
+ unused = vsi->num_queue_pairs - rss;
+ if (unused < (vsi->rss_size / 2)) {
+ rss = vsi->rss_size / 2;
+ unused = vsi->num_q_vectors - rss;
+ }
+ pf->macvlan_num = unused;
+
+ /* check the flow director rules */
+ hlist_for_each_entry_safe(rule, node2,
+ &pf->fdir_filter_list, fdir_node) {
+ if (rule->dest_ctl != drop && rss <= rule->q_index) {
+ dev_warn(&pf->pdev->dev,
+ "Remove user defined filter %d to enable macvlan offload\n",
+ rule->fd_id);
+ features &= ~NETIF_F_HW_L2FW_DOFFLOAD;
+ pf->macvlan_num = 0;
+ }
+ }
+ } else if (!(features & NETIF_F_HW_L2FW_DOFFLOAD) &&
+ netdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+ if (pf->macvlan_used) {
+ dev_warn(&pf->pdev->dev,
+ "Remove %d remaining macvlan offloads to disable macvlan offload\n",
+ pf->macvlan_used);
+ features |= NETIF_F_HW_L2FW_DOFFLOAD;
+ }
+ }
+
+ return features;
+}
+
+/**
* i40e_set_features - set the netdev feature flags
* @netdev: ptr to the netdev being adjusted
* @features: the feature set that the stack is suggesting
@@ -9247,6 +9307,45 @@ static int i40e_set_features(struct net_device *netdev,
need_reset = i40e_set_ntuple(pf, features);
+ /* keep this section last in this function as it
+ * might take care of the need_reset for the others
+ */
+ if (features & NETIF_F_HW_L2FW_DOFFLOAD &&
+ !(netdev->features & NETIF_F_HW_L2FW_DOFFLOAD)) {
+ /* reserve queues for macvlan use */
+ u16 rss = vsi->num_q_vectors - pf->macvlan_num;
+
+ if (rss != vsi->rss_size) {
+ if (i40e_reconfig_rss_queues(pf, rss))
+ need_reset = false;
+ }
+
+ pf->macvlan_hint = rss;
+ pf->macvlan_used = 0;
+
+ } else if (!(features & NETIF_F_HW_L2FW_DOFFLOAD) &&
+ netdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+ /* return macvlan queues to general use */
+ int num_qs = vsi->rss_size + pf->macvlan_num;
+ int i;
+
+ /* stop the upperdev queues if not already stopped */
+ for (i = vsi->rss_size; i < num_qs; i++) {
+ struct i40e_fwd *fwd = vsi->tx_rings[i]->fwd;
+
+ if (fwd)
+ netif_tx_stop_all_queues(fwd->vdev);
+ }
+
+ /* rebuild the rss layout with the restored queues */
+ if (i40e_reconfig_rss_queues(pf, num_qs))
+ need_reset = false;
+
+ pf->macvlan_hint = 0;
+ pf->macvlan_used = 0;
+ pf->macvlan_num = 0;
+ }
+
if (need_reset)
i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED), true);
@@ -9674,6 +9773,137 @@ static int i40e_xdp(struct net_device *dev,
}
}
+/**
+ * i40e_select_queue - select the Tx queue, watching for macvlan offloads
+ * @dev: netdevice
+ * @skb: packet to be sent
+ * @accel_priv: hint for offloading macvlan
+ * @fallback: alternative function to use if we don't care which Tx
+ **/
+static u16 i40e_select_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ struct i40e_fwd *fwd = accel_priv;
+
+ if (fwd)
+ return fwd->tx_base_queue;
+
+ return fallback(dev, skb);
+}
+
+/**
+ * i40e_fwd_add - add a macvlan offload
+ * @pdev: the lower physical device
+ * @vdev: the upper macvlan device
+ **/
+static void *i40e_fwd_add(struct net_device *pdev, struct net_device *vdev)
+{
+ struct i40e_netdev_priv *np = netdev_priv(pdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_fwd *fwd = NULL;
+ struct i40e_mac_filter *f;
+ int i;
+
+ if (vdev->num_tx_queues != 1 ||
+ vdev->num_rx_queues != vdev->num_tx_queues) {
+ netdev_info(pdev, "Macvlan offload for Rx/Tx single queue only\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!(pf->macvlan_num - pf->macvlan_used)) {
+ netdev_err(pdev, "No macvlan offload slots left\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (i40e_find_mac(vsi, vdev->dev_addr)) {
+ netdev_err(pdev, "MAC address %pM already in use\n",
+ vdev->dev_addr);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* create the fwd struct */
+ fwd = kzalloc(sizeof(*fwd), GFP_KERNEL);
+ if (!fwd)
+ return ERR_PTR(-ENOMEM);
+
+ /* find the next available macvlan queue */
+ if (!pf->macvlan_hint)
+ pf->macvlan_hint = vsi->rss_size;
+ for (i = pf->macvlan_hint; i < vsi->alloc_queue_pairs; i++) {
+ if (!vsi->tx_rings[i]->fwd) {
+ vsi->tx_rings[i]->fwd = fwd;
+
+ fwd->tx_base_queue = i;
+ fwd->vdev = vdev;
+
+ pf->macvlan_hint = i + 1;
+ break;
+ }
+ }
+ if (!fwd->tx_base_queue) {
+ netdev_err(pdev, "No available queue found for macvlan %s\n",
+ vdev->name);
+ goto no_queue;
+ }
+ pf->macvlan_used++;
+
+ /* set the mac address */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ f = i40e_add_mac_filter(vsi, vdev->dev_addr, fwd->tx_base_queue);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+ if (!f) {
+ netdev_err(pdev, "Failed to add macaddr %pM for macvlan %s\n",
+ vdev->dev_addr, vdev->name);
+ goto no_open;
+ }
+
+ netdev_info(pdev, "%s: queue %d for macvlan %s\n",
+ __func__, fwd->tx_base_queue, vdev->name);
+
+ if (netif_running(pdev))
+ netif_tx_start_all_queues(vdev);
+ else
+ netdev_info(pdev, "Macvlan %s offload start pending\n",
+ vdev->name);
+
+ return fwd;
+
+no_open:
+ vsi->tx_rings[fwd->tx_base_queue]->fwd = NULL;
+no_queue:
+ fwd->vdev = NULL;
+ kfree(fwd);
+ return ERR_PTR(-EBUSY);
+}
+
+/**
+ * i40e_fwd_del - remove a macvlan offload
+ * @pdev: the lower physical device
+ * @priv: the private pointer for the offload information
+ **/
+static void i40e_fwd_del(struct net_device *pdev, void *priv)
+{
+ struct i40e_netdev_priv *np = netdev_priv(pdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_fwd *fwd = priv;
+
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_del_mac_filter(vsi, fwd->vdev->dev_addr, fwd->tx_base_queue);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ vsi->tx_rings[fwd->tx_base_queue]->fwd = NULL;
+ fwd->tx_base_queue = 0;
+ fwd->vdev = NULL;
+
+ if (!pf->macvlan_hint || pf->macvlan_hint > fwd->tx_base_queue)
+ pf->macvlan_hint = fwd->tx_base_queue;
+ pf->macvlan_used--;
+
+ kfree(fwd);
+}
+
static const struct net_device_ops i40e_netdev_ops = {
.ndo_open = i40e_open,
.ndo_stop = i40e_close,
@@ -9691,6 +9921,7 @@ static int i40e_xdp(struct net_device *dev,
.ndo_poll_controller = i40e_netpoll,
#endif
.ndo_setup_tc = __i40e_setup_tc,
+ .ndo_fix_features = i40e_fix_features,
.ndo_set_features = i40e_set_features,
.ndo_set_vf_mac = i40e_ndo_set_vf_mac,
.ndo_set_vf_vlan = i40e_ndo_set_vf_port_vlan,
@@ -9707,6 +9938,9 @@ static int i40e_xdp(struct net_device *dev,
.ndo_bridge_getlink = i40e_ndo_bridge_getlink,
.ndo_bridge_setlink = i40e_ndo_bridge_setlink,
.ndo_xdp = i40e_xdp,
+ .ndo_select_queue = i40e_select_queue,
+ .ndo_dfwd_add_station = i40e_fwd_add,
+ .ndo_dfwd_del_station = i40e_fwd_del,
};
/**
@@ -9776,6 +10010,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
if (vsi->type == I40E_VSI_MAIN) {
+ netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
+
SET_NETDEV_DEV(netdev, &pf->pdev->dev);
ether_addr_copy(mac_addr, hw->mac.perm_addr);
/* The following steps are necessary for two reasons. First,
@@ -11209,7 +11445,8 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
/* limit lan qps to the smaller of qps, cpus or msix */
q_max = max_t(int, pf->rss_size_max, num_online_cpus());
q_max = min_t(int, q_max, pf->hw.func_caps.num_tx_qp);
- q_max = min_t(int, q_max, pf->hw.func_caps.num_msix_vectors);
+ q_max = min_t(int, q_max,
+ (pf->hw.func_caps.num_msix_vectors - 1));
pf->num_lan_qps = q_max;
queues_left -= pf->num_lan_qps;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index a4e3e66..8a0ea20 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -363,6 +363,7 @@ struct i40e_ring {
struct device *dev; /* Used for DMA mapping */
struct net_device *netdev; /* netdev ring maps to */
struct bpf_prog *xdp_prog;
+ struct i40e_fwd *fwd; /* macvlan forwarding */
union {
struct i40e_tx_buffer *tx_bi;
struct i40e_rx_buffer *rx_bi;
--
1.7.1
^ permalink raw reply related
* Re: [Intel-wired-lan] [RFC PATCH next 2/2] i40e: add support for macvlan hardware offload
From: Alexander Duyck @ 2017-10-17 21:32 UTC (permalink / raw)
To: Shannon Nelson; +Cc: intel-wired-lan, Jeff Kirsher, Netdev
In-Reply-To: <1508275089-430113-3-git-send-email-shannon.nelson@oracle.com>
On Tue, Oct 17, 2017 at 2:18 PM, Shannon Nelson
<shannon.nelson@oracle.com> wrote:
> This patch adds support for macvlan hardware offload (l2-fwd-offload)
> feature using the XL710's macvlan-to-queue filtering machanism. These
> are most useful for supporting separate mac addresses for Container
> virtualization using Docker and similar configurations.
>
> The basic design is to partition off some of the PF's general LAN queues
> outside of the standard RSS pool and use them as the offload queues.
> This especially makes sense on machines with more than 64 CPUs: since
> the RSS pool is limited to a maximum of 64, the queues assigned to the
> remaining CPUs essentially go unused. When on a machine with fewer than
> 64 CPUs, we shrink the RSS pool and use the upper queues for the offload.
>
> If the user has added Flow Director filters, enabling of macvlan offload
> is disallowed.
>
> To use this feature, use ethtool to enable l2-fwd-offload
> ethtool -K ethX l2-fwd-offload on
> When the next macvlan devices are created on ethX, the macvlan driver
> will automatically attempt to setup the hardweare offload.
>
> Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e.h | 10 +
> drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 15 ++
> drivers/net/ethernet/intel/i40e/i40e_main.c | 239 +++++++++++++++++++++++-
> drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
> 4 files changed, 264 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index a187f53..4868ae2 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -365,6 +365,10 @@ struct i40e_pf {
> u8 atr_sample_rate;
> bool wol_en;
>
> + u16 macvlan_hint;
> + u16 macvlan_used;
> + u16 macvlan_num;
> +
> struct hlist_head fdir_filter_list;
> u16 fdir_pf_active_filters;
> unsigned long fd_flush_timestamp;
> @@ -712,6 +716,12 @@ struct i40e_netdev_priv {
> struct i40e_vsi *vsi;
> };
>
> +struct i40e_fwd {
> + struct net_device *vdev;
> + u16 tx_base_queue;
> + /* future expansion here might include number of queues */
> +};
> +
> /* struct that defines an interrupt vector */
> struct i40e_q_vector {
> struct i40e_vsi *vsi;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index afd3ca8..e1628c1 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -3817,6 +3817,13 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
> struct i40e_pf *pf = vsi->back;
> int ret = -EOPNOTSUPP;
>
> + if (pf->macvlan_num) {
> + dev_warn(&pf->pdev->dev,
> + "Remove %d remaining macvlan offloads to change filter options\n",
> + pf->macvlan_used);
> + return -EBUSY;
> + }
> +
> switch (cmd->cmd) {
> case ETHTOOL_SRXFH:
> ret = i40e_set_rss_hash_opt(pf, cmd);
> @@ -3909,6 +3916,14 @@ static int i40e_set_channels(struct net_device *dev,
> if (count > i40e_max_channels(vsi))
> return -EINVAL;
>
> + /* verify that macvlan offloads are not in use */
> + if (pf->macvlan_num) {
> + dev_warn(&pf->pdev->dev,
> + "Remove %d remaining macvlan offloads to change channel count\n",
> + pf->macvlan_used);
> + return -EBUSY;
> + }
> +
> /* verify that the number of channels does not invalidate any current
> * flow director rules
> */
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index e4b8a4b..7b26c6f 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -9221,6 +9221,66 @@ static void i40e_clear_rss_lut(struct i40e_vsi *vsi)
> }
>
> /**
> + * i40e_fix_features - fix the proposed netdev feature flags
> + * @netdev: ptr to the netdev being adjusted
> + * @features: the feature set that the stack is suggesting
> + * Note: expects to be called while under rtnl_lock()
> + **/
> +static netdev_features_t i40e_fix_features(struct net_device *netdev,
> + netdev_features_t features)
> +{
> + struct i40e_netdev_priv *np = netdev_priv(netdev);
> + struct i40e_pf *pf = np->vsi->back;
> + struct i40e_vsi *vsi = np->vsi;
> +
> + /* make sure there are queues to be used for macvlan offload */
> + if (features & NETIF_F_HW_L2FW_DOFFLOAD &&
> + !(netdev->features & NETIF_F_HW_L2FW_DOFFLOAD)) {
> + const u8 drop = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
> + struct i40e_fdir_filter *rule;
> + struct hlist_node *node2;
> + u16 rss, unused;
> +
> + /* Find a set of queues to be used for macvlan offload.
> + * If there aren't many queues outside of the RSS set
> + * that could be used for macvlan, try shrinking the
> + * set to free up some queues, after checking if there
> + * are any Flow Director rules we might break.
> + */
> +
> + rss = vsi->rss_size;
> + unused = vsi->num_queue_pairs - rss;
> + if (unused < (vsi->rss_size / 2)) {
> + rss = vsi->rss_size / 2;
> + unused = vsi->num_q_vectors - rss;
> + }
> + pf->macvlan_num = unused;
> +
> + /* check the flow director rules */
> + hlist_for_each_entry_safe(rule, node2,
> + &pf->fdir_filter_list, fdir_node) {
> + if (rule->dest_ctl != drop && rss <= rule->q_index) {
> + dev_warn(&pf->pdev->dev,
> + "Remove user defined filter %d to enable macvlan offload\n",
> + rule->fd_id);
> + features &= ~NETIF_F_HW_L2FW_DOFFLOAD;
> + pf->macvlan_num = 0;
> + }
> + }
> + } else if (!(features & NETIF_F_HW_L2FW_DOFFLOAD) &&
> + netdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
> + if (pf->macvlan_used) {
> + dev_warn(&pf->pdev->dev,
> + "Remove %d remaining macvlan offloads to disable macvlan offload\n",
> + pf->macvlan_used);
> + features |= NETIF_F_HW_L2FW_DOFFLOAD;
> + }
> + }
> +
> + return features;
> +}
> +
> +/**
> * i40e_set_features - set the netdev feature flags
> * @netdev: ptr to the netdev being adjusted
> * @features: the feature set that the stack is suggesting
> @@ -9247,6 +9307,45 @@ static int i40e_set_features(struct net_device *netdev,
>
> need_reset = i40e_set_ntuple(pf, features);
>
> + /* keep this section last in this function as it
> + * might take care of the need_reset for the others
> + */
> + if (features & NETIF_F_HW_L2FW_DOFFLOAD &&
> + !(netdev->features & NETIF_F_HW_L2FW_DOFFLOAD)) {
> + /* reserve queues for macvlan use */
> + u16 rss = vsi->num_q_vectors - pf->macvlan_num;
> +
> + if (rss != vsi->rss_size) {
> + if (i40e_reconfig_rss_queues(pf, rss))
> + need_reset = false;
> + }
> +
> + pf->macvlan_hint = rss;
> + pf->macvlan_used = 0;
> +
> + } else if (!(features & NETIF_F_HW_L2FW_DOFFLOAD) &&
> + netdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
> + /* return macvlan queues to general use */
> + int num_qs = vsi->rss_size + pf->macvlan_num;
> + int i;
> +
> + /* stop the upperdev queues if not already stopped */
> + for (i = vsi->rss_size; i < num_qs; i++) {
> + struct i40e_fwd *fwd = vsi->tx_rings[i]->fwd;
> +
> + if (fwd)
> + netif_tx_stop_all_queues(fwd->vdev);
> + }
> +
> + /* rebuild the rss layout with the restored queues */
> + if (i40e_reconfig_rss_queues(pf, num_qs))
> + need_reset = false;
> +
> + pf->macvlan_hint = 0;
> + pf->macvlan_used = 0;
> + pf->macvlan_num = 0;
> + }
> +
> if (need_reset)
> i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED), true);
>
> @@ -9674,6 +9773,137 @@ static int i40e_xdp(struct net_device *dev,
> }
> }
>
> +/**
> + * i40e_select_queue - select the Tx queue, watching for macvlan offloads
> + * @dev: netdevice
> + * @skb: packet to be sent
> + * @accel_priv: hint for offloading macvlan
> + * @fallback: alternative function to use if we don't care which Tx
> + **/
> +static u16 i40e_select_queue(struct net_device *dev, struct sk_buff *skb,
> + void *accel_priv, select_queue_fallback_t fallback)
> +{
> + struct i40e_fwd *fwd = accel_priv;
> +
> + if (fwd)
> + return fwd->tx_base_queue;
> +
> + return fallback(dev, skb);
> +}
> +
So the select_queue function being needed is the deal breaker on all
of this as far as I am concerned. We aren't allowed to use it under
other cases so why should macvlan be an exception to the rule?
I think we should probably look at a different approach for this. For
example why is it we need to use a different transmit path for a
macvlan packet vs any other packet? On the Rx side we get the
advantage of avoiding the software hashing and demux. What do we get
for reserving queues for transmit?
My plan for this is to go back and "fix" ixgbe so we can get it away
from having to use the select_queue call for the macvlan offload and
then maybe look at proving a few select NDO operations for allowing
macvlans that are being offloaded to make specific calls into the
hardware to perform tasks as needed.
- Alex
^ permalink raw reply
* Re: [PATCH net v2 2/2] net: fec: Let fec_ptp have its own interrupt routine
From: Troy Kisky @ 2017-10-17 21:33 UTC (permalink / raw)
To: Andy Duan, shawn.guo@linaro.org, netdev@vger.kernel.org,
davem@davemloft.net
Cc: Fabio Estevam, lznuaa@gmail.com, andrew@lunn.ch
In-Reply-To: <AM4PR0401MB226019650A8FB767B11B8B91FF4F0@AM4PR0401MB2260.eurprd04.prod.outlook.com>
On 10/15/2017 8:41 PM, Andy Duan wrote:
> From: Troy Kisky <troy.kisky@boundarydevices.com> Sent: Saturday, October 14, 2017 10:10 AM
>> This is better for code locality and should slightly speed up normal interrupts.
>>
>> This also allows PPS clock output to start working for i.mx7. This is because
>> i.mx7 was already using the limit of 3 interrupts, and needed another.
>>
>> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
>>
>> ---
>>
>> v2: made this change independent of any devicetree change so that old dtbs
>> continue to work.
>>
>> Continue to register ptp clock if interrupt is not found.
>> ---
>> drivers/net/ethernet/freescale/fec.h | 3 +-
>> drivers/net/ethernet/freescale/fec_main.c | 25 ++++++----
>> drivers/net/ethernet/freescale/fec_ptp.c | 82 ++++++++++++++++++--------
>> -----
>> 3 files changed, 65 insertions(+), 45 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/freescale/fec.h
>> b/drivers/net/ethernet/freescale/fec.h
>> index ede1876a9a19..be56ac1f1ac4 100644
>> --- a/drivers/net/ethernet/freescale/fec.h
>> +++ b/drivers/net/ethernet/freescale/fec.h
>> @@ -582,12 +582,11 @@ struct fec_enet_private {
>> u64 ethtool_stats[0];
>> };
>>
>> -void fec_ptp_init(struct platform_device *pdev);
>> +void fec_ptp_init(struct platform_device *pdev, int irq_index);
>> void fec_ptp_stop(struct platform_device *pdev); void
>> fec_ptp_start_cyclecounter(struct net_device *ndev); int fec_ptp_set(struct
>> net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev,
>> struct ifreq *ifr); -uint fec_ptp_check_pps_event(struct fec_enet_private
>> *fep);
>>
>>
>> /**********************************************************
>> ******************/
>> #endif /* FEC_H */
>> diff --git a/drivers/net/ethernet/freescale/fec_main.c
>> b/drivers/net/ethernet/freescale/fec_main.c
>> index 3dc2d771a222..21afabbc560f 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -1602,10 +1602,6 @@ fec_enet_interrupt(int irq, void *dev_id)
>> ret = IRQ_HANDLED;
>> complete(&fep->mdio_done);
>> }
>> -
>> - if (fep->ptp_clock)
>> - if (fec_ptp_check_pps_event(fep))
>> - ret = IRQ_HANDLED;
>> return ret;
>> }
>>
>> @@ -3325,6 +3321,8 @@ fec_probe(struct platform_device *pdev)
>> struct device_node *np = pdev->dev.of_node, *phy_node;
>> int num_tx_qs;
>> int num_rx_qs;
>> + char irq_name[8];
>> + int irq_cnt;
>>
>> fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
>>
>> @@ -3465,18 +3463,27 @@ fec_probe(struct platform_device *pdev)
>> if (ret)
>> goto failed_reset;
>>
>> + irq_cnt = platform_irq_count(pdev);
>> + if (irq_cnt > FEC_IRQ_NUM)
>> + irq_cnt = FEC_IRQ_NUM; /* last for ptp */
>> + else if (irq_cnt == 2)
>> + irq_cnt = 1; /* last for ptp */
>> + else if (irq_cnt <= 0)
>> + irq_cnt = 1; /* Let the for loop fail */
>
> Don't do like this. Don't suppose pps interrupt is the last one.
I don't. If the pps interrupt is named, the named interrupt will be used. If it is NOT
named, the last interrupt is used, if 2 interrupts, or >3 interrupt are provided.
Otherwise, no pps interrupt is assumed.
Fortunately this seems to be true currently.
> And if irq_cnt is 1 like imx28/imx5x, the patch will break fec interrupt function.
How ? fec_ptp_init will not be called as bufdesc_ex is 0.
Also, if only 1 interrupt is provided, it is assumed there is no unnamed pps interrupt.
>
> I suggest to use .platform_get_irq_byname() to get pps(ptp) interrupt like your v1 logic check.
>
>> +
>> if (fep->bufdesc_ex)
>> - fec_ptp_init(pdev);
>> + fec_ptp_init(pdev, irq_cnt);
>>
>> ret = fec_enet_init(ndev);
>> if (ret)
>> goto failed_init;
>>
>> - for (i = 0; i < FEC_IRQ_NUM; i++) {
>> - irq = platform_get_irq(pdev, i);
>> + for (i = 0; i < irq_cnt; i++) {
>> + sprintf(irq_name, "int%d", i);
>> + irq = platform_get_irq_byname(pdev, irq_name);
>> + if (irq < 0)
>> + irq = platform_get_irq(pdev, i);
>> if (irq < 0) {
>> - if (i)
>> - break;
>> ret = irq;
>> goto failed_irq;
>> }
>> diff --git a/drivers/net/ethernet/freescale/fec_ptp.c
>> b/drivers/net/ethernet/freescale/fec_ptp.c
>> index 6ebad3fac81d..3abeee0d16dd 100644
>> --- a/drivers/net/ethernet/freescale/fec_ptp.c
>> +++ b/drivers/net/ethernet/freescale/fec_ptp.c
>> @@ -549,6 +549,37 @@ static void fec_time_keep(struct work_struct *work)
>> schedule_delayed_work(&fep->time_keep, HZ); }
>>
>> +/* This function checks the pps event and reloads the timer compare
>> +counter. */ static irqreturn_t fec_ptp_interrupt(int irq, void *dev_id)
>> +{
>> + struct net_device *ndev = dev_id;
>> + struct fec_enet_private *fep = netdev_priv(ndev);
>> + u32 val;
>> + u8 channel = fep->pps_channel;
>> + struct ptp_clock_event event;
>> +
>> + val = readl(fep->hwp + FEC_TCSR(channel));
>> + if (val & FEC_T_TF_MASK) {
>> + /* Write the next next compare(not the next according the
>> spec)
>> + * value to the register
>> + */
>> + writel(fep->next_counter, fep->hwp + FEC_TCCR(channel));
>> + do {
>> + writel(val, fep->hwp + FEC_TCSR(channel));
>> + } while (readl(fep->hwp + FEC_TCSR(channel)) &
>> FEC_T_TF_MASK);
>> +
>> + /* Update the counter; */
>> + fep->next_counter = (fep->next_counter + fep-
>>> reload_period) &
>> + fep->cc.mask;
>> +
>> + event.type = PTP_CLOCK_PPS;
>> + ptp_clock_event(fep->ptp_clock, &event);
>> + return IRQ_HANDLED;
>> + }
>> +
>> + return IRQ_NONE;
>> +}
>> +
>> /**
>> * fec_ptp_init
>> * @ndev: The FEC network adapter
>> @@ -558,10 +589,12 @@ static void fec_time_keep(struct work_struct *work)
>> * cyclecounter init routine and exits.
>> */
>>
>> -void fec_ptp_init(struct platform_device *pdev)
>> +void fec_ptp_init(struct platform_device *pdev, int irq_index)
>> {
>> struct net_device *ndev = platform_get_drvdata(pdev);
>> struct fec_enet_private *fep = netdev_priv(ndev);
>> + int irq;
>> + int ret;
>>
>> fep->ptp_caps.owner = THIS_MODULE;
>> snprintf(fep->ptp_caps.name, 16, "fec ptp"); @@ -587,6 +620,20 @@
>> void fec_ptp_init(struct platform_device *pdev)
>>
>> INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep);
>>
>> + irq = platform_get_irq_byname(pdev, "ptp");
>> + if (irq < 0)
>> + irq = platform_get_irq(pdev, irq_index);
>> + /* Failure to get an irq is not fatal,
>> + * only the PTP_CLOCK_PPS clock events should stop
>> + */
>> + if (irq >= 0) {
>> + ret = devm_request_irq(&pdev->dev, irq, fec_ptp_interrupt,
>> + 0, pdev->name, ndev);
>> + if (ret < 0)
>> + dev_warn(&pdev->dev, "request for ptp irq
>> failed(%d)\n",
>> + ret);
>> + }
>> +
>> fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
>> if (IS_ERR(fep->ptp_clock)) {
>> fep->ptp_clock = NULL;
>> @@ -605,36 +652,3 @@ void fec_ptp_stop(struct platform_device *pdev)
>> if (fep->ptp_clock)
>> ptp_clock_unregister(fep->ptp_clock);
>> }
>> -
>> -/**
>> - * fec_ptp_check_pps_event
>> - * @fep: the fec_enet_private structure handle
>> - *
>> - * This function check the pps event and reload the timer compare counter.
>> - */
>> -uint fec_ptp_check_pps_event(struct fec_enet_private *fep) -{
>> - u32 val;
>> - u8 channel = fep->pps_channel;
>> - struct ptp_clock_event event;
>> -
>> - val = readl(fep->hwp + FEC_TCSR(channel));
>> - if (val & FEC_T_TF_MASK) {
>> - /* Write the next next compare(not the next according the
>> spec)
>> - * value to the register
>> - */
>> - writel(fep->next_counter, fep->hwp + FEC_TCCR(channel));
>> - do {
>> - writel(val, fep->hwp + FEC_TCSR(channel));
>> - } while (readl(fep->hwp + FEC_TCSR(channel)) &
>> FEC_T_TF_MASK);
>> -
>> - /* Update the counter; */
>> - fep->next_counter = (fep->next_counter + fep-
>>> reload_period) & fep->cc.mask;
>> -
>> - event.type = PTP_CLOCK_PPS;
>> - ptp_clock_event(fep->ptp_clock, &event);
>> - return 1;
>> - }
>> -
>> - return 0;
>> -}
>> --
>> 2.11.0
>
>
^ permalink raw reply
* Re: [PATCH v3 net-next] tcp: Remove use of daddr_cache in tracepoint
From: Eric Dumazet @ 2017-10-17 21:44 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, xiyou.wangcong
In-Reply-To: <1508270973-23789-1-git-send-email-dsahern@gmail.com>
On Tue, 2017-10-17 at 13:09 -0700, David Ahern wrote:
> Running perf in one window to capture tcp_retransmit_skb tracepoint:
> $ perf record -e tcp:tcp_retransmit_skb -a
>
> And causing a retransmission on an active TCP session (e.g., dropping
> packets in the receiver, changing MTU on the interface to 500 and back
> to 1500) triggers a panic:
> Remove use of ipv6_pinfo in favor of data in sock_common.
>
> Fixes: e086101b150a ("tcp: add a tracepoint for tcp retransmission")
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
Reviewed-by: Eric Dumazet <edumazet@google.com>
Thanks David !
^ permalink raw reply
* Re: [PATCH net-next 3/3] ipv6: obsolete cached dst when removing them from fib tree
From: Martin KaFai Lau @ 2017-10-17 21:52 UTC (permalink / raw)
To: Paolo Abeni
Cc: Wei Wang, Linux Kernel Network Developers, David S. Miller,
Hannes Frederic Sowa
In-Reply-To: <CAEA6p_CMZu-ooO4sKXD3=wg8_wcAB+oZbTujJ4hEDQnjPZRNwg@mail.gmail.com>
On Tue, Oct 17, 2017 at 06:58:23PM +0000, Wei Wang wrote:
> On Tue, Oct 17, 2017 at 10:40 AM, Paolo Abeni <pabeni@redhat.com> wrote:
> > The commit 2b760fcf5cfb ("ipv6: hook up exception table to store
> > dst cache") partially reverted 1e2ea8ad37be ("ipv6: set
> > dst.obsolete when a cached route has expired").
> >
> > This change brings back the dst obsoleting and push it a step
> > farther: cached dst are always obsoleted when removed from the
> > fib tree, and removal by time expiration is now performed
> > regardless of dst->__refcnt, to be consistent with what we
> > already do for RTF_GATEWAY dst.
> >
> > Fixes: 2b760fcf5cfb ("ipv6: hook up exception table to store dst cache")
> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > ---
> > net/ipv6/route.c | 13 +++++++++++--
> > 1 file changed, 11 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> > index 8b25a31b6b03..fce740049e3e 100644
> > --- a/net/ipv6/route.c
> > +++ b/net/ipv6/route.c
> > @@ -1147,6 +1147,12 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
> > if (!bucket || !rt6_ex)
> > return;
> >
> > + /* sockets, flow cache, etc. can hold a refence to this dst, be sure
> > + * they will drop it.
> > + */
> > + if (rt6_ex->rt6i)
> > + rt6_ex->rt6i->dst.obsolete = DST_OBSOLETE_FORCE_CHK;
> > +
>
> Hmm... I don't really think it is needed. rt6 is created with
> rt6->dst.obsolete set to DST_OBSOLETE_FORCE_CHK. And by the time the
> above function is called, it should still be that value.
> Furthermore, the later call rt6_release() calls dst_dev_put() which
> sets rt6->dst.obsolete to DST_OBSOLETE_DEAD to indicate this route has
> been removed from the tree.
>
> > net = dev_net(rt6_ex->rt6i->dst.dev);
> > rt6_ex->rt6i->rt6i_node = NULL;
> > hlist_del_rcu(&rt6_ex->hlist);
> > @@ -1575,8 +1581,11 @@ static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
> > {
> > struct rt6_info *rt = rt6_ex->rt6i;
> >
> > - if (atomic_read(&rt->dst.__refcnt) == 1 &&
> > - time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
> > + /* we are pruning and obsoleting the exception route even if others
> > + * have still reference to it, so that on next dst_check() such
> > + * reference can be dropped
> > + */
> > + if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
>
> Why do we want to change this behavior? Before my patch series, cached
> routes were only deleted from the tree in fib6_age() when
> rt->dst.__refcnt == 1, isn't it?
In the commit 1e2ea8ad37be ("ipv6: set dst.obsolete when a cached route has expired"),
if obsolete is set to DST_OBSOLETE_KILL, why it is not removed from
the tree together?
>
> > RT6_TRACE("aging clone %p\n", rt);
> > rt6_remove_exception(bucket, rt6_ex);
> > return;
> > --
> > 2.13.6
> >
^ permalink raw reply
* Re: [PATCH net-next 2/3] ipv6: start fib6 gc on RTF_CACHE dst creation
From: Martin KaFai Lau @ 2017-10-17 21:53 UTC (permalink / raw)
To: Wei Wang
Cc: Paolo Abeni, Eric Dumazet, Linux Kernel Network Developers,
David S. Miller, Hannes Frederic Sowa
In-Reply-To: <CAEA6p_CKWdf0ZYm-n3kECnLMipEU3v+VVD4JFzHyPtxdBkvxSQ@mail.gmail.com>
On Tue, Oct 17, 2017 at 06:35:13PM +0000, Wei Wang wrote:
> On Tue, Oct 17, 2017 at 10:40 AM, Paolo Abeni <pabeni@redhat.com> wrote:
> > After the commit Fixes: 2b760fcf5cfb ("ipv6: hook up exception
> > table to store dst cache"), the fib6 gc is not started after
> > the creation of a RTF_CACHE via a redirect or pmtu update, since
> > fib6_add() isn't invoked anymore for such dsts.
Nice catch!
Acked-by: Martin KaFai Lau <kafai@fb.com>
> >
> > We need the fib6 gc to run periodically to clean the RTF_CACHE,
> > or the dst will stay there forever.
> >
> > Fix it by explicitly calling fib6_force_start_gc() on successful
> > exception creation. gc_args->more accounting will ensure that
> > the gc timer will run for whatever time needed to properly
> > clean the table.
> >
> > Fixes: 2b760fcf5cfb ("ipv6: hook up exception table to store dst cache")
> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > ---
> Acked-by: Wei Wang <weiwan@google.com>
>
> Totally true. Thanks for catching this.
>
> > net/ipv6/route.c | 4 +++-
> > 1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> > index 5bb53dbd4fd3..8b25a31b6b03 100644
> > --- a/net/ipv6/route.c
> > +++ b/net/ipv6/route.c
> > @@ -1340,8 +1340,10 @@ static int rt6_insert_exception(struct rt6_info *nrt,
> > spin_unlock_bh(&rt6_exception_lock);
> >
> > /* Update fn->fn_sernum to invalidate all cached dst */
> > - if (!err)
> > + if (!err) {
> > fib6_update_sernum(ort);
> > + fib6_force_start_gc(net);
> > + }
> >
> > return err;
> > }
> > --
> > 2.13.6
> >
^ permalink raw reply
* Cycling Enthusiasts List
From: Greg Elmassian @ 2017-10-17 22:02 UTC (permalink / raw)
To: netdev
Hi,
Hope all's well,
Would you be interested in acquiring an email list of “ Cycling Enthusiasts List ” from USA?
Each record in the list contains Contact Name (First, Middle and Last Name), Mailing Address, List type and Opt-in email address.
All the contacts are opt-in verified, 100% permission based and can be used for unlimited multi-channel marketing.
We also have data for:
(1)Motorcycle Owners List (2)RV/Boat Owners List
(3)Camping Enthusiasts (4)Spa and Resort Visitors List
(5)Skiers List (6)Harley Davidson Owners List
(7)Travelers List (8)Health and Fitness Enthusiasts
(9)Sports Enthusiasts List (10)Outdoor /Hiking Enthusiasts List
Let me know if you'd be interested in hearing more about it.
Waiting for your valuable and sincere reply.
Best Regards,
Greg Elmassian
^ permalink raw reply
* [PATCH] net: l2tp: mark expected switch fall-through
From: Gustavo A. R. Silva @ 2017-10-17 22:42 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Notice that in this particular case I replaced the "NOBREAK" comment with
a "fall through" comment, which is what GCC is expecting to find.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
net/l2tp/l2tp_netlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 7135f46..f517942 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -406,7 +406,7 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
if (nla_put_u16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)) ||
nla_put_u16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)))
goto nla_put_failure;
- /* NOBREAK */
+ /* fall through */
case L2TP_ENCAPTYPE_IP:
#if IS_ENABLED(CONFIG_IPV6)
if (np) {
--
2.7.4
^ permalink raw reply related
* Re: using verifier to ensure a BPF program uses certain metadata?
From: Alexei Starovoitov @ 2017-10-17 22:58 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, Daniel Borkmann, linux-wireless
In-Reply-To: <1508139524.10607.25.camel@sipsolutions.net>
On Mon, Oct 16, 2017 at 09:38:44AM +0200, Johannes Berg wrote:
> Hi,
>
> As we discussed in April already (it's really been that long...), I'd
> wanted to allow using BPF to filter wireless monitor frames, to enable
> new use cases and higher performance in monitoring. I have some code,
> at
>
> https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git/log/?h=bpf
bpf bits looks pretty straightforward.
attach looks fine too. I'm assuming there is some rtnl or other lock,
so multiple assigns cannot race?
It's missing query interface though.
Please add support to return prog_id.
> which implements parts of this. It's still missing the TX status path
> and perhaps associated metadata, but that part is easy.
>
> The bigger "problem" is that we're going to be adding support for
> devices that have 802.11->Ethernet conversion already in hardware, and
> in that case the notion that the filter program will get an 802.11
> header to look at is no longer right.
>
> Now, most likely for the actual in-service monitoring we'll actually
> have to reconstitute the 802.11 header on the fly (in pure monitoring
> where nothing else is active, we can just disable the conversion), but
> the filtering shouldn't really be reliant on that, since that's not the
> cheapest thing to do.
>
> The obvious idea around this is to add a metadata field (just a bit
> really), something like "is_data_ethernet", saying that it was both a
> data frame and is already converted to have an Ethernet header.
> However, since these devices don't really exist yet for the vast
> majority of people, I'm a bit afraid that we'll find later a lot of
> code simply ignoring this field and looking at the "802.11" header,
> which is then broken if it encounters an Ethernet header instead.
>
> Are there lies my question: If we added a new callback to
> bpf_verifier_ops (e.g. "post_verifier_check"), to be called after the
> normal verification, and also added a context argument to
> "is_valid_access" (*), we could easily track that this new metadata
> field is accessed, and reject programs that don't access it at all.
>
> Now, I realize that people could trivially just work around this in
> their program if they wanted, but I think most will take the reminder
> and just implement
>
> if (ctx->is_data_ethernet)
> return DROP_FRAME;
>
> instead, since mostly data frames will not be very relevant to them.
>
> What do you think?
sounds fine and considering new verifier ops after Jakub refactoring
a check that is_data_ethernet was accessed would fit nicely.
Without void** hack.
^ permalink raw reply
* Re: [PATCH 0/7] Adding permanent config get/set to devlink
From: Steve Lin @ 2017-10-17 22:58 UTC (permalink / raw)
To: netdev
Cc: Jiri Pirko, David S . Miller, Michael Chan, John Linville,
Andy Gospodarek, Steven Lin
In-Reply-To: <1508273069-40461-1-git-send-email-steven.lin1@broadcom.com>
My apologies - this patchset was intended for net-next; I forgot to
add that to the subject line, though.
Steve
On Tue, Oct 17, 2017 at 4:44 PM, Steve Lin <steven.lin1@broadcom.com> wrote:
> DIFFERENCES FROM RFC:
> Implemented most of the changes suggested by Jiri and others.
> Thanks for the valuable feedback!
>
> Adds a devlink command for getting & setting permanent
> (persistent / NVRAM) device configuration parameters, and
> enumerates the parameters as nested devlink attributes.
>
> bnxt driver patches make use of these new devlink cmds/
> attributes.
>
> Steve Lin (7):
> devlink: Add permanent config parameter get/set operations
> devlink: Adding NPAR permanent config parameters
> devlink: Adding high level dev perm config params
> devlink: Adding perm config of link settings
> devlink: Adding pre-boot permanent config parameters
> bnxt: Move generic devlink code to new file
> bnxt: Add devlink support for config get/set
>
> drivers/net/ethernet/broadcom/bnxt/Makefile | 2 +-
> drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 +
> drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 363 ++++++++++++++++++++++
> drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 56 ++++
> drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 100 ++++++
> drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 53 +---
> drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h | 37 +--
> include/net/devlink.h | 4 +
> include/uapi/linux/devlink.h | 113 +++++++
> net/core/devlink.c | 300 ++++++++++++++++++
> 10 files changed, 944 insertions(+), 85 deletions(-)
> create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
> create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
>
> --
> 2.7.4
>
^ permalink raw reply
* Re: [Intel-wired-lan] [RFC PATCH next 2/2] i40e: add support for macvlan hardware offload
From: Shannon Nelson @ 2017-10-17 23:12 UTC (permalink / raw)
To: Alexander Duyck; +Cc: intel-wired-lan, Jeff Kirsher, Netdev
In-Reply-To: <CAKgT0Uft_kCyct==am7W0TGUo-YzUhSVkJir83uGx_XwMuxsHg@mail.gmail.com>
On 10/17/2017 2:32 PM, Alexander Duyck wrote:
>
> So the select_queue function being needed is the deal breaker on all
> of this as far as I am concerned. We aren't allowed to use it under
> other cases so why should macvlan be an exception to the rule?
I realize that the stack is pretty good at chosing the "right" queue,
which is my understanding as to why we shouldn't use select_queue(), but
it doesn't know how to use the accel_priv context associated with the
macvlan offload.
I saw DaveM's guidance to the HiNIC folks when they tried to add
select_queue(): "do not implement this function unless you absolutely
need to do something custom in your driver". I can see where this might
be the exception.
When originally thinking about how to do this, I wanted to use the
accel_priv as a pointer to the VSI to be used for the offload, then we
could have multiple queues and use all the VSI specific tuning
operations that XL710 has available. It can work when selecting the
queue, but by the time you get to start_xmit(), you no longer have that
context and only have the queue number. You can't do any fancy encoding
in the queue number because the value has to be within
dev->num_tx_queues. Maybe we can add accel_priv to the start_xmit
interface? (I can hear the groans already...)
However... for our case, you might be right anyway. If the stack is
doing its job at keeping the conversation on the one queue/irq/cpu
combination, any Tx following the offloaded Rx might already be headed
for the right Tx queue. I'll check on that.
> I think we should probably look at a different approach for this. For
> example why is it we need to use a different transmit path for a
> macvlan packet vs any other packet? On the Rx side we get the
> advantage of avoiding the software hashing and demux. What do we get
> for reserving queues for transmit?
There are a couple of reasons I can think of to keep the Tx on the
specific queue pair:
- Keep the Tx traffic on the same CPU and irq as the Rx traffic
- Don't let the flow get interrupted, slowed, or otherwise perturbed by
other traffic flows.
- Allow for adding hardware assisted bandwidth constraints to the
offloaded flow without bothering the rest of the NIC's traffic
Are these enough to want to guarantee the Tx queue?
> My plan for this is to go back and "fix" ixgbe so we can get it away
> from having to use the select_queue call for the macvlan offload and
> then maybe look at proving a few select NDO operations for allowing
> macvlans that are being offloaded to make specific calls into the
> hardware to perform tasks as needed.
The ixgbe implementation can certainly be improved. I think its biggest
failing is that the rest of the general traffic gets constrained to a
single queue - no more RSS for load balancing.
sln
^ permalink raw reply
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