* [PATCH net-next v4 2/7] etf: Add skip_sock_check
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
Currently, etf expects a socket with SO_TXTIME option set for each packet
it encounters. So, it will drop all other packets. But, in the future
commits we are planning to add functionality which where tstamp value will
be set by another qdisc. Also, some packets which are generated from within
the kernel (e.g. ICMP packets) do not have any socket associated with them.
So, this commit adds support for skip_sock_check. When this option is set,
etf will skip checking for a socket and other associated options for all
skbs.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
include/uapi/linux/pkt_sched.h | 1 +
net/sched/sch_etf.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 8b2f993cbb77..409d1616472d 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -990,6 +990,7 @@ struct tc_etf_qopt {
__u32 flags;
#define TC_ETF_DEADLINE_MODE_ON BIT(0)
#define TC_ETF_OFFLOAD_ON BIT(1)
+#define TC_ETF_SKIP_SOCK_CHECK BIT(2)
};
enum {
diff --git a/net/sched/sch_etf.c b/net/sched/sch_etf.c
index db0c2ba1d156..cebfb65d8556 100644
--- a/net/sched/sch_etf.c
+++ b/net/sched/sch_etf.c
@@ -22,10 +22,12 @@
#define DEADLINE_MODE_IS_ON(x) ((x)->flags & TC_ETF_DEADLINE_MODE_ON)
#define OFFLOAD_IS_ON(x) ((x)->flags & TC_ETF_OFFLOAD_ON)
+#define SKIP_SOCK_CHECK_IS_SET(x) ((x)->flags & TC_ETF_SKIP_SOCK_CHECK)
struct etf_sched_data {
bool offload;
bool deadline_mode;
+ bool skip_sock_check;
int clockid;
int queue;
s32 delta; /* in ns */
@@ -77,6 +79,9 @@ static bool is_packet_valid(struct Qdisc *sch, struct sk_buff *nskb)
struct sock *sk = nskb->sk;
ktime_t now;
+ if (q->skip_sock_check)
+ goto skip;
+
if (!sk)
return false;
@@ -92,6 +97,7 @@ static bool is_packet_valid(struct Qdisc *sch, struct sk_buff *nskb)
if (sk->sk_txtime_deadline_mode != q->deadline_mode)
return false;
+skip:
now = q->get_time();
if (ktime_before(txtime, now) || ktime_before(txtime, q->last))
return false;
@@ -385,6 +391,7 @@ static int etf_init(struct Qdisc *sch, struct nlattr *opt,
q->clockid = qopt->clockid;
q->offload = OFFLOAD_IS_ON(qopt);
q->deadline_mode = DEADLINE_MODE_IS_ON(qopt);
+ q->skip_sock_check = SKIP_SOCK_CHECK_IS_SET(qopt);
switch (q->clockid) {
case CLOCK_REALTIME:
@@ -473,6 +480,9 @@ static int etf_dump(struct Qdisc *sch, struct sk_buff *skb)
if (q->deadline_mode)
opt.flags |= TC_ETF_DEADLINE_MODE_ON;
+ if (q->skip_sock_check)
+ opt.flags |= TC_ETF_SKIP_SOCK_CHECK;
+
if (nla_put(skb, TCA_ETF_PARMS, sizeof(opt), &opt))
goto nla_put_failure;
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v4 3/7] taprio: calculate cycle_time when schedule is installed
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
cycle time for a particular schedule is calculated only when it is first
installed. So, it makes sense to just calculate it once right after the
'cycle_time' parameter has been parsed and store it in cycle_time.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 29 +++++++++++------------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 9ecfb8f5902a..a41d7d4434ee 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -108,22 +108,6 @@ static void switch_schedules(struct taprio_sched *q,
*admin = NULL;
}
-static ktime_t get_cycle_time(struct sched_gate_list *sched)
-{
- struct sched_entry *entry;
- ktime_t cycle = 0;
-
- if (sched->cycle_time != 0)
- return sched->cycle_time;
-
- list_for_each_entry(entry, &sched->entries, list)
- cycle = ktime_add_ns(cycle, entry->interval);
-
- sched->cycle_time = cycle;
-
- return cycle;
-}
-
static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
@@ -524,6 +508,15 @@ static int parse_taprio_schedule(struct nlattr **tb,
if (err < 0)
return err;
+ if (!new->cycle_time) {
+ struct sched_entry *entry;
+ ktime_t cycle = 0;
+
+ list_for_each_entry(entry, &new->entries, list)
+ cycle = ktime_add_ns(cycle, entry->interval);
+ new->cycle_time = cycle;
+ }
+
return 0;
}
@@ -605,7 +598,7 @@ static int taprio_get_start_time(struct Qdisc *sch,
return 0;
}
- cycle = get_cycle_time(sched);
+ cycle = sched->cycle_time;
/* The qdisc is expected to have at least one sched_entry. Moreover,
* any entry must have 'interval' > 0. Thus if the cycle time is zero,
@@ -632,7 +625,7 @@ static void setup_first_close_time(struct taprio_sched *q,
first = list_first_entry(&sched->entries,
struct sched_entry, list);
- cycle = get_cycle_time(sched);
+ cycle = sched->cycle_time;
/* FIXME: find a better place to do this */
sched->cycle_close_time = ktime_add_ns(base, cycle);
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v4 5/7] taprio: Add support for txtime-assist mode
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
Currently, we are seeing non-critical packets being transmitted outside of
their timeslice. We can confirm that the packets are being dequeued at the
right time. So, the delay is induced in the hardware side. The most likely
reason is the hardware queues are starving the lower priority queues.
In order to improve the performance of taprio, we will be making use of the
txtime feature provided by the ETF qdisc. For all the packets which do not
have the SO_TXTIME option set, taprio will set the transmit timestamp (set
in skb->tstamp) in this mode. TAPrio Qdisc will ensure that the transmit
time for the packet is set to when the gate is open. If SO_TXTIME is set,
the TAPrio qdisc will validate whether the timestamp (in skb->tstamp)
occurs when the gate corresponding to skb's traffic class is open.
Following two parameters added to support this mode:
- flags: used to enable txtime-assist mode. Will also be used to enable
other modes (like hardware offloading) later.
- txtime-delay: This indicates the minimum time it will take for the packet
to hit the wire. This is useful in determining whether we can transmit
the packet in the remaining time if the gate corresponding to the packet is
currently open.
An example configuration for enabling txtime-assist:
tc qdisc replace dev eth0 parent root handle 100 taprio \\
num_tc 3 \\
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \\
queues 1@0 1@0 1@0 \\
base-time 1558653424279842568 \\
sched-entry S 01 300000 \\
sched-entry S 02 300000 \\
sched-entry S 04 400000 \\
flags 0x1 \\
txtime-delay 40000 \\
clockid CLOCK_TAI
tc qdisc replace dev $IFACE parent 100:1 etf skip_sock_check \\
offload delta 200000 clockid CLOCK_TAI
Note that all the traffic classes are mapped to the same queue. This is
only possible in taprio when txtime-assist is enabled. Also, note that the
ETF Qdisc is enabled with offload mode set.
In this mode, if the packet's traffic class is open and the complete packet
can be transmitted, taprio will try to transmit the packet immediately.
This will be done by setting skb->tstamp to current_time + the time delta
indicated in the txtime-delay parameter. This parameter indicates the time
taken (in software) for packet to reach the network adapter.
If the packet cannot be transmitted in the current interval or if the
packet's traffic is not currently transmitting, the skb->tstamp is set to
the next available timestamp value. This is tracked in the next_launchtime
parameter in the struct sched_entry.
The behaviour w.r.t admin and oper schedules is not changed from what is
present in software mode.
The transmit time is already known in advance. So, we do not need the HR
timers to advance the schedule and wakeup the dequeue side of taprio. So,
HR timer won't be run when this mode is enabled.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
include/uapi/linux/pkt_sched.h | 4 +
net/sched/sch_taprio.c | 351 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 338 insertions(+), 17 deletions(-)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 409d1616472d..5fb19046aee5 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -1159,6 +1159,8 @@ enum {
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL]
*/
+#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST 0x1
+
enum {
TCA_TAPRIO_ATTR_UNSPEC,
TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
@@ -1170,6 +1172,8 @@ enum {
TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */
+ TCA_TAPRIO_ATTR_FLAGS, /* u32 */
+ TCA_TAPRIO_ATTR_TXTIME_DELAY, /* s32 */
__TCA_TAPRIO_ATTR_MAX,
};
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 6ef0cc03fdb9..6911f22fd8dc 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -21,12 +21,16 @@
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
+#include <net/sock.h>
static LIST_HEAD(taprio_list);
static DEFINE_SPINLOCK(taprio_list_lock);
#define TAPRIO_ALL_GATES_OPEN -1
+#define FLAGS_VALID(flags) (!((flags) & ~TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST))
+#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
+
struct sched_entry {
struct list_head list;
@@ -35,6 +39,7 @@ struct sched_entry {
* packet leaves after this time.
*/
ktime_t close_time;
+ ktime_t next_txtime;
atomic_t budget;
int index;
u32 gate_mask;
@@ -55,6 +60,7 @@ struct sched_gate_list {
struct taprio_sched {
struct Qdisc **qdiscs;
struct Qdisc *root;
+ u32 flags;
int clockid;
atomic64_t picos_per_byte; /* Using picoseconds because for 10Gbps+
* speeds it's sub-nanoseconds per byte
@@ -68,6 +74,7 @@ struct taprio_sched {
ktime_t (*get_time)(void);
struct hrtimer advance_timer;
struct list_head taprio_list;
+ int txtime_delay;
};
static ktime_t sched_base_time(const struct sched_gate_list *sched)
@@ -108,6 +115,237 @@ static void switch_schedules(struct taprio_sched *q,
*admin = NULL;
}
+/* Get how much time has been already elapsed in the current cycle. */
+static s32 get_cycle_time_elapsed(struct sched_gate_list *sched, ktime_t time)
+{
+ ktime_t time_since_sched_start;
+ s32 time_elapsed;
+
+ time_since_sched_start = ktime_sub(time, sched->base_time);
+ div_s64_rem(time_since_sched_start, sched->cycle_time, &time_elapsed);
+
+ return time_elapsed;
+}
+
+static ktime_t get_interval_end_time(struct sched_gate_list *sched,
+ struct sched_gate_list *admin,
+ struct sched_entry *entry,
+ ktime_t intv_start)
+{
+ s32 cycle_elapsed = get_cycle_time_elapsed(sched, intv_start);
+ ktime_t intv_end, cycle_ext_end, cycle_end;
+
+ cycle_end = ktime_add_ns(intv_start, sched->cycle_time - cycle_elapsed);
+ intv_end = ktime_add_ns(intv_start, entry->interval);
+ cycle_ext_end = ktime_add(cycle_end, sched->cycle_time_extension);
+
+ if (ktime_before(intv_end, cycle_end))
+ return intv_end;
+ else if (admin && admin != sched &&
+ ktime_after(admin->base_time, cycle_end) &&
+ ktime_before(admin->base_time, cycle_ext_end))
+ return admin->base_time;
+ else
+ return cycle_end;
+}
+
+static int length_to_duration(struct taprio_sched *q, int len)
+{
+ return (len * atomic64_read(&q->picos_per_byte)) / 1000;
+}
+
+/* Returns the entry corresponding to next available interval. If
+ * validate_interval is set, it only validates whether the timestamp occurs
+ * when the gate corresponding to the skb's traffic class is open.
+ */
+static struct sched_entry *find_entry_to_transmit(struct sk_buff *skb,
+ struct Qdisc *sch,
+ struct sched_gate_list *sched,
+ struct sched_gate_list *admin,
+ ktime_t time,
+ ktime_t *interval_start,
+ ktime_t *interval_end,
+ bool validate_interval)
+{
+ ktime_t curr_intv_start, curr_intv_end, cycle_end, packet_transmit_time;
+ ktime_t earliest_txtime = KTIME_MAX, txtime, cycle, transmit_end_time;
+ struct sched_entry *entry = NULL, *entry_found = NULL;
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct net_device *dev = qdisc_dev(sch);
+ bool entry_available = false;
+ s32 cycle_elapsed;
+ int tc, n;
+
+ tc = netdev_get_prio_tc_map(dev, skb->priority);
+ packet_transmit_time = length_to_duration(q, qdisc_pkt_len(skb));
+
+ *interval_start = 0;
+ *interval_end = 0;
+
+ if (!sched)
+ return NULL;
+
+ cycle = sched->cycle_time;
+ cycle_elapsed = get_cycle_time_elapsed(sched, time);
+ curr_intv_end = ktime_sub_ns(time, cycle_elapsed);
+ cycle_end = ktime_add_ns(curr_intv_end, cycle);
+
+ list_for_each_entry(entry, &sched->entries, list) {
+ curr_intv_start = curr_intv_end;
+ curr_intv_end = get_interval_end_time(sched, admin, entry,
+ curr_intv_start);
+
+ if (ktime_after(curr_intv_start, cycle_end))
+ break;
+
+ if (!(entry->gate_mask & BIT(tc)) ||
+ packet_transmit_time > entry->interval)
+ continue;
+
+ txtime = entry->next_txtime;
+
+ if (ktime_before(txtime, time) || validate_interval) {
+ transmit_end_time = ktime_add_ns(time, packet_transmit_time);
+ if ((ktime_before(curr_intv_start, time) &&
+ ktime_before(transmit_end_time, curr_intv_end)) ||
+ (ktime_after(curr_intv_start, time) && !validate_interval)) {
+ entry_found = entry;
+ *interval_start = curr_intv_start;
+ *interval_end = curr_intv_end;
+ break;
+ } else if (!entry_available && !validate_interval) {
+ /* Here, we are just trying to find out the
+ * first available interval in the next cycle.
+ */
+ entry_available = 1;
+ entry_found = entry;
+ *interval_start = ktime_add_ns(curr_intv_start, cycle);
+ *interval_end = ktime_add_ns(curr_intv_end, cycle);
+ }
+ } else if (ktime_before(txtime, earliest_txtime) &&
+ !entry_available) {
+ earliest_txtime = txtime;
+ entry_found = entry;
+ n = div_s64(ktime_sub(txtime, curr_intv_start), cycle);
+ *interval_start = ktime_add(curr_intv_start, n * cycle);
+ *interval_end = ktime_add(curr_intv_end, n * cycle);
+ }
+ }
+
+ return entry_found;
+}
+
+static bool is_valid_interval(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct sched_gate_list *sched, *admin;
+ ktime_t interval_start, interval_end;
+ struct sched_entry *entry;
+
+ rcu_read_lock();
+ sched = rcu_dereference(q->oper_sched);
+ admin = rcu_dereference(q->admin_sched);
+
+ entry = find_entry_to_transmit(skb, sch, sched, admin, skb->tstamp,
+ &interval_start, &interval_end, true);
+ rcu_read_unlock();
+
+ return entry;
+}
+
+static ktime_t get_cycle_start(struct sched_gate_list *sched,
+ ktime_t time)
+{
+ ktime_t cycle_elapsed;
+
+ cycle_elapsed = get_cycle_time_elapsed(sched, time);
+
+ return ktime_sub(time, cycle_elapsed);
+}
+
+/* There are a few scenarios where we will have to modify the txtime from
+ * what is read from next_txtime in sched_entry. They are:
+ * 1. If txtime is in the past,
+ * a. The gate for the traffic class is currently open and packet can be
+ * transmitted before it closes, schedule the packet right away.
+ * b. If the gate corresponding to the traffic class is going to open later
+ * in the cycle, set the txtime of packet to the interval start.
+ * 2. If txtime is in the future, there are packets corresponding to the
+ * current traffic class waiting to be transmitted. So, the following
+ * possibilities exist:
+ * a. We can transmit the packet before the window containing the txtime
+ * closes.
+ * b. The window might close before the transmission can be completed
+ * successfully. So, schedule the packet in the next open window.
+ */
+static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
+{
+ ktime_t transmit_end_time, interval_end, interval_start;
+ struct taprio_sched *q = qdisc_priv(sch);
+ struct sched_gate_list *sched, *admin;
+ ktime_t minimum_time, now, txtime;
+ int len, packet_transmit_time;
+ struct sched_entry *entry;
+ bool sched_changed;
+
+ now = q->get_time();
+ minimum_time = ktime_add_ns(now, q->txtime_delay);
+
+ rcu_read_lock();
+ admin = rcu_dereference(q->admin_sched);
+ sched = rcu_dereference(q->oper_sched);
+ if (admin && ktime_after(minimum_time, admin->base_time))
+ switch_schedules(q, &admin, &sched);
+
+ /* Until the schedule starts, all the queues are open */
+ if (!sched || ktime_before(minimum_time, sched->base_time)) {
+ txtime = minimum_time;
+ goto done;
+ }
+
+ len = qdisc_pkt_len(skb);
+ packet_transmit_time = length_to_duration(q, len);
+
+ do {
+ sched_changed = 0;
+
+ entry = find_entry_to_transmit(skb, sch, sched, admin,
+ minimum_time,
+ &interval_start, &interval_end,
+ false);
+ if (!entry) {
+ txtime = 0;
+ goto done;
+ }
+
+ txtime = entry->next_txtime;
+ txtime = max_t(ktime_t, txtime, minimum_time);
+ txtime = max_t(ktime_t, txtime, interval_start);
+
+ if (admin && admin != sched &&
+ ktime_after(txtime, admin->base_time)) {
+ sched = admin;
+ sched_changed = 1;
+ continue;
+ }
+
+ transmit_end_time = ktime_add(txtime, packet_transmit_time);
+ minimum_time = transmit_end_time;
+
+ /* Update the txtime of current entry to the next time it's
+ * interval starts.
+ */
+ if (ktime_after(transmit_end_time, interval_end))
+ entry->next_txtime = ktime_add(interval_start, sched->cycle_time);
+ } while (sched_changed || ktime_after(transmit_end_time, interval_end));
+
+ entry->next_txtime = transmit_end_time;
+
+done:
+ rcu_read_unlock();
+ return txtime;
+}
+
static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
@@ -121,6 +359,15 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (unlikely(!child))
return qdisc_drop(skb, sch, to_free);
+ if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
+ if (!is_valid_interval(skb, sch))
+ return qdisc_drop(skb, sch, to_free);
+ } else if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ skb->tstamp = get_packet_txtime(skb, sch);
+ if (!skb->tstamp)
+ return qdisc_drop(skb, sch, to_free);
+ }
+
qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++;
@@ -156,6 +403,9 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
if (!skb)
continue;
+ if (TXTIME_ASSIST_IS_ENABLED(q->flags))
+ return skb;
+
prio = skb->priority;
tc = netdev_get_prio_tc_map(dev, prio);
@@ -168,11 +418,6 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
return NULL;
}
-static int length_to_duration(struct taprio_sched *q, int len)
-{
- return div_u64(len * atomic64_read(&q->picos_per_byte), 1000);
-}
-
static void taprio_set_budget(struct taprio_sched *q, struct sched_entry *entry)
{
atomic_set(&entry->budget,
@@ -216,6 +461,13 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
if (unlikely(!child))
continue;
+ if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ skb = child->ops->dequeue(child);
+ if (!skb)
+ continue;
+ goto skb_found;
+ }
+
skb = child->ops->peek(child);
if (!skb)
continue;
@@ -246,6 +498,7 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
if (unlikely(!skb))
goto done;
+skb_found:
qdisc_bstats_update(sch, skb);
qdisc_qstats_backlog_dec(sch, skb);
sch->q.qlen--;
@@ -522,7 +775,8 @@ static int parse_taprio_schedule(struct nlattr **tb,
static int taprio_parse_mqprio_opt(struct net_device *dev,
struct tc_mqprio_qopt *qopt,
- struct netlink_ext_ack *extack)
+ struct netlink_ext_ack *extack,
+ u32 taprio_flags)
{
int i, j;
@@ -570,6 +824,9 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
return -EINVAL;
}
+ if (TXTIME_ASSIST_IS_ENABLED(taprio_flags))
+ continue;
+
/* Verify that the offset and counts do not overlap */
for (j = i + 1; j < qopt->num_tc; j++) {
if (last > qopt->offset[j]) {
@@ -700,6 +957,18 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE;
}
+static void setup_txtime(struct taprio_sched *q,
+ struct sched_gate_list *sched, ktime_t base)
+{
+ struct sched_entry *entry;
+ u32 interval = 0;
+
+ list_for_each_entry(entry, &sched->entries, list) {
+ entry->next_txtime = ktime_add_ns(base, interval);
+ interval += entry->interval;
+ }
+}
+
static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
@@ -708,6 +977,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
struct taprio_sched *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
struct tc_mqprio_qopt *mqprio = NULL;
+ u32 taprio_flags = 0;
int i, err, clockid;
unsigned long flags;
ktime_t start;
@@ -720,7 +990,21 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
- err = taprio_parse_mqprio_opt(dev, mqprio, extack);
+ if (tb[TCA_TAPRIO_ATTR_FLAGS]) {
+ taprio_flags = nla_get_u32(tb[TCA_TAPRIO_ATTR_FLAGS]);
+
+ if (q->flags != 0 && q->flags != taprio_flags) {
+ NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
+ return -EOPNOTSUPP;
+ } else if (!FLAGS_VALID(taprio_flags)) {
+ NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
+ return -EINVAL;
+ }
+
+ q->flags = taprio_flags;
+ }
+
+ err = taprio_parse_mqprio_opt(dev, mqprio, extack, taprio_flags);
if (err < 0)
return err;
@@ -779,7 +1063,18 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
/* Protects against enqueue()/dequeue() */
spin_lock_bh(qdisc_lock(sch));
- if (!hrtimer_active(&q->advance_timer)) {
+ if (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]) {
+ if (!TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+ NL_SET_ERR_MSG_MOD(extack, "txtime-delay can only be set when txtime-assist mode is enabled");
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ q->txtime_delay = nla_get_s32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
+ }
+
+ if (!TXTIME_ASSIST_IS_ENABLED(taprio_flags) &&
+ !hrtimer_active(&q->advance_timer)) {
hrtimer_init(&q->advance_timer, q->clockid, HRTIMER_MODE_ABS);
q->advance_timer.function = advance_sched;
}
@@ -822,20 +1117,35 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
goto unlock;
}
- setup_first_close_time(q, new_admin, start);
+ if (TXTIME_ASSIST_IS_ENABLED(taprio_flags)) {
+ setup_txtime(q, new_admin, start);
- /* Protects against advance_sched() */
- spin_lock_irqsave(&q->current_entry_lock, flags);
+ if (!oper) {
+ rcu_assign_pointer(q->oper_sched, new_admin);
+ err = 0;
+ new_admin = NULL;
+ goto unlock;
+ }
+
+ rcu_assign_pointer(q->admin_sched, new_admin);
+ if (admin)
+ call_rcu(&admin->rcu, taprio_free_sched_cb);
+ } else {
+ setup_first_close_time(q, new_admin, start);
- taprio_start_sched(sch, start, new_admin);
+ /* Protects against advance_sched() */
+ spin_lock_irqsave(&q->current_entry_lock, flags);
- rcu_assign_pointer(q->admin_sched, new_admin);
- if (admin)
- call_rcu(&admin->rcu, taprio_free_sched_cb);
- new_admin = NULL;
+ taprio_start_sched(sch, start, new_admin);
- spin_unlock_irqrestore(&q->current_entry_lock, flags);
+ rcu_assign_pointer(q->admin_sched, new_admin);
+ if (admin)
+ call_rcu(&admin->rcu, taprio_free_sched_cb);
+ spin_unlock_irqrestore(&q->current_entry_lock, flags);
+ }
+
+ new_admin = NULL;
err = 0;
unlock:
@@ -1073,6 +1383,13 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
if (nla_put_s32(skb, TCA_TAPRIO_ATTR_SCHED_CLOCKID, q->clockid))
goto options_error;
+ if (q->flags && nla_put_u32(skb, TCA_TAPRIO_ATTR_FLAGS, q->flags))
+ goto options_error;
+
+ if (q->txtime_delay &&
+ nla_put_s32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
+ goto options_error;
+
if (oper && dump_schedule(skb, oper))
goto options_error;
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v4 6/7] taprio: make clock reference conversions easier
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
Later in this series we will need to transform from
CLOCK_MONOTONIC (used in TCP) to the clock reference used in TAPRIO.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 6911f22fd8dc..44540c30887e 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -61,6 +61,7 @@ struct taprio_sched {
struct Qdisc **qdiscs;
struct Qdisc *root;
u32 flags;
+ enum tk_offsets tk_offset;
int clockid;
atomic64_t picos_per_byte; /* Using picoseconds because for 10Gbps+
* speeds it's sub-nanoseconds per byte
@@ -71,7 +72,6 @@ struct taprio_sched {
struct sched_entry __rcu *current_entry;
struct sched_gate_list __rcu *oper_sched;
struct sched_gate_list __rcu *admin_sched;
- ktime_t (*get_time)(void);
struct hrtimer advance_timer;
struct list_head taprio_list;
int txtime_delay;
@@ -85,6 +85,20 @@ static ktime_t sched_base_time(const struct sched_gate_list *sched)
return ns_to_ktime(sched->base_time);
}
+static ktime_t taprio_get_time(struct taprio_sched *q)
+{
+ ktime_t mono = ktime_get();
+
+ switch (q->tk_offset) {
+ case TK_OFFS_MAX:
+ return mono;
+ default:
+ return ktime_mono_to_any(mono, q->tk_offset);
+ }
+
+ return KTIME_MAX;
+}
+
static void taprio_free_sched_cb(struct rcu_head *head)
{
struct sched_gate_list *sched = container_of(head, struct sched_gate_list, rcu);
@@ -288,7 +302,7 @@ static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
struct sched_entry *entry;
bool sched_changed;
- now = q->get_time();
+ now = taprio_get_time(q);
minimum_time = ktime_add_ns(now, q->txtime_delay);
rcu_read_lock();
@@ -479,7 +493,7 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
continue;
len = qdisc_pkt_len(skb);
- guard = ktime_add_ns(q->get_time(),
+ guard = ktime_add_ns(taprio_get_time(q),
length_to_duration(q, len));
/* In the case that there's no gate entry, there's no
@@ -848,7 +862,7 @@ static int taprio_get_start_time(struct Qdisc *sch,
s64 n;
base = sched_base_time(sched);
- now = q->get_time();
+ now = taprio_get_time(q);
if (ktime_after(base, now)) {
*start = base;
@@ -1094,16 +1108,16 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
switch (q->clockid) {
case CLOCK_REALTIME:
- q->get_time = ktime_get_real;
+ q->tk_offset = TK_OFFS_REAL;
break;
case CLOCK_MONOTONIC:
- q->get_time = ktime_get;
+ q->tk_offset = TK_OFFS_MAX;
break;
case CLOCK_BOOTTIME:
- q->get_time = ktime_get_boottime;
+ q->tk_offset = TK_OFFS_BOOT;
break;
case CLOCK_TAI:
- q->get_time = ktime_get_clocktai;
+ q->tk_offset = TK_OFFS_TAI;
break;
default:
NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v4 4/7] taprio: Remove inline directive
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
Remove inline directive from length_to_duration(). We will let the compiler
make the decisions.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index a41d7d4434ee..6ef0cc03fdb9 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -168,7 +168,7 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
return NULL;
}
-static inline int length_to_duration(struct taprio_sched *q, int len)
+static int length_to_duration(struct taprio_sched *q, int len)
{
return div_u64(len * atomic64_read(&q->picos_per_byte), 1000);
}
--
2.7.3
^ permalink raw reply related
* [PATCH net-next v4 7/7] taprio: Adjust timestamps for TCP packets
From: Vedang Patel @ 2019-06-19 17:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, davem, jhs, xiyou.wangcong, jiri,
intel-wired-lan, vinicius.gomes, l, jakub.kicinski, m-karicheri2,
sergei.shtylyov, Vedang Patel
In-Reply-To: <1560966016-28254-1-git-send-email-vedang.patel@intel.com>
When the taprio qdisc is running in "txtime offload" mode, it will
set the launchtime value (in skb->tstamp) for all the packets which do
not have the SO_TXTIME socket option. But, the TCP packets already have
this value set and it indicates the earliest departure time represented
in CLOCK_MONOTONIC clock.
We need to respect the timestamp set by the TCP subsystem. So, convert
this time to the clock which taprio is using and ensure that the packet
is not transmitted before the deadline set by TCP.
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
---
net/sched/sch_taprio.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 44540c30887e..36cad8d68883 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -22,6 +22,7 @@
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
#include <net/sock.h>
+#include <net/tcp.h>
static LIST_HEAD(taprio_list);
static DEFINE_SPINLOCK(taprio_list_lock);
@@ -277,6 +278,41 @@ static ktime_t get_cycle_start(struct sched_gate_list *sched,
return ktime_sub(time, cycle_elapsed);
}
+/* This returns the tstamp value set by TCP in terms of the set clock. */
+static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb)
+{
+ unsigned int offset = skb_network_offset(skb);
+ const struct ipv6hdr *ipv6h;
+ const struct iphdr *iph;
+ struct ipv6hdr _ipv6h;
+
+ ipv6h = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
+ if (!ipv6h)
+ return 0;
+
+ if (ipv6h->version == 4) {
+ iph = (struct iphdr *)ipv6h;
+ offset += iph->ihl * 4;
+
+ /* special-case 6in4 tunnelling, as that is a common way to get
+ * v6 connectivity in the home
+ */
+ if (iph->protocol == IPPROTO_IPV6) {
+ ipv6h = skb_header_pointer(skb, offset,
+ sizeof(_ipv6h), &_ipv6h);
+
+ if (!ipv6h || ipv6h->nexthdr != IPPROTO_TCP)
+ return 0;
+ } else if (iph->protocol != IPPROTO_TCP) {
+ return 0;
+ }
+ } else if (ipv6h->version == 6 && ipv6h->nexthdr != IPPROTO_TCP) {
+ return 0;
+ }
+
+ return ktime_mono_to_any(skb->skb_mstamp_ns, q->tk_offset);
+}
+
/* There are a few scenarios where we will have to modify the txtime from
* what is read from next_txtime in sched_entry. They are:
* 1. If txtime is in the past,
@@ -294,7 +330,7 @@ static ktime_t get_cycle_start(struct sched_gate_list *sched,
*/
static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
{
- ktime_t transmit_end_time, interval_end, interval_start;
+ ktime_t transmit_end_time, interval_end, interval_start, tcp_tstamp;
struct taprio_sched *q = qdisc_priv(sch);
struct sched_gate_list *sched, *admin;
ktime_t minimum_time, now, txtime;
@@ -305,6 +341,9 @@ static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
now = taprio_get_time(q);
minimum_time = ktime_add_ns(now, q->txtime_delay);
+ tcp_tstamp = get_tcp_tstamp(q, skb);
+ minimum_time = max_t(ktime_t, minimum_time, tcp_tstamp);
+
rcu_read_lock();
admin = rcu_dereference(q->admin_sched);
sched = rcu_dereference(q->oper_sched);
--
2.7.3
^ permalink raw reply related
* Re: [PATCH] net/ipv4: fib_trie: Avoid cryptic ternary expressions
From: Nick Desaulniers @ 2019-06-19 17:41 UTC (permalink / raw)
To: Joe Perches, Linus Torvalds
Cc: Matthias Kaehlcke, David S . Miller, Alexey Kuznetsov,
Hideaki YOSHIFUJI, Alexander Duyck, netdev, LKML,
Douglas Anderson, Nathan Huckleberry, clang-built-linux,
Nathan Chancellor
In-Reply-To: <f22006fedb0204ad05858609bc9d3ed0abc6078e.camel@perches.com>
On Wed, Jun 19, 2019 at 2:36 AM Joe Perches <joe@perches.com> wrote:
>
> On Tue, 2019-06-18 at 16:23 -0700, Nick Desaulniers wrote:
> > As a side note, I'm going to try to see if MAINTAINERS and
> > scripts/get_maintainers.pl supports regexes on the commit messages in
> > order to cc our mailing list
>
> Neither. Why should either?
Looks like `K:` is exactly what I'm looking for. Joe, how does:
https://github.com/ClangBuiltLinux/linux/commit/a0a64b8d65c4e7e033f49e48cc610d6e4002927e
look? Is there a maintainer for MAINTAINERS or do I just send the
patch to Linus?
--
Thanks,
~Nick Desaulniers
^ permalink raw reply
* [PATCH net-next] net: sched: act_ctinfo: tidy UAPI definition
From: Kevin Darbyshire-Bryant @ 2019-06-19 17:41 UTC (permalink / raw)
To: netdev; +Cc: Kevin Darbyshire-Bryant
Remove some enums from the UAPI definition that were only used
internally and are NOT part of the UAPI.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
include/net/tc_act/tc_ctinfo.h | 5 +++++
include/uapi/linux/tc_act/tc_ctinfo.h | 5 -----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/net/tc_act/tc_ctinfo.h b/include/net/tc_act/tc_ctinfo.h
index d6a688571672..f071c1d70a25 100644
--- a/include/net/tc_act/tc_ctinfo.h
+++ b/include/net/tc_act/tc_ctinfo.h
@@ -23,6 +23,11 @@ struct tcf_ctinfo {
u64 stats_cpmark_set;
};
+enum {
+ CTINFO_MODE_DSCP = BIT(0),
+ CTINFO_MODE_CPMARK = BIT(1)
+};
+
#define to_ctinfo(a) ((struct tcf_ctinfo *)a)
#endif /* __NET_TC_CTINFO_H */
diff --git a/include/uapi/linux/tc_act/tc_ctinfo.h b/include/uapi/linux/tc_act/tc_ctinfo.h
index 32337304fbe5..f5f26d95d0e7 100644
--- a/include/uapi/linux/tc_act/tc_ctinfo.h
+++ b/include/uapi/linux/tc_act/tc_ctinfo.h
@@ -26,9 +26,4 @@ enum {
#define TCA_CTINFO_MAX (__TCA_CTINFO_MAX - 1)
-enum {
- CTINFO_MODE_DSCP = _BITUL(0),
- CTINFO_MODE_CPMARK = _BITUL(1)
-};
-
#endif
--
2.20.1 (Apple Git-117)
^ permalink raw reply related
* Re: [PATCH][bpf] bpf: verifier: add break statement in switch
From: Andrii Nakryiko @ 2019-06-19 17:43 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
Yonghong Song, Lawrence Brakmo, Networking, bpf, open list,
Kees Cook
In-Reply-To: <20190619160207.GA26960@embeddedor>
On Wed, Jun 19, 2019 at 9:02 AM Gustavo A. R. Silva
<gustavo@embeddedor.com> wrote:
>
> Notice that in this case, it's much clearer to explicitly add a break
> rather than letting the code to fall through. It also avoid potential
> future fall-through warnings[1].
>
> This patch is part of the ongoing efforts to enable
> -Wimplicit-fallthrough.
>
> [1] https://lore.kernel.org/patchwork/patch/1087056/
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
> ---
Acked-by: Andrii Nakryiko <andriin@fb.com>
> kernel/bpf/verifier.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index d2c8a6677ac4..0acf7c569ec6 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5365,6 +5365,7 @@ static int check_return_code(struct bpf_verifier_env *env)
> if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
> env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG)
> range = tnum_range(1, 1);
> + break;
> case BPF_PROG_TYPE_CGROUP_SKB:
> case BPF_PROG_TYPE_CGROUP_SOCK:
> case BPF_PROG_TYPE_SOCK_OPS:
> --
> 2.21.0
>
^ permalink raw reply
* Re: [PATCH][bpf-next] bpf: verifier: add a break statement in switch
From: Andrii Nakryiko @ 2019-06-19 17:44 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
Yonghong Song, Lawrence Brakmo, Networking, bpf, open list,
Kees Cook
In-Reply-To: <20190619160708.GA30356@embeddedor>
On Wed, Jun 19, 2019 at 9:07 AM Gustavo A. R. Silva
<gustavo@embeddedor.com> wrote:
>
> Notice that in this case, it's much clearer to explicitly add a break
> rather than letting the code to fall through. It also avoid potential
> future fall-through warnings[1].
>
> This patch is part of the ongoing efforts to enable
> -Wimplicit-fallthrough.
>
> [1] https://lore.kernel.org/patchwork/patch/1087056/
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
> ---
Acked-by: Andrii Nakryiko <andriin@fb.com>
> kernel/bpf/verifier.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 709ce4cef8ba..0b38cc917d21 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -6066,6 +6066,7 @@ static int check_return_code(struct bpf_verifier_env *env)
> range = tnum_range(0, 3);
> enforce_attach_type_range = tnum_range(2, 3);
> }
> + break;
> case BPF_PROG_TYPE_CGROUP_SOCK:
> case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
> case BPF_PROG_TYPE_SOCK_OPS:
> --
> 2.21.0
>
^ permalink raw reply
* [PATCH] net: fddi: skfp: Include generic PCI definitions from pci_regs.h
From: Puranjay Mohan @ 2019-06-19 17:45 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, netdev, linux-kernel, Bjorn Helgaas,
linux-kernel-mentees
Include the generic PCI definitions from include/uapi/linux/pci_regs.h
change PCI_REV_ID to PCI_REVISION_ID to make it compatible with the
generic define.
This driver uses only one generic PCI define.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
drivers/net/fddi/skfp/drvfbi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/fddi/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
index bdd5700e71fa..38f6d943385d 100644
--- a/drivers/net/fddi/skfp/drvfbi.c
+++ b/drivers/net/fddi/skfp/drvfbi.c
@@ -20,6 +20,7 @@
#include "h/supern_2.h"
#include "h/skfbiinc.h"
#include <linux/bitrev.h>
+#include <uapi/linux/pci_regs.h>
#ifndef lint
static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ;
@@ -127,7 +128,7 @@ static void card_start(struct s_smc *smc)
* at very first before any other initialization functions is
* executed.
*/
- rev_id = inp(PCI_C(PCI_REV_ID)) ;
+ rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
smc->hw.hw_is_64bit = TRUE ;
} else {
--
2.21.0
^ permalink raw reply related
* Re: [PATCH] netfilter: synproxy: fix building syncookie calls
From: Pablo Neira Ayuso @ 2019-06-19 17:46 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jozsef Kadlecsik, Florian Westphal, David S. Miller,
Alexey Kuznetsov, Hideaki YOSHIFUJI, Fernando Fernandez Mancera,
wenxu, netfilter-devel, coreteam, linux-kernel, netdev
In-Reply-To: <20190619125500.1054426-1-arnd@arndb.de>
On Wed, Jun 19, 2019 at 02:54:36PM +0200, Arnd Bergmann wrote:
> When either CONFIG_IPV6 or CONFIG_SYN_COOKIES are disabled, the kernel
> fails to build:
>
> include/linux/netfilter_ipv6.h:180:9: error: implicit declaration of function '__cookie_v6_init_sequence'
> [-Werror,-Wimplicit-function-declaration]
> return __cookie_v6_init_sequence(iph, th, mssp);
> include/linux/netfilter_ipv6.h:194:9: error: implicit declaration of function '__cookie_v6_check'
> [-Werror,-Wimplicit-function-declaration]
> return __cookie_v6_check(iph, th, cookie);
> net/ipv6/netfilter.c:237:26: error: use of undeclared identifier '__cookie_v6_init_sequence'; did you mean 'cookie_init_sequence'?
> net/ipv6/netfilter.c:238:21: error: use of undeclared identifier '__cookie_v6_check'; did you mean '__cookie_v4_check'?
>
> Fix the IS_ENABLED() checks to match the function declaration
> and definitions for these.
I made this:
https://patchwork.ozlabs.org/patch/1117735/
Basically it does:
+#endif
+#if IS_MODULE(CONFIG_IPV6) && defined(CONFIG_SYN_COOKIES)
.cookie_init_sequence = __cookie_v6_init_sequence,
.cookie_v6_check = __cookie_v6_check,
#endif
If CONFIG_IPV6=n, then net/ipv6/netfilter.c is never compiled.
Unless I'm missing anything, I'd prefer my patch because it's a bit
less of ifdefs 8-)
Thanks!
^ permalink raw reply
* [PATCH] net: fddi: skfp: remove generic PCI defines from skfbi.h
From: Puranjay Mohan @ 2019-06-19 17:46 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, netdev, linux-kernel, Bjorn Helgaas,
linux-kernel-mentees
skfbi.h defines its own copies of PCI_COMMAND, PCI_STATUS, etc.
remove them in favor of the generic definitions in
include/uapi/linux/pci_regs.h
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
drivers/net/fddi/skfp/h/skfbi.h | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/drivers/net/fddi/skfp/h/skfbi.h b/drivers/net/fddi/skfp/h/skfbi.h
index 89557457b352..ed144a8e78d1 100644
--- a/drivers/net/fddi/skfp/h/skfbi.h
+++ b/drivers/net/fddi/skfp/h/skfbi.h
@@ -27,29 +27,6 @@
/*
* Configuration Space header
*/
-#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
-#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
-#define PCI_COMMAND 0x04 /* 16 bit Command */
-#define PCI_STATUS 0x06 /* 16 bit Status */
-#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
-#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
-#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
-#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
-#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
-#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
-#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
-#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
-/* Byte 18..2b: Reserved */
-#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
-#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
-#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
-/* Byte 34..33: Reserved */
-#define PCI_CAP_PTR 0x34 /* 8 bit (ML) Capabilities Ptr */
-/* Byte 35..3b: Reserved */
-#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
-#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
-#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
-#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
/* Device Dependent Region */
#define PCI_OUR_REG 0x40 /* 32 bit (DV) Our Register */
#define PCI_OUR_REG_1 0x40 /* 32 bit (ML) Our Register 1 */
--
2.21.0
^ permalink raw reply related
* Re: [PATCH iproute2 v2 2/2] uapi: update if_link.h
From: Stephen Hemminger @ 2019-06-19 17:47 UTC (permalink / raw)
To: Denis Kirjanov, David Ahern; +Cc: netdev, linux-rdma, dledford, mkubecek
In-Reply-To: <20190619141414.4242-2-dkirjanov@suse.com>
On Wed, 19 Jun 2019 16:14:14 +0200
Denis Kirjanov <kda@linux-powerpc.org> wrote:
> update if_link.h to commit 75345f888f700c4ab2448287e35d48c760b202e6
> ("ipoib: show VF broadcast address")
>
> Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
This is only on net-next so the patches should target iproute2-next.
David can update from that.
^ permalink raw reply
* Re: [PATCH] perf cs-etm: Improve completeness for kernel address space
From: Mathieu Poirier @ 2019-06-19 17:49 UTC (permalink / raw)
To: Leo Yan
Cc: Arnaldo Carvalho de Melo, Linux Kernel Mailing List,
linux-arm-kernel, netdev, bpf, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Peter Zijlstra, Suzuki Poulouse, Coresight ML
In-Reply-To: <20190617150024.11787-1-leo.yan@linaro.org>
Hi Leo,
On Mon, 17 Jun 2019 at 09:00, Leo Yan <leo.yan@linaro.org> wrote:
>
> Arm and arm64 architecture reserve some memory regions prior to the
> symbol '_stext' and these memory regions later will be used by device
> module and BPF jit. The current code misses to consider these memory
> regions thus any address in the regions will be taken as user space
> mode, but perf cannot find the corresponding dso with the wrong CPU
> mode so we misses to generate samples for device module and BPF
> related trace data.
>
> This patch parse the link scripts to get the memory size prior to start
> address and reduce this size from 'etmq->etm->kernel_start', then can
> get a fixed up kernel start address which contain memory regions for
> device module and BPF. Finally, cs_etm__cpu_mode() can return right
> mode for these memory regions and perf can successfully generate
> samples.
>
> The reason for parsing the link scripts is Arm architecture changes text
> offset dependent on different platforms, which define multiple text
> offsets in $kernel/arch/arm/Makefile. This offset is decided when build
> kernel and the final value is extended in the link script, so we can
> extract the used value from the link script. We use the same way to
> parse arm64 link script as well. If fail to find the link script, the
> pre start memory size is assumed as zero, in this case it has no any
> change caused with this patch.
>
> Below is detailed info for testing this patch:
>
> - Build LLVM/Clang 8.0 or later version;
>
> - Configure perf with ~/.perfconfig:
>
> root@debian:~# cat ~/.perfconfig
> # this file is auto-generated.
> [llvm]
> clang-path = /mnt/build/llvm-build/build/install/bin/clang
> kbuild-dir = /mnt/linux-kernel/linux-cs-dev/
> clang-opt = "-DLINUX_VERSION_CODE=0x50200 -g"
> dump-obj = true
>
> [trace]
> show_zeros = yes
> show_duration = no
> no_inherit = yes
> show_timestamp = no
> show_arg_names = no
> args_alignment = 40
> show_prefix = yes
>
> - Run 'perf trace' command with eBPF event:
>
> root@debian:~# perf trace -e string \
> -e $kernel/tools/perf/examples/bpf/augmented_raw_syscalls.c
>
> - Read eBPF program memory mapping in kernel:
>
> root@debian:~# echo 1 > /proc/sys/net/core/bpf_jit_kallsyms
> root@debian:~# cat /proc/kallsyms | grep -E "bpf_prog_.+_sys_[enter|exit]"
> ffff000000086a84 t bpf_prog_f173133dc38ccf87_sys_enter [bpf]
> ffff000000088618 t bpf_prog_c1bd85c092d6e4aa_sys_exit [bpf]
>
> - Launch any program which accesses file system frequently so can hit
> the system calls trace flow with eBPF event;
>
> - Capture CoreSight trace data with filtering eBPF program:
>
> root@debian:~# perf record -e cs_etm/@20070000.etr/ \
> --filter 'filter 0xffff000000086a84/0x800' -a sleep 5s
>
> - Annotate for symbol 'bpf_prog_f173133dc38ccf87_sys_enter':
>
> root@debian:~# perf report
> Then select 'branches' samples and press 'a' to annotate symbol
> 'bpf_prog_f173133dc38ccf87_sys_enter', press 'P' to print to the
> bpf_prog_f173133dc38ccf87_sys_enter.annotation file:
>
> root@debian:~# cat bpf_prog_f173133dc38ccf87_sys_enter.annotation
>
> bpf_prog_f173133dc38ccf87_sys_enter() bpf_prog_f173133dc38ccf87_sys_enter
> Event: branches
>
> Percent int sys_enter(struct syscall_enter_args *args)
> stp x29, x30, [sp, #-16]!
>
> int key = 0;
> mov x29, sp
>
> augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
> stp x19, x20, [sp, #-16]!
>
> augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
> stp x21, x22, [sp, #-16]!
>
> stp x25, x26, [sp, #-16]!
>
> return bpf_get_current_pid_tgid();
> mov x25, sp
>
> return bpf_get_current_pid_tgid();
> mov x26, #0x0 // #0
>
> sub sp, sp, #0x10
>
> return bpf_map_lookup_elem(pids, &pid) != NULL;
> add x19, x0, #0x0
>
> mov x0, #0x0 // #0
>
> mov x10, #0xfffffffffffffff8 // #-8
>
> if (pid_filter__has(&pids_filtered, getpid()))
> str w0, [x25, x10]
>
> probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
> add x1, x25, #0x0
>
> probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
> mov x10, #0xfffffffffffffff8 // #-8
>
> syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
> add x1, x1, x10
>
> syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
> mov x0, #0xffff8009ffffffff // #-140694538682369
>
> movk x0, #0x6698, lsl #16
>
> movk x0, #0x3e00
>
> mov x10, #0xffffffffffff1040 // #-61376
>
> if (syscall == NULL || !syscall->enabled)
> movk x10, #0x1023, lsl #16
>
> if (syscall == NULL || !syscall->enabled)
> movk x10, #0x0, lsl #32
>
> loop_iter_first()
> 3.69 → blr bpf_prog_f173133dc38ccf87_sys_enter
> loop_iter_first()
> add x7, x0, #0x0
>
> loop_iter_first()
> add x20, x7, #0x0
>
> int size = probe_read_str(&augmented_filename->value, filename_len, filename_arg);
> mov x0, #0x1 // #1
>
> [...]
>
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
> Cc: coresight@lists.linaro.org
> Cc: linux-arm-kernel@lists.infradead.org
> Signed-off-by: Leo Yan <leo.yan@linaro.org>
> ---
> tools/perf/Makefile.config | 24 ++++++++++++++++++++++++
> tools/perf/util/cs-etm.c | 26 +++++++++++++++++++++++++-
> 2 files changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> index 51dd00f65709..4776c2c1fb6d 100644
> --- a/tools/perf/Makefile.config
> +++ b/tools/perf/Makefile.config
> @@ -418,6 +418,30 @@ ifdef CORESIGHT
> endif
> LDFLAGS += $(LIBOPENCSD_LDFLAGS)
> EXTLIBS += $(OPENCSDLIBS)
> + ifneq ($(wildcard $(srctree)/arch/arm64/kernel/vmlinux.lds),)
> + # Extract info from lds:
> + # . = ((((((((0xffffffffffffffff)) - (((1)) << (48)) + 1) + (0)) + (0x08000000))) + (0x08000000))) + 0x00080000;
> + # ARM64_PRE_START_SIZE := (0x08000000 + 0x08000000 + 0x00080000)
> + ARM64_PRE_START_SIZE := $(shell egrep ' \. \= \({8}0x[0-9a-fA-F]+\){2}' \
> + $(srctree)/arch/arm64/kernel/vmlinux.lds | \
> + sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
> + awk -F' ' '{print "("$$6 "+" $$7 "+" $$8")"}' 2>/dev/null)
> + else
> + ARM64_PRE_START_SIZE := 0
> + endif
> + CFLAGS += -DARM64_PRE_START_SIZE="$(ARM64_PRE_START_SIZE)"
> + ifneq ($(wildcard $(srctree)/arch/arm/kernel/vmlinux.lds),)
> + # Extract info from lds:
> + # . = ((0xC0000000)) + 0x00208000;
> + # ARM_PRE_START_SIZE := 0x00208000
> + ARM_PRE_START_SIZE := $(shell egrep ' \. \= \({2}0x[0-9a-fA-F]+\){2}' \
> + $(srctree)/arch/arm/kernel/vmlinux.lds | \
> + sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
> + awk -F' ' '{print "("$$2")"}' 2>/dev/null)
> + else
> + ARM_PRE_START_SIZE := 0
> + endif
> + CFLAGS += -DARM_PRE_START_SIZE="$(ARM_PRE_START_SIZE)"
> $(call detected,CONFIG_LIBOPENCSD)
> ifdef CSTRACE_RAW
> CFLAGS += -DCS_DEBUG_RAW
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index 0c7776b51045..ae831f836c70 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -613,10 +613,34 @@ static void cs_etm__free(struct perf_session *session)
> static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
> {
> struct machine *machine;
> + u64 fixup_kernel_start = 0;
> + const char *arch;
>
> machine = etmq->etm->machine;
> + arch = perf_env__arch(machine->env);
>
> - if (address >= etmq->etm->kernel_start) {
> + /*
> + * Since arm and arm64 specify some memory regions prior to
> + * 'kernel_start', kernel addresses can be less than 'kernel_start'.
> + *
> + * For arm architecture, the 16MB virtual memory space prior to
> + * 'kernel_start' is allocated to device modules, a PMD table if
> + * CONFIG_HIGHMEM is enabled and a PGD table.
> + *
> + * For arm64 architecture, the root PGD table, device module memory
> + * region and BPF jit region are prior to 'kernel_start'.
> + *
> + * To reflect the complete kernel address space, compensate these
> + * pre-defined regions for kernel start address.
> + */
> + if (!strcmp(arch, "arm64"))
> + fixup_kernel_start = etmq->etm->kernel_start -
> + ARM64_PRE_START_SIZE;
> + else if (!strcmp(arch, "arm"))
> + fixup_kernel_start = etmq->etm->kernel_start -
> + ARM_PRE_START_SIZE;
I will test your work but from a quick look wouldn't it be better to
have a single define name here? From looking at the modifications you
did to Makefile.config there doesn't seem to be a reason to have two.
Thanks,
Mathieu
> +
> + if (address >= fixup_kernel_start) {
> if (machine__is_host(machine))
> return PERF_RECORD_MISC_KERNEL;
> else
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH net] ipv6: Default fib6_type to RTN_UNICAST when not set
From: David Ahern @ 2019-06-19 17:50 UTC (permalink / raw)
To: davem; +Cc: netdev, David Ahern
From: David Ahern <dsahern@gmail.com>
A user reported that routes are getting installed with type 0 (RTN_UNSPEC)
where before the routes were RTN_UNICAST. One example is from accel-ppp
which apparently still uses the ioctl interface and does not set
rtmsg_type. Another is the netlink interface where ipv6 does not require
rtm_type to be set (v4 does). Prior to the commit in the Fixes tag the
ipv6 stack converted type 0 to RTN_UNICAST, so restore that behavior.
Fixes: e8478e80e5a7 ("net/ipv6: Save route type in rt6_info")
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv6/route.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0f60eb3a2873..11ad62effd56 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3184,7 +3184,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
rt->fib6_table = table;
rt->fib6_metric = cfg->fc_metric;
- rt->fib6_type = cfg->fc_type;
+ rt->fib6_type = cfg->fc_type ? : RTN_UNICAST;
rt->fib6_flags = cfg->fc_flags & ~RTF_GATEWAY;
ipv6_addr_prefix(&rt->fib6_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
--
2.11.0
^ permalink raw reply related
* Re: [PATCH mlx5-next 11/15] RDMA/mlx5: Add vport metadata matching for IB representors
From: Mark Bloch @ 2019-06-19 17:52 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Jianbo Liu, Saeed Mahameed, netdev@vger.kernel.org,
linux-rdma@vger.kernel.org, Roi Dayan
In-Reply-To: <20190619081226.GI11611@mtr-leonro.mtl.com>
On 6/19/19 1:12 AM, Leon Romanovsky wrote:
> On Wed, Jun 19, 2019 at 07:58:51AM +0000, Mark Bloch wrote:
>>
>>
>> On 6/19/2019 00:43, Leon Romanovsky wrote:
>>> On Wed, Jun 19, 2019 at 07:26:54AM +0000, Mark Bloch wrote:
>>>>
>>>>
>>>> On 6/18/2019 23:51, Leon Romanovsky wrote:
>>>>> On Wed, Jun 19, 2019 at 06:40:16AM +0000, Jianbo Liu wrote:
>>>>>> The 06/19/2019 13:04, Leon Romanovsky wrote:
>>>>>>> On Wed, Jun 19, 2019 at 04:44:26AM +0000, Jianbo Liu wrote:
>>>>>>>> The 06/18/2019 18:19, Leon Romanovsky wrote:
>>>>>>>>> On Mon, Jun 17, 2019 at 07:23:30PM +0000, Saeed Mahameed wrote:
>>>>>>>>>> From: Jianbo Liu <jianbol@mellanox.com>
>>>>>>>>>>
>>>>>>>>>> If vport metadata matching is enabled in eswitch, the rule created
>>>>>>>>>> must be changed to match on the metadata, instead of source port.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
>>>>>>>>>> Reviewed-by: Roi Dayan <roid@mellanox.com>
>>>>>>>>>> Reviewed-by: Mark Bloch <markb@mellanox.com>
>>>>>>>>>> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
>>>>>>>>>> ---
>>>>>>>>>> drivers/infiniband/hw/mlx5/ib_rep.c | 11 +++++++
>>>>>>>>>> drivers/infiniband/hw/mlx5/ib_rep.h | 16 ++++++++++
>>>>>>>>>> drivers/infiniband/hw/mlx5/main.c | 45 +++++++++++++++++++++++------
>>>>>>>>>> 3 files changed, 63 insertions(+), 9 deletions(-)
>>>>>>>>>>
>>>>>>>>>> diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c
>>>>>>>>>> index 22e651cb5534..d4ed611de35d 100644
>>>>>>>>>> --- a/drivers/infiniband/hw/mlx5/ib_rep.c
>>>>>>>>>> +++ b/drivers/infiniband/hw/mlx5/ib_rep.c
>>>>>>>>>> @@ -131,6 +131,17 @@ struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport)
>>>>>>>>>> return mlx5_eswitch_vport_rep(esw, vport);
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> +u32 mlx5_ib_eswitch_vport_match_metadata_enabled(struct mlx5_eswitch *esw)
>>>>>>>>>> +{
>>>>>>>>>> + return mlx5_eswitch_vport_match_metadata_enabled(esw);
>>>>>>>>>> +}
>>>>>>>>>> +
>>>>>>>>>> +u32 mlx5_ib_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
>>>>>>>>>> + u16 vport)
>>>>>>>>>> +{
>>>>>>>>>> + return mlx5_eswitch_get_vport_metadata_for_match(esw, vport);
>>>>>>>>>> +}
>>>>>>>>>
>>>>>>>>> 1. There is no need to introduce one line functions, call to that code directly.
>>>>>>>>
>>>>>>>> No. They are in IB, and we don't want them be mixed up by the original
>>>>>>>> functions in eswitch. Please ask Mark more about it.
>>>>>>>
>>>>>>> Please enlighten me.
>>>>>>
>>>>>> It was suggested by Mark in prevouis review.
>>>>>> I think it's because there are in different modules, and better to with
>>>>>> different names, so introduce there extra one line functions.
>>>>>> Please correct me if I'm wrong, Mark...
>>>>>
>>>>> mlx5_ib is full of direct function calls to mlx5_core and it is done on
>>>>> purpose for at least two reasons. First is to control in one place
>>>>> all compilation options and expose proper API interface with and without
>>>>> specific kernel config is on. Second is to emphasize that this is core
>>>>> function and save us time in refactoring and reviewing.
>>>>
>>>> This was done in order to avoid #ifdef CONFIG_MLX5_ESWITCH,
>>>> I want to hide (as much as possible) the interactions with the eswitch level in ib_rep.c/ib_rep.h
>>>> so ib_rep.h will provide the stubs needed in case CONFIG_MLX5_ESWITCH isn't defined.
>>>> (Today include/linux/mlx5/eswitch.h) doesn't provide any stubs, mlx5_eswitch_get_encap_mode()
>>>> should have probably done the same.
>>>
>>> This is exactly the problem, eswitch.h should provide stubs for all
>>> exported functions, so other clients of eswitch won't need to deal with
>>> various unrelated config options.
>>
>> The way it works today, code in drivers/infiniband/hw/mlx5/main.c doesn't call eswitch layer directly
>> but the functions in ib_rep.{c,h} as most often there is additional logic we must do before calling
>> the eswitch layer.
>>
>> If you look at drivers/infiniband/hw/mlx5/Makefile you will see ib_rep is complied only when
>> CONFIG_MLX5_ESWITCH id defined.
>
> This simple patch + cleanup of ib_rep.h will do the trick.
>
> diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
> index 67b9e7ac569a..b917ba28659e 100644
> --- a/drivers/infiniband/hw/mlx5/main.c
> +++ b/drivers/infiniband/hw/mlx5/main.c
> @@ -59,7 +59,9 @@
> #include <linux/in.h>
> #include <linux/etherdevice.h>
> #include "mlx5_ib.h"
> +#if defined(CONFIG_MLX5_ESWITCH)
> #include "ib_rep.h"
> +#endif
> #include "cmd.h"
> #include "srq.h"
> #include <linux/mlx5/fs_helpers.h>
> @@ -6765,6 +6767,7 @@ static const struct mlx5_ib_profile pf_profile = {
> mlx5_ib_stage_delay_drop_cleanup),
> };
>
> +#if defined(CONFIG_MLX5_ESWITCH)
> const struct mlx5_ib_profile uplink_rep_profile = {
> STAGE_CREATE(MLX5_IB_STAGE_INIT,
> mlx5_ib_stage_init_init,
> @@ -6812,6 +6815,7 @@
> const struct mlx5_ib_profile uplink_rep_profile = {
> mlx5_ib_stage_post_ib_reg_umr_init,
> NULL),
> };
>
I really dislike seeing #if defined(CONFIG_MLX5_ESWITCH) inside .c files
and here it's easily avoided so I don't see a reason do it it.
Can this cleanup wait for after this series?
Mark
>>
>> so instead of having to deal with two places that contain stubs, we need to deal with only one (ib_rep.h).
>> For me it makes it easier to follow, but I can adept if you don't like it.
>>
>> Mark
>>
>>>
>>>>
>>>> As my long term goal is to break drivers/infiniband/hw/mlx5/main.c (that file is already 7000 LOC)
>>>> I want to group together stuff in separate files.
>>>
>>> Yes, it is right thing to do.
>>>
>>>>
>>>> If you prefer direct calls that's okay as well.
>>>
>>> Yes, please.
>>>
>>>>
>>>> Mark
>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>>> 2. It should be bool and not u32.
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> --
>>>>>>
>>>>>> --
^ permalink raw reply
* [PATCH net-next] ipv6: Check if route exists before notifying it
From: Ido Schimmel @ 2019-06-19 17:55 UTC (permalink / raw)
To: netdev; +Cc: davem, dsahern, mlxsw, Ido Schimmel
From: Ido Schimmel <idosch@mellanox.com>
When user space sends invalid information in RTA_MULTIPATH, the nexthop
list in ip6_route_multipath_add() is empty and there is no route to
notify.
The code that emits the netlink notifications correctly checks if the
route is not NULL, but I missed that for the in-kernel notifications.
Add the check to avoid NULL pointer dereference [1].
[1]
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 9190 Comm: syz-executor149 Not tainted 5.2.0-rc5+ #38
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:call_fib6_multipath_entry_notifiers+0xd1/0x1a0
net/ipv6/ip6_fib.c:396
Code: 8b b5 30 ff ff ff 48 c7 85 68 ff ff ff 00 00 00 00 48 c7 85 70 ff ff
ff 00 00 00 00 89 45 88 4c 89 e0 48 c1 e8 03 4c 89 65 80 <42> 80 3c 28 00
0f 85 9a 00 00 00 48 b8 00 00 00 00 00 fc ff df 4d
RSP: 0018:ffff88809788f2c0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 1ffff11012f11e59 RCX: 00000000ffffffff
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffff88809788f390 R08: ffff88809788f8c0 R09: 000000000000000c
R10: ffff88809788f5d8 R11: ffff88809788f527 R12: 0000000000000000
R13: dffffc0000000000 R14: ffff88809788f8c0 R15: ffffffff89541d80
FS: 000055555632c880(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000080 CR3: 000000009ba7c000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
ip6_route_multipath_add+0xc55/0x1490 net/ipv6/route.c:5094
inet6_rtm_newroute+0xed/0x180 net/ipv6/route.c:5208
rtnetlink_rcv_msg+0x463/0xb00 net/core/rtnetlink.c:5219
netlink_rcv_skb+0x177/0x450 net/netlink/af_netlink.c:2477
rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5237
netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
netlink_unicast+0x531/0x710 net/netlink/af_netlink.c:1328
netlink_sendmsg+0x8ae/0xd70 net/netlink/af_netlink.c:1917
sock_sendmsg_nosec net/socket.c:646 [inline]
sock_sendmsg+0xd7/0x130 net/socket.c:665
___sys_sendmsg+0x803/0x920 net/socket.c:2286
__sys_sendmsg+0x105/0x1d0 net/socket.c:2324
__do_sys_sendmsg net/socket.c:2333 [inline]
__se_sys_sendmsg net/socket.c:2331 [inline]
__x64_sys_sendmsg+0x78/0xb0 net/socket.c:2331
do_syscall_64+0xfd/0x680 arch/x86/entry/common.c:301
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x4401f9
Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7
48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff
ff 0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ffc09fd0028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 00000000004401f9
RDX: 0000000000000000 RSI: 0000000020000080 RDI: 0000000000000003
RBP: 00000000006ca018 R08: 0000000000000000 R09: 00000000004002c8
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000401a80
R13: 0000000000401b10 R14: 0000000000000000 R15: 0000000000000000
Reported-by: syzbot+382566d339d52cd1a204@syzkaller.appspotmail.com
Fixes: ebee3cad835f ("ipv6: Add IPv6 multipath notifications for add / replace")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
net/ipv6/ip6_fib.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1d16a01eccf5..241a0e9a07c3 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -393,6 +393,8 @@ int call_fib6_multipath_entry_notifiers(struct net *net,
.nsiblings = nsiblings,
};
+ if (!rt)
+ return -EINVAL;
rt->fib6_table->fib_seq++;
return call_fib6_notifiers(net, event_type, &info.info);
}
--
2.20.1
^ permalink raw reply related
* Re: [PATCH RESEND nf-next] netfilter: add support for matching IPv4 options
From: Stephen Suryaputra @ 2019-06-19 17:58 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, netdev
In-Reply-To: <20190619171832.om7losybbkysuk4r@salvia>
On Wed, Jun 19, 2019 at 07:18:32PM +0200, Pablo Neira Ayuso wrote:
>
> Rules with this options will load fine:
>
> ip option eol type 1
> ip option noop type 1
> ip option sec type 1
> ip option timestamp type 1
> ip option rr type 1
> ip option sid type 1
>
> However, they will not ever match I think.
>
> found is set to true, but target is set to EOPNOTSUPP, then...
>
> [...]
> > + err = ipv4_find_option(nft_net(pkt), skb, &offset, priv->type, NULL, NULL);
>
> ... ipv4_find_option() returns -EOPNOTSUPP which says header does
> not exist.
>
Yes. My goal in writing this is mainly to block loose and/or strict
source routing. The system also will need to block RA and RR. Others are
not fully supported since we (my employer) don't need it. They can be
added later on if desired...
^ permalink raw reply
* Re: [PATCH RESEND nf-next] netfilter: add support for matching IPv4 options
From: Pablo Neira Ayuso @ 2019-06-19 18:00 UTC (permalink / raw)
To: Stephen Suryaputra; +Cc: netfilter-devel, netdev
In-Reply-To: <20190619175801.GA3859@ubuntu>
On Wed, Jun 19, 2019 at 01:58:02PM -0400, Stephen Suryaputra wrote:
> On Wed, Jun 19, 2019 at 07:18:32PM +0200, Pablo Neira Ayuso wrote:
> >
> > Rules with this options will load fine:
> >
> > ip option eol type 1
> > ip option noop type 1
> > ip option sec type 1
> > ip option timestamp type 1
> > ip option rr type 1
> > ip option sid type 1
> >
> > However, they will not ever match I think.
> >
> > found is set to true, but target is set to EOPNOTSUPP, then...
> >
> > [...]
> > > + err = ipv4_find_option(nft_net(pkt), skb, &offset, priv->type, NULL, NULL);
> >
> > ... ipv4_find_option() returns -EOPNOTSUPP which says header does
> > not exist.
> >
> Yes. My goal in writing this is mainly to block loose and/or strict
> source routing. The system also will need to block RA and RR. Others are
> not fully supported since we (my employer) don't need it. They can be
> added later on if desired...
OK, that's fine. Then I'd suggest you remove support from eol, noop,
sec, timestamp and sid from the userspace patches.
Thanks!
^ permalink raw reply
* Re: [PATCH] net: fddi: skfp: Include generic PCI definitions from pci_regs.h
From: Shuah Khan @ 2019-06-19 18:04 UTC (permalink / raw)
To: Puranjay Mohan
Cc: netdev, linux-kernel, Bjorn Helgaas, linux-kernel-mentees,
Shuah Khan
In-Reply-To: <20190619174556.21194-1-puranjay12@gmail.com>
On 6/19/19 11:45 AM, Puranjay Mohan wrote:
> Include the generic PCI definitions from include/uapi/linux/pci_regs.h
> change PCI_REV_ID to PCI_REVISION_ID to make it compatible with the
> generic define.
> This driver uses only one generic PCI define.
>
> Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
> ---
> drivers/net/fddi/skfp/drvfbi.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/fddi/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
> index bdd5700e71fa..38f6d943385d 100644
> --- a/drivers/net/fddi/skfp/drvfbi.c
> +++ b/drivers/net/fddi/skfp/drvfbi.c
> @@ -20,6 +20,7 @@
> #include "h/supern_2.h"
> #include "h/skfbiinc.h"
> #include <linux/bitrev.h>
> +#include <uapi/linux/pci_regs.h>
>
> #ifndef lint
> static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ;
> @@ -127,7 +128,7 @@ static void card_start(struct s_smc *smc)
> * at very first before any other initialization functions is
> * executed.
> */
> - rev_id = inp(PCI_C(PCI_REV_ID)) ;
> + rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
> if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
> smc->hw.hw_is_64bit = TRUE ;
> } else {
>
Why not delete the PCI_REV_ID define in:
drivers/net/fddi/skfp/h/skfbi.h
It looks like this header has duplicate PCI config space header defines,
not just this one. Some of them are slightly different names:
e.g:
#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
Looks like it defines the standard PCI config space instead of
including and using the standard defines from uapi/linux/pci_regs.h
Something to look into.
thanks,
-- Shuah
^ permalink raw reply
* Re: [PATCH] net/ipv4: fib_trie: Avoid cryptic ternary expressions
From: Joe Perches @ 2019-06-19 18:10 UTC (permalink / raw)
To: Nick Desaulniers, Linus Torvalds
Cc: Matthias Kaehlcke, David S . Miller, Alexey Kuznetsov,
Hideaki YOSHIFUJI, Alexander Duyck, netdev, LKML,
Douglas Anderson, Nathan Huckleberry, clang-built-linux,
Nathan Chancellor
In-Reply-To: <CAKwvOdkJCt7Du01e3LreLdpREPuZXWYnUad6WzqwO_o4i0yk7A@mail.gmail.com>
On Wed, 2019-06-19 at 10:41 -0700, Nick Desaulniers wrote:
> On Wed, Jun 19, 2019 at 2:36 AM Joe Perches <joe@perches.com> wrote:
> > On Tue, 2019-06-18 at 16:23 -0700, Nick Desaulniers wrote:
> > > As a side note, I'm going to try to see if MAINTAINERS and
> > > scripts/get_maintainers.pl supports regexes on the commit messages in
> > > order to cc our mailing list
> >
> > Neither. Why should either?
>
> Looks like `K:` is exactly what I'm looking for.
Using K: for commit message content isn't the intended
use, but if it works for you, fine by me.
> Joe, how does:
> https://github.com/ClangBuiltLinux/linux/commit/a0a64b8d65c4e7e033f49e48cc610d6e4002927e
> look?
You might consider using
K: \b(?i:clang|llvm)\b
to get case insensitive matches.
> Is there a maintainer for MAINTAINERS or do I just send the
> patch to Linus?
Generally MAINTAINER patches go via Andrew Morton or
indirectly along with other changes via a pull request
to Linus.
^ permalink raw reply
* Re: [RFC net-next 1/5] net: stmmac: introduce IEEE 802.1Qbv configuration functionalities
From: Vinicius Costa Gomes @ 2019-06-19 18:12 UTC (permalink / raw)
To: Voon Weifeng, David S. Miller, Maxime Coquelin
Cc: netdev, linux-kernel, Jose Abreu, Giuseppe Cavallaro, Andrew Lunn,
Florian Fainelli, Alexandre Torgue, Ong Boon Leong, Voon Weifeng
In-Reply-To: <1560893778-6838-2-git-send-email-weifeng.voon@intel.com>
Hi,
Voon Weifeng <weifeng.voon@intel.com> writes:
> From: Ong Boon Leong <boon.leong.ong@intel.com>
>
> IEEE 802.1Qbv Enhancements for Scheduled Traffics (EST) is available in
> EQoS ver5.xx. The change adds basic EST functionalities:
>
> a) EST initialization with hardware capabilities detection.
> b) Setting Gate Control List (GCL), i.e. gate open/close & time intervals,
> and all GC Related Registers (GCRR), e.g., base time (BTR), cycle time
> (CTR), time extension (TER) and GC List Length (LLR).
> c) Setting time interval left shift (TILS), PTP time offset (PTOV) and
> current time offset (CTOV).
> d) Enable/disable EST.
> e) Getting TSN hardware capabilities.
> f) Getting Gate Control configuration either from driver data store or
> hardware.
>
> We extend the main driver logic to include basic TSN capability discovery,
> and setup. We also add EST feature enable/disable control.
>
> Reviewed-by: Chuah Kim Tatt <kim.tatt.chuah@intel.com>
> Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
> Reviewed-by: Kweh Hock Leong <hock.leong.kweh@intel.com>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
> Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +-
> drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c | 790 ++++++++++++++++++++++
> drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.h | 173 +++++
> drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 13 +
> drivers/net/ethernet/stmicro/stmmac/hwif.h | 52 ++
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 46 ++
> include/linux/stmmac.h | 1 +
> 7 files changed, 1076 insertions(+), 1 deletion(-)
> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c
> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.h
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index c59926d96bcc..76fb36cb4da7 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
> mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \
> dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
> stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
> - $(stmmac-y)
> + dw_tsn_lib.o $(stmmac-y)
>
> stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c
> new file mode 100644
> index 000000000000..cba27c604cb1
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.c
> @@ -0,0 +1,790 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
> +/* Copyright (c) 2019, Intel Corporation.
> + * dw_tsn_lib.c: DW EQoS v5.00 TSN capabilities
> + */
> +
> +#include "dwmac4.h"
> +#include "dwmac5.h"
> +#include "dw_tsn_lib.h"
> +
> +static struct tsn_hw_cap dw_tsn_hwcap;
> +static bool dw_tsn_feat_en[TSN_FEAT_ID_MAX];
> +static unsigned int dw_tsn_hwtunable[TSN_HWTUNA_MAX];
> +static struct est_gc_config dw_est_gc_config;
If it's at all possible to have more than one of these devices in a
system, this should be moved to a per-device structure. That
mac_device_info struct perhaps?
> +
> +static unsigned int est_get_gcl_depth(unsigned int hw_cap)
> +{
> + unsigned int estdep = (hw_cap & GMAC_HW_FEAT_ESTDEP)
> + >> GMAC_HW_FEAT_ESTDEP_SHIFT;
> + unsigned int depth;
> +
> + switch (estdep) {
> + case 1:
> + depth = 64;
> + break;
> + case 2:
> + depth = 128;
> + break;
> + case 3:
> + depth = 256;
> + break;
> + case 4:
> + depth = 512;
> + break;
> + case 5:
> + depth = 1024;
> + break;
> + default:
> + depth = 0;
> + }
> +
> + return depth;
> +}
> +
> +static unsigned int est_get_ti_width(unsigned int hw_cap)
> +{
> + unsigned int estwid = (hw_cap & GMAC_HW_FEAT_ESTWID)
> + >> GMAC_HW_FEAT_ESTWID_SHIFT;
> + unsigned int width;
> +
> + switch (estwid) {
> + case 1:
> + width = 16;
> + break;
> + case 2:
> + width = 20;
> + break;
> + case 3:
> + width = 24;
> + break;
> + default:
> + width = 0;
> + }
> +
> + return width;
> +}
> +
> +static int est_poll_srwo(void *ioaddr)
> +{
> + /* Poll until the EST GCL Control[SRWO] bit clears.
> + * Total wait = 12 x 50ms ~= 0.6s.
> + */
> + unsigned int retries = 12;
> + unsigned int value;
> +
> + do {
> + value = TSN_RD32(ioaddr + MTL_EST_GCL_CTRL);
> + if (!(value & MTL_EST_GCL_CTRL_SRWO))
> + return 0;
> + msleep(50);
> + } while (--retries);
> +
> + return -ETIMEDOUT;
> +}
> +
> +static int est_set_gcl_addr(void *ioaddr, unsigned int addr,
> + unsigned int gcrr, unsigned int rwops,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + unsigned int value;
> +
> + value = MTL_EST_GCL_CTRL_ADDR_VAL(addr) & MTL_EST_GCL_CTRL_ADDR;
> +
> + if (dbgm) {
> + if (dbgb)
> + value |= MTL_EST_GCL_CTRL_DBGB1;
> +
> + value |= MTL_EST_GCL_CTRL_DBGM;
> + }
> +
> + if (gcrr)
> + value |= MTL_EST_GCL_CTRL_GCRR;
> +
> + /* This is the only place SRWO is set and driver polls SRWO
> + * for self-cleared before exit. Therefore, caller should
> + * check return status for possible time out error.
> + */
> + value |= (rwops | MTL_EST_GCL_CTRL_SRWO);
> +
> + TSN_WR32(value, ioaddr + MTL_EST_GCL_CTRL);
> +
> + return est_poll_srwo(ioaddr);
> +}
> +
> +static int est_write_gcl_config(void *ioaddr, unsigned int data,
> + unsigned int addr, unsigned int gcrr,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + TSN_WR32(data, ioaddr + MTL_EST_GCL_DATA);
> +
> + return est_set_gcl_addr(ioaddr, addr, gcrr, GCL_OPS_W, dbgb, dbgm);
> +}
> +
> +static int est_read_gcl_config(void *ioaddr, unsigned int *data,
> + unsigned int addr, unsigned int gcrr,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + int ret;
> +
> + ret = est_set_gcl_addr(ioaddr, addr, gcrr, GCL_OPS_R, dbgb, dbgm);
> + if (ret)
> + return ret;
> +
> + *data = TSN_RD32(ioaddr + MTL_EST_GCL_DATA);
> +
> + return ret;
> +}
> +
> +static int est_read_gce(void *ioaddr, unsigned int row,
> + unsigned int *gates, unsigned int *ti_nsec,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int ti_wid = cap->ti_wid;
> + unsigned int gates_mask;
> + unsigned int ti_mask;
> + unsigned int value;
> + int ret;
> +
> + gates_mask = (1 << cap->txqcnt) - 1;
> + ti_mask = (1 << ti_wid) - 1;
> +
> + ret = est_read_gcl_config(ioaddr, &value, row, 0, dbgb, dbgm);
> + if (ret) {
> + TSN_ERR("Read GCE failed! row=%u\n", row);
> +
> + return ret;
> + }
> + *ti_nsec = value & ti_mask;
> + *gates = (value >> ti_wid) & gates_mask;
> +
> + return ret;
> +}
> +
> +static unsigned int est_get_gcl_total_intervals_nsec(unsigned int bank,
> + unsigned int gcl_len)
> +{
> + struct est_gc_entry *gcl = dw_est_gc_config.gcb[bank].gcl;
> + unsigned int nsec = 0;
> + unsigned int row;
> +
> + for (row = 0; row < gcl_len; row++) {
> + nsec += gcl->ti_nsec;
> + gcl++;
> + }
> +
> + return nsec;
> +}
> +
> +static int est_set_tils(void *ioaddr, const unsigned int tils)
> +{
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int value;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + if (tils > cap->tils_max) {
> + TSN_WARN("EST: invalid tils(%u), max=%u\n",
> + tils, cap->tils_max);
> +
> + return -EINVAL;
> + }
> +
> + /* Ensure that HW is not in the midst of GCL transition */
> + value = TSN_RD32(ioaddr + MTL_EST_CTRL);
> + value &= ~MTL_EST_CTRL_SSWL;
> +
> + /* MTL_EST_CTRL value has been read earlier, if TILS value
> + * differs, we update here.
> + */
> + if (tils != dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_TILS]) {
> + value &= ~MTL_EST_CTRL_TILS;
> + value |= (tils << MTL_EST_CTRL_TILS_SHIFT);
> +
> + TSN_WR32(value, ioaddr + MTL_EST_CTRL);
> + dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_TILS] = tils;
> + }
> +
> + return 0;
> +}
> +
> +static int est_set_ov(void *ioaddr,
> + const unsigned int *ptov,
> + const unsigned int *ctov)
> +{
> + unsigned int value;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + value = TSN_RD32(ioaddr + MTL_EST_CTRL);
> + value &= ~MTL_EST_CTRL_SSWL;
> +
> + if (ptov) {
> + if (*ptov > EST_PTOV_MAX) {
> + TSN_WARN("EST: invalid PTOV(%u), max=%u\n",
> + *ptov, EST_PTOV_MAX);
> +
> + return -EINVAL;
> + } else if (*ptov !=
> + dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_PTOV]) {
> + value &= ~MTL_EST_CTRL_PTOV;
> + value |= (*ptov << MTL_EST_CTRL_PTOV_SHIFT);
> + dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_PTOV] = *ptov;
> + }
> + }
> +
> + if (ctov) {
> + if (*ctov > EST_CTOV_MAX) {
> + TSN_WARN("EST: invalid CTOV(%u), max=%u\n",
> + *ctov, EST_CTOV_MAX);
> +
> + return -EINVAL;
> + } else if (*ctov != dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_CTOV]) {
> + value &= ~MTL_EST_CTRL_CTOV;
> + value |= (*ctov << MTL_EST_CTRL_CTOV_SHIFT);
> + dw_tsn_hwtunable[TSN_HWTUNA_TX_EST_CTOV] = *ctov;
> + }
> + }
> +
> + TSN_WR32(value, ioaddr + MTL_EST_CTRL);
> +
> + return 0;
> +}
> +
> +void dwmac_tsn_init(void *ioaddr)
Perhaps this should return an error if TSN is not supported. It may help
simplify the initialization below.
> +{
> + unsigned int hwid = TSN_RD32(ioaddr + GMAC4_VERSION) & TSN_VER_MASK;
> + unsigned int hw_cap2 = TSN_RD32(ioaddr + GMAC_HW_FEATURE2);
> + unsigned int hw_cap3 = TSN_RD32(ioaddr + GMAC_HW_FEATURE3);
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int gcl_depth;
> + unsigned int tils_max;
> + unsigned int ti_wid;
> +
> + memset(cap, 0, sizeof(*cap));
> +
> + if (hwid < TSN_CORE_VER) {
> + TSN_WARN_NA("IP v5.00 does not support TSN\n");
> + return;
> + }
> +
> + if (!(hw_cap3 & GMAC_HW_FEAT_ESTSEL)) {
> + TSN_WARN_NA("EST NOT supported\n");
> + cap->est_support = 0;
> +
> + return;
> + }
> +
> + gcl_depth = est_get_gcl_depth(hw_cap3);
> + ti_wid = est_get_ti_width(hw_cap3);
> +
> + cap->ti_wid = ti_wid;
> + cap->gcl_depth = gcl_depth;
> +
> + tils_max = (hw_cap3 & GMAC_HW_FEAT_ESTSEL ? 3 : 0);
> + tils_max = (1 << tils_max) - 1;
> + cap->tils_max = tils_max;
> +
> + cap->ext_max = EST_TIWID_TO_EXTMAX(ti_wid);
> + cap->txqcnt = ((hw_cap2 & GMAC_HW_FEAT_TXQCNT) >> 6) + 1;
> + cap->est_support = 1;
> +
> + TSN_INFO("EST: depth=%u, ti_wid=%u, tils_max=%u tqcnt=%u\n",
> + gcl_depth, ti_wid, tils_max, cap->txqcnt);
> +}
> +
> +void dwmac_get_tsn_hwcap(struct tsn_hw_cap **tsn_hwcap)
> +{
> + *tsn_hwcap = &dw_tsn_hwcap;
> +}
> +
> +void dwmac_set_est_gcb(struct est_gc_entry *gcl, unsigned int bank)
> +{
> + if (bank >= 0 && bank < EST_GCL_BANK_MAX)
> + dw_est_gc_config.gcb[bank].gcl = gcl;
> +}
> +
> +void dwmac_set_tsn_feat(enum tsn_feat_id featid, bool enable)
> +{
> + if (featid < TSN_FEAT_ID_MAX)
> + dw_tsn_feat_en[featid] = enable;
> +}
> +
> +int dwmac_set_tsn_hwtunable(void *ioaddr,
> + enum tsn_hwtunable_id id,
> + const unsigned int *data)
> +{
> + int ret = 0;
> +
> + switch (id) {
> + case TSN_HWTUNA_TX_EST_TILS:
> + ret = est_set_tils(ioaddr, *data);
> + break;
> + case TSN_HWTUNA_TX_EST_PTOV:
> + ret = est_set_ov(ioaddr, data, NULL);
> + break;
> + case TSN_HWTUNA_TX_EST_CTOV:
> + ret = est_set_ov(ioaddr, NULL, data);
> + break;
> + default:
> + ret = -EINVAL;
> + };
> +
> + return ret;
> +}
> +
> +int dwmac_get_tsn_hwtunable(enum tsn_hwtunable_id id, unsigned int *data)
> +{
> + if (id >= TSN_HWTUNA_MAX)
> + return -EINVAL;
> +
> + *data = dw_tsn_hwtunable[id];
> +
> + return 0;
> +}
> +
> +int dwmac_get_est_bank(void *ioaddr, unsigned int own)
> +{
> + int swol;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + swol = TSN_RD32(ioaddr + MTL_EST_STATUS);
> +
> + swol = ((swol & MTL_EST_STATUS_SWOL) >>
> + MTL_EST_STATUS_SWOL_SHIFT);
> +
> + if (own)
> + return swol;
> + else
> + return (~swol & 0x1);
> +}
> +
> +int dwmac_set_est_gce(void *ioaddr,
> + struct est_gc_entry *gce, unsigned int row,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int ti_nsec = gce->ti_nsec;
> + unsigned int gates = gce->gates;
> + struct est_gc_entry *gcl;
> + unsigned int gates_mask;
> + unsigned int ti_wid;
> + unsigned int ti_max;
> + unsigned int value;
> + unsigned int bank;
> + int ret;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + if (dbgb >= EST_GCL_BANK_MAX)
> + return -EINVAL;
> +
> + if (dbgm) {
> + bank = dbgb;
> + } else {
> + value = TSN_RD32(ioaddr + MTL_EST_STATUS);
> + bank = (value & MTL_EST_STATUS_SWOL) >>
> + MTL_EST_STATUS_SWOL_SHIFT;
> + }
> +
> + if (!cap->gcl_depth || row > cap->gcl_depth) {
> + TSN_WARN("EST: row(%u) > GCL depth(%u)\n",
> + row, cap->gcl_depth);
> +
> + return -EINVAL;
> + }
> +
> + ti_wid = cap->ti_wid;
> + ti_max = (1 << ti_wid) - 1;
> + if (ti_nsec > ti_max) {
> + TSN_WARN("EST: ti_nsec(%u) > upper limit(%u)\n",
> + ti_nsec, ti_max);
> +
> + return -EINVAL;
> + }
> +
> + gates_mask = (1 << cap->txqcnt) - 1;
> + value = ((gates & gates_mask) << ti_wid) | ti_nsec;
> +
> + ret = est_write_gcl_config(ioaddr, value, row, 0, dbgb, dbgm);
> + if (ret) {
> + TSN_ERR("EST: GCE write failed: bank=%u row=%u.\n",
> + bank, row);
> +
> + return ret;
> + }
> +
> + TSN_INFO("EST: GCE write: dbgm=%u bank=%u row=%u, gc=0x%x.\n",
> + dbgm, bank, row, value);
> +
> + /* Since GC write is successful, update GCL copy of the driver */
> + gcl = dw_est_gc_config.gcb[bank].gcl + row;
> + gcl->gates = gates;
> + gcl->ti_nsec = ti_nsec;
> +
> + return ret;
> +}
> +
> +int dwmac_get_est_gcrr_llr(void *ioaddr, unsigned int *gcl_len,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + unsigned int bank, value;
> + int ret;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + if (dbgb >= EST_GCL_BANK_MAX)
> + return -EINVAL;
> +
> + if (dbgm) {
> + bank = dbgb;
> + } else {
> + value = TSN_RD32(ioaddr + MTL_EST_STATUS);
> + bank = (value & MTL_EST_STATUS_SWOL) >>
> + MTL_EST_STATUS_SWOL_SHIFT;
> + }
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_LLR, 1,
> + dbgb, dbgm);
> + if (ret) {
> + TSN_ERR("read LLR fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> +
> + *gcl_len = value;
> +
> + return 0;
> +}
> +
> +int dwmac_set_est_gcrr_llr(void *ioaddr, unsigned int gcl_len,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int bank, value;
> + struct est_gcrr *bgcrr;
> + int ret = 0;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + if (dbgb >= EST_GCL_BANK_MAX)
> + return -EINVAL;
> +
> + if (dbgm) {
> + bank = dbgb;
> + } else {
> + value = TSN_RD32(ioaddr + MTL_EST_STATUS);
> + bank = (value & MTL_EST_STATUS_SWOL) >>
> + MTL_EST_STATUS_SWOL_SHIFT;
> + }
> +
> + if (gcl_len > cap->gcl_depth) {
> + TSN_WARN("EST: GCL length(%u) > depth(%u)\n",
> + gcl_len, cap->gcl_depth);
> +
> + return -EINVAL;
> + }
> +
> + bgcrr = &dw_est_gc_config.gcb[bank].gcrr;
> +
> + if (gcl_len != bgcrr->llr) {
> + ret = est_write_gcl_config(ioaddr, gcl_len,
> + GCL_CTRL_ADDR_LLR, 1,
> + dbgb, dbgm);
> + if (ret) {
> + TSN_ERR_NA("EST: GCRR programming failure!\n");
> +
> + return ret;
> + }
> + bgcrr->llr = gcl_len;
> + }
> +
> + return 0;
> +}
> +
> +int dwmac_set_est_gcrr_times(void *ioaddr,
> + struct est_gcrr *gcrr,
> + unsigned int dbgb, unsigned int dbgm)
> +{
> + unsigned int cycle_nsec = gcrr->cycle_nsec;
> + unsigned int cycle_sec = gcrr->cycle_sec;
> + unsigned int base_nsec = gcrr->base_nsec;
> + unsigned int base_sec = gcrr->base_sec;
> + unsigned int ext_nsec = gcrr->ter_nsec;
> + struct tsn_hw_cap *cap = &dw_tsn_hwcap;
> + unsigned int gcl_len, tti_ns, value;
> + struct est_gcrr *bgcrr;
> + u64 val_ns, sys_ns;
> + unsigned int bank;
> + int ret = 0;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + if (dbgb >= EST_GCL_BANK_MAX)
> + return -EINVAL;
> +
> + if (dbgm) {
> + bank = dbgb;
> + } else {
> + value = TSN_RD32(ioaddr + MTL_EST_STATUS);
> + bank = (value & MTL_EST_STATUS_SWOL) >>
> + MTL_EST_STATUS_SWOL_SHIFT;
> + }
> +
> + if (base_nsec > 1000000000ULL || cycle_nsec > 1000000000ULL) {
> + TSN_WARN("EST: base(%u) or cycle(%u) nsec > 1s !\n",
> + base_nsec, cycle_nsec);
> +
> + return -EINVAL;
> + }
> +
> + /* Ensure base time is later than MAC system time */
> + val_ns = (u64)base_nsec;
> + val_ns += (u64)(base_sec * 1000000000ULL);
> +
> + /* Get the MAC system time */
> + sys_ns = TSN_RD32(ioaddr + TSN_PTP_STNSR);
> + sys_ns += TSN_RD32(ioaddr + TSN_PTP_STSR) * 1000000000ULL;
> +
> + if (val_ns <= sys_ns) {
> + TSN_WARN("EST: base time(%llu) <= system time(%llu)\n",
> + val_ns, sys_ns);
> +
> + return -EINVAL;
> + }
> +
> + if (cycle_sec > EST_CTR_HI_MAX) {
> + TSN_WARN("EST: cycle time(%u) > 255 seconds\n", cycle_sec);
> +
> + return -EINVAL;
> + }
> +
> + if (ext_nsec > cap->ext_max) {
> + TSN_WARN("EST: invalid time extension(%u), max=%u\n",
> + ext_nsec, cap->ext_max);
> +
> + return -EINVAL;
> + }
> +
> + bgcrr = &dw_est_gc_config.gcb[bank].gcrr;
> + gcl_len = bgcrr->llr;
> +
> + /* Sanity test on GCL total time intervals against cycle time.
> + * a) For GC length = 1, if its time interval is equal or greater
> + * than cycle time, it is a constant gate error.
> + * b) If total time interval > cycle time, irregardless of GC
> + * length, it is not considered an error that GC list is
> + * truncated. In this case, giving a warning message is
> + * sufficient.
> + * c) If total time interval < cycle time, irregardless of GC
> + * length, all GATES are OPEN after the last GC is processed
> + * until cycle time lapses. This is potentially due to poor
> + * GCL configuration but is not an error, so we inform user
> + * about it.
> + */
> + tti_ns = est_get_gcl_total_intervals_nsec(bank, gcl_len);
> + val_ns = (u64)cycle_nsec;
> + val_ns += (u64)(cycle_sec * 1000000000ULL);
> + if (gcl_len == 1 && tti_ns >= val_ns) {
> + TSN_WARN_NA("EST: Constant gate error!\n");
> +
> + return -EINVAL;
> + }
> +
> + if (tti_ns > val_ns)
> + TSN_WARN_NA("EST: GCL is truncated!\n");
> +
> + if (tti_ns < val_ns) {
> + TSN_INFO("EST: All GCs OPEN at %u of %llu-ns cycle\n",
> + tti_ns, val_ns);
> + }
> +
> + /* Finally, start programming GCL related registers if the value
> + * differs from the driver copy for efficiency.
> + */
> +
> + if (base_nsec != bgcrr->base_nsec)
> + ret |= est_write_gcl_config(ioaddr, base_nsec,
> + GCL_CTRL_ADDR_BTR_LO, 1,
> + dbgb, dbgm);
> +
> + if (base_sec != bgcrr->base_sec)
> + ret |= est_write_gcl_config(ioaddr, base_sec,
> + GCL_CTRL_ADDR_BTR_HI, 1,
> + dbgb, dbgm);
> +
> + if (cycle_nsec != bgcrr->cycle_nsec)
> + ret |= est_write_gcl_config(ioaddr, cycle_nsec,
> + GCL_CTRL_ADDR_CTR_LO, 1,
> + dbgb, dbgm);
> +
> + if (cycle_sec != bgcrr->cycle_sec)
> + ret |= est_write_gcl_config(ioaddr, cycle_sec,
> + GCL_CTRL_ADDR_CTR_HI, 1,
> + dbgb, dbgm);
> +
> + if (ext_nsec != bgcrr->ter_nsec)
> + ret |= est_write_gcl_config(ioaddr, ext_nsec,
> + GCL_CTRL_ADDR_TER, 1,
> + dbgb, dbgm);
> +
> + if (ret) {
> + TSN_ERR_NA("EST: GCRR programming failure!\n");
> +
> + return ret;
> + }
> +
> + /* Finally, we are ready to switch SWOL now. */
> + value = TSN_RD32(ioaddr + MTL_EST_CTRL);
> + value |= MTL_EST_CTRL_SSWL;
> + TSN_WR32(value, ioaddr + MTL_EST_CTRL);
> +
> + /* Update driver copy */
> + bgcrr->base_sec = base_sec;
> + bgcrr->base_nsec = base_nsec;
> + bgcrr->cycle_sec = cycle_sec;
> + bgcrr->cycle_nsec = cycle_nsec;
> + bgcrr->ter_nsec = ext_nsec;
> +
> + TSN_INFO_NA("EST: gcrr set successful\n");
> +
> + return 0;
> +}
> +
> +int dwmac_set_est_enable(void *ioaddr, bool enable)
> +{
> + unsigned int value;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + value = TSN_RD32(ioaddr + MTL_EST_CTRL);
> + value &= ~(MTL_EST_CTRL_SSWL | MTL_EST_CTRL_EEST);
> + value |= (enable & MTL_EST_CTRL_EEST);
> + TSN_WR32(value, ioaddr + MTL_EST_CTRL);
> + dw_est_gc_config.enable = enable;
> +
> + return 0;
> +}
> +
> +int dwmac_get_est_gcc(void *ioaddr,
> + struct est_gc_config **gcc, bool frmdrv)
> +{
> + struct est_gc_config *pgcc;
> + unsigned int bank;
> + unsigned int value;
> + int ret;
> +
> + if (!dw_tsn_feat_en[TSN_FEAT_ID_EST])
> + return -ENOTSUPP;
> +
> + /* Get GC config from driver */
> + if (frmdrv) {
> + *gcc = &dw_est_gc_config;
> +
> + TSN_INFO_NA("EST: read GCL from driver copy done.\n");
> +
> + return 0;
> + }
> +
> + /* Get GC config from HW */
> + pgcc = &dw_est_gc_config;
> +
> + value = TSN_RD32(ioaddr + MTL_EST_CTRL);
> + pgcc->enable = value & MTL_EST_CTRL_EEST;
> +
> + for (bank = 0; bank < EST_GCL_BANK_MAX; bank++) {
> + unsigned int llr, row;
> + struct est_gc_bank *gcbc = &pgcc->gcb[bank];
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_BTR_LO, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read BTR(low) fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.base_nsec = value;
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_BTR_HI, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read BTR(high) fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.base_sec = value;
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_CTR_LO, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read CTR(low) fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.cycle_nsec = value;
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_CTR_HI, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read CTR(high) fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.cycle_sec = value;
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_TER, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read TER fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.ter_nsec = value;
> +
> + ret = est_read_gcl_config(ioaddr, &value,
> + GCL_CTRL_ADDR_LLR, 1,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read LLR fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gcbc->gcrr.llr = value;
> + llr = value;
> +
> + for (row = 0; row < llr; row++) {
> + unsigned int gates, ti_nsec;
> + struct est_gc_entry *gce = gcbc->gcl + row;
> +
> + ret = est_read_gce(ioaddr, row, &gates, &ti_nsec,
> + bank, 1);
> + if (ret) {
> + TSN_ERR("read GCE fail at bank=%u\n", bank);
> +
> + return ret;
> + }
> + gce->gates = gates;
> + gce->ti_nsec = ti_nsec;
> + }
> + }
> +
> + *gcc = pgcc;
> + TSN_INFO_NA("EST: read GCL from HW done.\n");
> +
> + return 0;
> +}
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.h b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.h
> new file mode 100644
> index 000000000000..feb71f7e7031
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dw_tsn_lib.h
> @@ -0,0 +1,173 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2019, Intel Corporation.
> + * dw_tsn_lib.h: DW EQoS v5.00 TSN capabilities header
> + */
> +
> +#ifndef __DW_TSN_LIB_H__
> +#define __DW_TSN_LIB_H__
> +
> +#include "linux/printk.h"
> +
> +/* DWMAC v5.xx supports the following Time Sensitive Networking protocols:
> + * 1) IEEE 802.1Qbv Enhancements for Scheduled Traffic (EST)
> + */
> +
> +/* MAC HW features3 bitmap */
> +#define GMAC_HW_FEAT_ESTWID GENMASK(21, 20)
> +#define GMAC_HW_FEAT_ESTWID_SHIFT 20
> +#define GMAC_HW_FEAT_ESTDEP GENMASK(19, 17)
> +#define GMAC_HW_FEAT_ESTDEP_SHIFT 17
> +#define GMAC_HW_FEAT_ESTSEL BIT(16)
> +
> +/* MTL EST control register */
> +#define MTL_EST_CTRL 0x00000c50
> +#define MTL_EST_CTRL_PTOV GENMASK(31, 24)
> +#define MTL_EST_CTRL_PTOV_SHIFT 24
> +#define MTL_EST_CTRL_CTOV GENMASK(23, 12)
> +#define MTL_EST_CTRL_CTOV_SHIFT 12
> +#define MTL_EST_CTRL_TILS GENMASK(10, 8)
> +#define MTL_EST_CTRL_TILS_SHIFT 8
> +#define MTL_EST_CTRL_SSWL BIT(1) /* Switch to SWOL */
> +#define MTL_EST_CTRL_EEST BIT(0) /* Enable EST */
> +
> +/* MTL EST status register */
> +#define MTL_EST_STATUS 0x00000c58
> +#define MTL_EST_STATUS_BTRL GENMASK(11, 8) /* BTR ERR loop cnt */
> +#define MTL_EST_STATUS_BTRL_SHIFT 8
> +#define MTL_EST_STATUS_BTRL_MAX (0xF << 8)
> +#define MTL_EST_STATUS_SWOL BIT(7) /* SW owned list */
> +#define MTL_EST_STATUS_SWOL_SHIFT 7
> +#define MTL_EST_STATUS_BTRE BIT(1) /* BTR Error */
> +#define MTL_EST_STATUS_SWLC BIT(0) /* Switch to SWOL complete */
> +
> +/* MTL EST GCL control register */
> +#define MTL_EST_GCL_CTRL 0x00000c80
> +#define MTL_EST_GCL_CTRL_ADDR GENMASK(10, 8) /* GCL Address */
> +#define MTL_EST_GCL_CTRL_ADDR_VAL(addr) (addr << 8)
> +#define GCL_CTRL_ADDR_BTR_LO 0x0
> +#define GCL_CTRL_ADDR_BTR_HI 0x1
> +#define GCL_CTRL_ADDR_CTR_LO 0x2
> +#define GCL_CTRL_ADDR_CTR_HI 0x3
> +#define GCL_CTRL_ADDR_TER 0x4
> +#define GCL_CTRL_ADDR_LLR 0x5
> +#define MTL_EST_GCL_CTRL_DBGB1 BIT(5) /* Debug Mode Bank Select */
> +#define MTL_EST_GCL_CTRL_DBGM BIT(4) /* Debug Mode */
> +#define MTL_EST_GCL_CTRL_GCRR BIT(2) /* GC Related Registers */
> +#define MTL_EST_GCL_CTRL_R1W0 BIT(1) /* Read / Write Operation */
> +#define GCL_OPS_R BIT(1)
> +#define GCL_OPS_W 0
> +#define MTL_EST_GCL_CTRL_SRWO BIT(0) /* Start R/W Operation */
> +
> +/* MTL EST GCL data register */
> +#define MTL_EST_GCL_DATA 0x00000c84
> +
> +/* EST Global defines */
> +#define EST_CTR_HI_MAX 0xff /* CTR Hi is 8-bit only */
> +#define EST_PTOV_MAX 0xff /* Max PTP time offset */
> +#define EST_CTOV_MAX 0xfff /* Max Current time offset */
> +#define EST_TIWID_TO_EXTMAX(ti_wid) ((1 << (ti_wid + 7)) - 1)
> +#define EST_GCL_BANK_MAX (2)
> +
> +/* MAC Core Version */
> +#define TSN_VER_MASK 0xFF
> +#define TSN_CORE_VER 0x50
> +
> +/* MAC PTP clock registers */
> +#define TSN_PTP_STSR 0x08
> +#define TSN_PTP_STNSR 0x0c
> +
> +/* Hardware Tunable Enum */
> +enum tsn_hwtunable_id {
> + TSN_HWTUNA_TX_EST_TILS = 0,
> + TSN_HWTUNA_TX_EST_PTOV,
> + TSN_HWTUNA_TX_EST_CTOV,
> + TSN_HWTUNA_MAX,
> +};
> +
> +/* TSN Feature Enabled List */
> +enum tsn_feat_id {
> + TSN_FEAT_ID_EST = 0,
> + TSN_FEAT_ID_MAX,
> +};
> +
> +/* HW register read & write macros */
> +#define TSN_RD32(__addr) readl(__addr)
> +#define TSN_WR32(__val, __addr) writel(__val, __addr)
> +
> +/* Logging macros with no args */
> +#define DRVNAME "stmmac"
> +#define TSN_INFO_NA(__msg) printk(KERN_INFO DRVNAME ":" __msg)
> +#define TSN_WARN_NA(__msg) printk(KERN_WARNING DRVNAME ":" __msg)
> +#define TSN_ERR_NA(__msg) printk(KERN_ERR DRVNAME ":" __msg)
> +
> +/* Logging macros with args */
> +#define TSN_INFO(__msg, __arg0, __args...) \
> + printk(KERN_INFO DRVNAME ":" __msg, (__arg0), ##__args)
> +#define TSN_WARN(__msg, __arg0, __args...) \
> + printk(KERN_WARNING DRVNAME ":" __msg, (__arg0), ##__args)
> +#define TSN_ERR(__msg, __arg0, __args...) \
> + printk(KERN_ERR DRVNAME ":" __msg, (__arg0), ##__args)
> +
> +/* TSN HW Capabilities */
> +struct tsn_hw_cap {
> + bool est_support; /* 1: supported */
> + unsigned int txqcnt; /* Number of TxQ (control gate) */
> + unsigned int gcl_depth; /* GCL depth. */
> + unsigned int ti_wid; /* time interval width */
> + unsigned int tils_max; /* Max time interval left shift */
> + unsigned int ext_max; /* Max time extension */
> +};
> +
> +/* EST Gate Control Entry */
> +struct est_gc_entry {
> + unsigned int gates; /* gate control: 0: closed,
> + * 1: open.
> + */
> + unsigned int ti_nsec; /* time interval in nsec */
> +};
> +
> +/* EST GCL Related Registers */
> +struct est_gcrr {
> + unsigned int base_nsec; /* base time denominator (nsec) */
> + unsigned int base_sec; /* base time numerator (sec) */
> + unsigned int cycle_nsec; /* cycle time denominator (nsec) */
> + unsigned int cycle_sec; /* cycle time numerator sec)*/
> + unsigned int ter_nsec; /* time extension (nsec) */
> + unsigned int llr; /* GC list length */
> +};
> +
> +/* EST Gate Control bank */
> +struct est_gc_bank {
> + struct est_gc_entry *gcl; /* Gate Control List */
> + struct est_gcrr gcrr; /* GCL Related Registers */
> +};
> +
> +/* EST Gate Control Configuration */
> +struct est_gc_config {
> + struct est_gc_bank gcb[EST_GCL_BANK_MAX];
> + bool enable; /* 1: enabled */
> +};
> +
> +/* TSN functions */
> +void dwmac_tsn_init(void *ioaddr);
> +void dwmac_get_tsn_hwcap(struct tsn_hw_cap **tsn_hwcap);
> +void dwmac_set_est_gcb(struct est_gc_entry *gcl, unsigned int bank);
> +void dwmac_set_tsn_feat(enum tsn_feat_id featid, bool enable);
> +int dwmac_set_tsn_hwtunable(void *ioaddr, enum tsn_hwtunable_id id,
> + const unsigned int *data);
> +int dwmac_get_tsn_hwtunable(enum tsn_hwtunable_id id, unsigned int *data);
> +int dwmac_get_est_bank(void *ioaddr, unsigned int own);
> +int dwmac_set_est_gce(void *ioaddr,
> + struct est_gc_entry *gce, unsigned int row,
> + unsigned int dbgb, unsigned int dbgm);
> +int dwmac_get_est_gcrr_llr(void *ioaddr, unsigned int *gcl_len,
> + unsigned int dbgb, unsigned int dbgm);
> +int dwmac_set_est_gcrr_llr(void *ioaddr, unsigned int gcl_len,
> + unsigned int dbgb, unsigned int dbgm);
> +int dwmac_set_est_gcrr_times(void *ioaddr,
> + struct est_gcrr *gcrr,
> + unsigned int dbgb, unsigned int dbgm);
> +int dwmac_set_est_enable(void *ioaddr, bool enable);
> +int dwmac_get_est_gcc(void *ioaddr,
> + struct est_gc_config **gcc, bool frmdrv);
> +#endif /* __DW_TSN_LIB_H__ */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> index 8d9f6cda4012..1361807fe802 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> @@ -817,6 +817,19 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
> .pcs_get_adv_lp = dwmac4_get_adv_lp,
> .debug = dwmac4_debug,
> .set_filter = dwmac4_set_filter,
> + .tsn_init = dwmac_tsn_init,
> + .get_tsn_hwcap = dwmac_get_tsn_hwcap,
> + .set_est_gcb = dwmac_set_est_gcb,
> + .set_tsn_feat = dwmac_set_tsn_feat,
> + .set_tsn_hwtunable = dwmac_set_tsn_hwtunable,
> + .get_tsn_hwtunable = dwmac_get_tsn_hwtunable,
> + .get_est_bank = dwmac_get_est_bank,
> + .set_est_gce = dwmac_set_est_gce,
> + .get_est_gcrr_llr = dwmac_get_est_gcrr_llr,
> + .set_est_gcrr_llr = dwmac_set_est_gcrr_llr,
> + .set_est_gcrr_times = dwmac_set_est_gcrr_times,
> + .set_est_enable = dwmac_set_est_enable,
> + .get_est_gcc = dwmac_get_est_gcc,
> .safety_feat_config = dwmac5_safety_feat_config,
> .safety_feat_irq_status = dwmac5_safety_feat_irq_status,
> .safety_feat_dump = dwmac5_safety_feat_dump,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 2acfbc70e3c8..518a72805185 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -7,6 +7,7 @@
>
> #include <linux/netdevice.h>
> #include <linux/stmmac.h>
> +#include "dw_tsn_lib.h"
>
> #define stmmac_do_void_callback(__priv, __module, __cname, __arg0, __args...) \
> ({ \
> @@ -311,6 +312,31 @@ struct stmmac_ops {
> bool loopback);
> void (*pcs_rane)(void __iomem *ioaddr, bool restart);
> void (*pcs_get_adv_lp)(void __iomem *ioaddr, struct rgmii_adv *adv);
> + /* TSN functions */
> + void (*tsn_init)(void __iomem *ioaddr);
> + void (*get_tsn_hwcap)(struct tsn_hw_cap **tsn_hwcap);
> + void (*set_est_gcb)(struct est_gc_entry *gcl,
> + u32 bank);
> + void (*set_tsn_feat)(enum tsn_feat_id featid, bool enable);
> + int (*set_tsn_hwtunable)(void __iomem *ioaddr,
> + enum tsn_hwtunable_id id,
> + const unsigned int *data);
> + int (*get_tsn_hwtunable)(enum tsn_hwtunable_id id,
> + unsigned int *data);
> + int (*get_est_bank)(void __iomem *ioaddr, u32 own);
> + int (*set_est_gce)(void __iomem *ioaddr,
> + struct est_gc_entry *gce, u32 row,
> + u32 dbgb, u32 dbgm);
> + int (*get_est_gcrr_llr)(void __iomem *ioaddr, u32 *gcl_len,
> + u32 dbgb, u32 dbgm);
> + int (*set_est_gcrr_llr)(void __iomem *ioaddr, u32 gcl_len,
> + u32 dbgb, u32 dbgm);
> + int (*set_est_gcrr_times)(void __iomem *ioaddr,
> + struct est_gcrr *gcrr,
> + u32 dbgb, u32 dbgm);
> + int (*set_est_enable)(void __iomem *ioaddr, bool enable);
> + int (*get_est_gcc)(void __iomem *ioaddr,
> + struct est_gc_config **gcc, bool frmdrv);
These functions do not seem to be consistent with the rest of the
stmmac_ops: most of the operations already there receive an
mac_device_info as first argument, which seem much less error prone than
a void* ioaddr.
> /* Safety Features */
> int (*safety_feat_config)(void __iomem *ioaddr, unsigned int asp);
> int (*safety_feat_irq_status)(struct net_device *ndev,
> @@ -385,6 +411,32 @@ struct stmmac_ops {
> stmmac_do_void_callback(__priv, mac, pcs_rane, __args)
> #define stmmac_pcs_get_adv_lp(__priv, __args...) \
> stmmac_do_void_callback(__priv, mac, pcs_get_adv_lp, __args)
> +#define stmmac_tsn_init(__priv, __args...) \
> + stmmac_do_void_callback(__priv, mac, tsn_init, __args)
> +#define stmmac_get_tsn_hwcap(__priv, __args...) \
> + stmmac_do_void_callback(__priv, mac, get_tsn_hwcap, __args)
> +#define stmmac_set_est_gcb(__priv, __args...) \
> + stmmac_do_void_callback(__priv, mac, set_est_gcb, __args)
> +#define stmmac_set_tsn_feat(__priv, __args...) \
> + stmmac_do_void_callback(__priv, mac, set_tsn_feat, __args)
> +#define stmmac_set_tsn_hwtunable(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, set_tsn_hwtunable, __args)
> +#define stmmac_get_tsn_hwtunable(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, get_tsn_hwtunable, __args)
> +#define stmmac_get_est_bank(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, get_est_bank, __args)
> +#define stmmac_set_est_gce(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, set_est_gce, __args)
> +#define stmmac_get_est_gcrr_llr(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, get_est_gcrr_llr, __args)
> +#define stmmac_set_est_gcrr_llr(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, set_est_gcrr_llr, __args)
> +#define stmmac_set_est_gcrr_times(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, set_est_gcrr_times, __args)
> +#define stmmac_set_est_enable(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, set_est_enable, __args)
> +#define stmmac_get_est_gcc(__priv, __args...) \
> + stmmac_do_callback(__priv, mac, get_est_gcc, __args)
> #define stmmac_safety_feat_config(__priv, __args...) \
> stmmac_do_callback(__priv, mac, safety_feat_config, __args)
> #define stmmac_safety_feat_irq_status(__priv, __args...) \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index a48751989fa6..91213cd3a668 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -41,6 +41,7 @@
> #include "stmmac.h"
> #include <linux/reset.h>
> #include <linux/of_mdio.h>
> +#include "dw_tsn_lib.h"
> #include "dwmac1000.h"
> #include "dwxgmac2.h"
> #include "hwif.h"
> @@ -3621,6 +3622,8 @@ static int stmmac_set_features(struct net_device *netdev,
> */
> stmmac_rx_ipc(priv, priv->hw);
>
> + netdev->features = features;
> +
> return 0;
> }
>
> @@ -4070,6 +4073,8 @@ static void stmmac_service_task(struct work_struct *work)
> */
> static int stmmac_hw_init(struct stmmac_priv *priv)
> {
> + struct tsn_hw_cap *tsn_hwcap;
> + int gcl_depth = 0;
> int ret;
>
> /* dwmac-sun8i only work in chain mode */
> @@ -4082,6 +4087,38 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
> if (ret)
> return ret;
>
> + /* Initialize TSN capability */
> + stmmac_tsn_init(priv, priv->ioaddr);
> + stmmac_get_tsn_hwcap(priv, &tsn_hwcap);
> + if (tsn_hwcap)
> + gcl_depth = tsn_hwcap->gcl_depth;
> + if (gcl_depth > 0) {
> + u32 bank;
> + struct est_gc_entry *gcl[EST_GCL_BANK_MAX];
> +
> + for (bank = 0; bank < EST_GCL_BANK_MAX; bank++) {
> + gcl[bank] = devm_kzalloc(priv->device,
> + (sizeof(*gcl) * gcl_depth),
> + GFP_KERNEL);
> + if (!gcl[bank]) {
> + ret = -ENOMEM;
> + break;
> + }
> + stmmac_set_est_gcb(priv, gcl[bank], bank);
> + }
> + if (ret) {
> + int i;
> +
> + for (i = bank - 1; i >= 0; i--) {
> + devm_kfree(priv->device, gcl[i]);
> + stmmac_set_est_gcb(priv, NULL, bank);
> + }
> + dev_warn(priv->device, "EST: GCL -ENOMEM\n");
> +
> + return ret;
> + }
> + }
> +
> /* Get the HW capability (new GMAC newer than 3.50a) */
> priv->hw_cap_support = stmmac_get_hw_features(priv);
> if (priv->hw_cap_support) {
> @@ -4168,6 +4205,7 @@ int stmmac_dvr_probe(struct device *device,
> struct stmmac_resources *res)
> {
> struct net_device *ndev = NULL;
> + struct tsn_hw_cap *tsn_hwcap;
> struct stmmac_priv *priv;
> u32 queue, maxq;
> int ret = 0;
> @@ -4254,6 +4292,14 @@ int stmmac_dvr_probe(struct device *device,
> }
> ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
> ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
> +
> + /* TSN HW feature setup */
> + stmmac_get_tsn_hwcap(priv, &tsn_hwcap);
> + if (tsn_hwcap && tsn_hwcap->est_support && priv->plat->tsn_est_en) {
> + stmmac_set_tsn_feat(priv, TSN_FEAT_ID_EST, true);
> + dev_info(priv->device, "EST feature enabled\n");
> + }
> +
> #ifdef STMMAC_VLAN_TAG_USED
> /* Both mac100 and gmac support receive VLAN tag detection */
> ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 7d06241582dd..d4a90f48e49b 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -172,6 +172,7 @@ struct plat_stmmacenet_data {
> int has_gmac4;
> bool has_sun8i;
> bool tso_en;
> + bool tsn_est_en;
> int mac_port_sel_speed;
> bool en_tx_lpi_clockgating;
> int has_xgmac;
> --
> 1.9.1
^ permalink raw reply
* [PATCH v2] net: mvpp2: debugfs: Add pmap to fs dump
From: Nathan Huckleberry @ 2019-06-19 18:17 UTC (permalink / raw)
To: davem, maxime.chevallier
Cc: netdev, linux-kernel, Nathan Huckleberry, clang-built-linux
In-Reply-To: <20190619084921.7e1310e0@bootlin.com>
There was an unused variable 'mvpp2_dbgfs_prs_pmap_fops'
Added a usage consistent with other fops to dump pmap
to userspace.
Cc: clang-built-linux@googlegroups.com
Link: https://github.com/ClangBuiltLinux/linux/issues/529
Signed-off-by: Nathan Huckleberry <nhuck@google.com>
---
Changes from v1 -> v2
* Fix typo
* Change commit prefix to debugfs
drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c
index 0ee39ea47b6b..274fb07362cb 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c
@@ -566,6 +566,9 @@ static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent,
debugfs_create_file("hits", 0444, prs_entry_dir, entry,
&mvpp2_dbgfs_prs_hits_fops);
+ debugfs_create_file("pmap", 0444, prs_entry_dir, entry,
+ &mvpp2_dbgfs_prs_pmap_fops);
+
return 0;
}
--
2.22.0.410.gd8fdbe21b5-goog
^ permalink raw reply related
* Re: [PATCH] mm: mempolicy: handle vma with unmovable pages mapped correctly in mbind
From: Yang Shi @ 2019-06-19 18:19 UTC (permalink / raw)
To: Vlastimil Babka, Michal Hocko
Cc: akpm, mgorman, linux-mm, linux-kernel, Eric Dumazet,
David S. Miller, netdev
In-Reply-To: <687f4e57-5c50-7900-645e-6ef3a5c1c0c7@linux.alibaba.com>
On 6/19/19 9:21 AM, Yang Shi wrote:
>
>
> On 6/19/19 1:22 AM, Vlastimil Babka wrote:
>> On 6/19/19 7:21 AM, Michal Hocko wrote:
>>> On Tue 18-06-19 14:13:16, Yang Shi wrote:
>>> [...]
>>>> I used to have !__PageMovable(page), but it was removed since the
>>>> aforementioned reason. I could add it back.
>>>>
>>>> For the temporary off LRU page, I did a quick search, it looks the
>>>> most
>>>> paths have to acquire mmap_sem, so it can't race with us here. Page
>>>> reclaim/compaction looks like the only race. But, since the mapping
>>>> should
>>>> be preserved even though the page is off LRU temporarily unless the
>>>> page is
>>>> reclaimed, so we should be able to exclude temporary off LRU pages by
>>>> calling page_mapping() and page_anon_vma().
>>>>
>>>> So, the fix may look like:
>>>>
>>>> if (!PageLRU(head) && !__PageMovable(page)) {
>>>> if (!(page_mapping(page) || page_anon_vma(page)))
>>>> return -EIO;
>>> This is getting even more muddy TBH. Is there any reason that we
>>> have to
>>> handle this problem during the isolation phase rather the migration?
>> I think it was already said that if pages can't be isolated, then
>> migration phase won't process them, so they're just ignored.
>
> Yes,exactly.
>
>> However I think the patch is wrong to abort immediately when
>> encountering such page that cannot be isolated (AFAICS). IMHO it should
>> still try to migrate everything it can, and only then return -EIO.
>
> It is fine too. I don't see mbind semantics define how to handle such
> case other than returning -EIO.
By looking into the code, it looks not that easy as what I thought.
do_mbind() would check the return value of queue_pages_range(), it just
applies the policy and manipulates vmas as long as the return value is 0
(success), then migrate pages on the list. We could put the movable
pages on the list by not breaking immediately, but they will be ignored.
If we migrate the pages regardless of the return value, it may break the
policy since the policy will *not* be applied at all.
>
>
^ 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