* [PATCH net-next 2/6] net: sched: sch: add extack for init callback
From: Alexander Aring @ 2017-12-06 16:08 UTC (permalink / raw)
To: davem
Cc: jhs, xiyou.wangcong, jiri, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171206160845.6646-1-aring@mojatatu.com>
This patch adds extack support for init callback to prepare per-qdisc
specific changes for extack.
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
include/net/sch_generic.h | 3 ++-
net/sched/sch_api.c | 2 +-
net/sched/sch_cbq.c | 3 ++-
net/sched/sch_cbs.c | 3 ++-
net/sched/sch_choke.c | 3 ++-
net/sched/sch_codel.c | 3 ++-
net/sched/sch_drr.c | 3 ++-
net/sched/sch_dsmark.c | 3 ++-
net/sched/sch_fifo.c | 14 ++++++++++----
net/sched/sch_fq.c | 3 ++-
net/sched/sch_fq_codel.c | 3 ++-
net/sched/sch_generic.c | 8 +++++---
net/sched/sch_gred.c | 3 ++-
net/sched/sch_hfsc.c | 3 ++-
net/sched/sch_hhf.c | 3 ++-
net/sched/sch_htb.c | 3 ++-
net/sched/sch_ingress.c | 6 ++++--
net/sched/sch_mq.c | 3 ++-
net/sched/sch_mqprio.c | 3 ++-
net/sched/sch_multiq.c | 3 ++-
net/sched/sch_netem.c | 3 ++-
net/sched/sch_pie.c | 3 ++-
net/sched/sch_plug.c | 3 ++-
net/sched/sch_prio.c | 3 ++-
net/sched/sch_qfq.c | 3 ++-
net/sched/sch_red.c | 3 ++-
net/sched/sch_sfb.c | 3 ++-
net/sched/sch_sfq.c | 3 ++-
net/sched/sch_tbf.c | 3 ++-
net/sched/sch_teql.c | 3 ++-
30 files changed, 72 insertions(+), 36 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 7dd8b0b0d244..a6974a46c9da 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -186,7 +186,8 @@ struct Qdisc_ops {
struct sk_buff * (*dequeue)(struct Qdisc *);
struct sk_buff * (*peek)(struct Qdisc *);
- int (*init)(struct Qdisc *sch, struct nlattr *arg);
+ int (*init)(struct Qdisc *sch, struct nlattr *arg,
+ struct netlink_ext_ack *extack);
void (*reset)(struct Qdisc *);
void (*destroy)(struct Qdisc *);
int (*change)(struct Qdisc *sch,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 7b52a16d2fea..c9b9136a3e30 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1083,7 +1083,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
}
if (ops->init) {
- err = ops->init(sch, tca[TCA_OPTIONS]);
+ err = ops->init(sch, tca[TCA_OPTIONS], extack);
if (err != 0)
goto err_out5;
}
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 525eb3a6d625..845f1ebbb217 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1132,7 +1132,8 @@ static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
[TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
};
-static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
+static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct cbq_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_CBQ_MAX + 1];
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index 7a72980c1509..d77c632a276c 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -291,7 +291,8 @@ static int cbs_change(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int cbs_init(struct Qdisc *sch, struct nlattr *opt)
+static int cbs_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct cbs_sched_data *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index b30a2c70bd48..f3f773ff9ac4 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -428,7 +428,8 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int choke_init(struct Qdisc *sch, struct nlattr *opt)
+static int choke_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
return choke_change(sch, opt);
}
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index c518a1efcb9d..7221244e7f3b 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -184,7 +184,8 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int codel_init(struct Qdisc *sch, struct nlattr *opt)
+static int codel_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct codel_sched_data *q = qdisc_priv(sch);
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 5bbcef3dcd8c..1a88473cd768 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -408,7 +408,8 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
return NULL;
}
-static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
+static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct drr_sched *q = qdisc_priv(sch);
int err;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index fb4fb71c68cf..16dd480b5583 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -330,7 +330,8 @@ static struct sk_buff *dsmark_peek(struct Qdisc *sch)
return p->q->ops->peek(p->q);
}
-static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
+static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct dsmark_qdisc_data *p = qdisc_priv(sch);
struct nlattr *tb[TCA_DSMARK_MAX + 1];
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 1e37247656f8..a2d1c9f9b798 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -55,7 +55,8 @@ static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch,
return NET_XMIT_CN;
}
-static int fifo_init(struct Qdisc *sch, struct nlattr *opt)
+static int fifo_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
bool bypass;
bool is_bfifo = sch->ops == &bfifo_qdisc_ops;
@@ -88,6 +89,11 @@ static int fifo_init(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
+static int fifo_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ return fifo_init(sch, opt, NULL);
+}
+
static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct tc_fifo_qopt opt = { .limit = sch->limit };
@@ -108,7 +114,7 @@ struct Qdisc_ops pfifo_qdisc_ops __read_mostly = {
.peek = qdisc_peek_head,
.init = fifo_init,
.reset = qdisc_reset_queue,
- .change = fifo_init,
+ .change = fifo_change,
.dump = fifo_dump,
.owner = THIS_MODULE,
};
@@ -122,7 +128,7 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
.peek = qdisc_peek_head,
.init = fifo_init,
.reset = qdisc_reset_queue,
- .change = fifo_init,
+ .change = fifo_change,
.dump = fifo_dump,
.owner = THIS_MODULE,
};
@@ -136,7 +142,7 @@ struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = {
.peek = qdisc_peek_head,
.init = fifo_init,
.reset = qdisc_reset_queue,
- .change = fifo_init,
+ .change = fifo_change,
.dump = fifo_dump,
.owner = THIS_MODULE,
};
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 263d16e3219e..c9f61ffe220e 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -788,7 +788,8 @@ static void fq_destroy(struct Qdisc *sch)
qdisc_watchdog_cancel(&q->watchdog);
}
-static int fq_init(struct Qdisc *sch, struct nlattr *opt)
+static int fq_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct fq_sched_data *q = qdisc_priv(sch);
int err;
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 0305d791ea94..5d0b20898ffa 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -458,7 +458,8 @@ static void fq_codel_destroy(struct Qdisc *sch)
kvfree(q->flows);
}
-static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
+static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
int i;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3839cbbdc32b..0f26a6026988 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -434,7 +434,8 @@ struct Qdisc noop_qdisc = {
};
EXPORT_SYMBOL(noop_qdisc);
-static int noqueue_init(struct Qdisc *qdisc, struct nlattr *opt)
+static int noqueue_init(struct Qdisc *qdisc, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
/* register_qdisc() assigns a default of noop_enqueue if unset,
* but __dev_queue_xmit() treats noqueue only as such
@@ -567,7 +568,8 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
return -1;
}
-static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
+static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
int prio;
struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
@@ -666,7 +668,7 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
}
sch->parent = parentid;
- if (!ops->init || ops->init(sch, NULL) == 0)
+ if (!ops->init || ops->init(sch, NULL, NULL) == 0)
return sch;
qdisc_destroy(sch);
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 17c7130454bd..be22b1f4ee12 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -462,7 +462,8 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
return err;
}
-static int gred_init(struct Qdisc *sch, struct nlattr *opt)
+static int gred_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct nlattr *tb[TCA_GRED_MAX + 1];
int err;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index d04068a97d81..eca5e34ceb6f 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1388,7 +1388,8 @@ hfsc_schedule_watchdog(struct Qdisc *sch)
}
static int
-hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
+hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct tc_hfsc_qopt *qopt;
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 73a53c08091b..b3a80f0ed4b0 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -571,7 +571,8 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int hhf_init(struct Qdisc *sch, struct nlattr *opt)
+static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct hhf_sched_data *q = qdisc_priv(sch);
int i;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index fa0380730ff0..41d9b7da9273 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1017,7 +1017,8 @@ static void htb_work_func(struct work_struct *work)
rcu_read_unlock();
}
-static int htb_init(struct Qdisc *sch, struct nlattr *opt)
+static int htb_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct htb_sched *q = qdisc_priv(sch);
struct nlattr *tb[TCA_HTB_MAX + 1];
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 5ecc38f35d47..c703cf3a0bed 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -62,7 +62,8 @@ static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
mini_qdisc_pair_swap(miniqp, tp_head);
}
-static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
+static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct ingress_sched_data *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
@@ -166,7 +167,8 @@ static struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl)
}
}
-static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
+static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct clsact_sched_data *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 213b586a06a0..c4f160495366 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -35,7 +35,8 @@ static void mq_destroy(struct Qdisc *sch)
kfree(priv->qdiscs);
}
-static int mq_init(struct Qdisc *sch, struct nlattr *opt)
+static int mq_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct net_device *dev = qdisc_dev(sch);
struct mq_sched *priv = qdisc_priv(sch);
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index b85885a9d8a1..9355c4a4686c 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -132,7 +132,8 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
return 0;
}
-static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
+static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct net_device *dev = qdisc_dev(sch);
struct mqprio_sched *priv = qdisc_priv(sch);
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 012216386c0b..7ed50e653d1a 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -236,7 +236,8 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
+static int multiq_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct multiq_sched_data *q = qdisc_priv(sch);
int i, err;
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index dd70924cbcdf..6490ce08d29e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -984,7 +984,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
return ret;
}
-static int netem_init(struct Qdisc *sch, struct nlattr *opt)
+static int netem_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct netem_sched_data *q = qdisc_priv(sch);
int ret;
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index 776c694c77c7..c4c87ed3971f 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -439,7 +439,8 @@ static void pie_timer(struct timer_list *t)
}
-static int pie_init(struct Qdisc *sch, struct nlattr *opt)
+static int pie_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct pie_sched_data *q = qdisc_priv(sch);
diff --git a/net/sched/sch_plug.c b/net/sched/sch_plug.c
index 1c6cbab3e7b9..d9c6fbe55ae5 100644
--- a/net/sched/sch_plug.c
+++ b/net/sched/sch_plug.c
@@ -123,7 +123,8 @@ static struct sk_buff *plug_dequeue(struct Qdisc *sch)
return qdisc_dequeue_head(sch);
}
-static int plug_init(struct Qdisc *sch, struct nlattr *opt)
+static int plug_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct plug_sched_data *q = qdisc_priv(sch);
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 2c79559a0d31..8632d795e6ee 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -205,7 +205,8 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int prio_init(struct Qdisc *sch, struct nlattr *opt)
+static int prio_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct prio_sched_data *q = qdisc_priv(sch);
int err;
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 6962b37a3ad3..7c1b976314bd 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -1413,7 +1413,8 @@ static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
qfq_deactivate_class(q, cl);
}
-static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
+static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct qfq_sched *q = qdisc_priv(sch);
struct qfq_group *grp;
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 7f8ea9e297c3..bf1b72b8f0de 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -262,7 +262,8 @@ static inline void red_adaptative_timer(struct timer_list *t)
spin_unlock(root_lock);
}
-static int red_init(struct Qdisc *sch, struct nlattr *opt)
+static int red_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct red_sched_data *q = qdisc_priv(sch);
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 0678debdd856..b2205eaa0f51 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -549,7 +549,8 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt)
return 0;
}
-static int sfb_init(struct Qdisc *sch, struct nlattr *opt)
+static int sfb_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct sfb_sched_data *q = qdisc_priv(sch);
int err;
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 09c1203c1711..0af813ed67c2 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -718,7 +718,8 @@ static void sfq_destroy(struct Qdisc *sch)
kfree(q->red_parms);
}
-static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
+static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct sfq_sched_data *q = qdisc_priv(sch);
int i;
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 120f4f365967..6fbfce047d4c 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -421,7 +421,8 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
return err;
}
-static int tbf_init(struct Qdisc *sch, struct nlattr *opt)
+static int tbf_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct tbf_sched_data *q = qdisc_priv(sch);
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 9fe6b427afed..93f04cf5cac1 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -167,7 +167,8 @@ teql_destroy(struct Qdisc *sch)
}
}
-static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
+static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct net_device *dev = qdisc_dev(sch);
struct teql_master *m = (struct teql_master *)sch->ops;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 1/6] net: sched: sch_api: handle generic qdisc errors
From: Alexander Aring @ 2017-12-06 16:08 UTC (permalink / raw)
To: davem
Cc: jhs, xiyou.wangcong, jiri, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171206160845.6646-1-aring@mojatatu.com>
This patch adds extack support for generic qdisc handling. The extack
will be set deeper to each called function which is not part of netdev
core api. A future patchset will add per-qdisc specific changes.
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
net/sched/sch_api.c | 193 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 139 insertions(+), 54 deletions(-)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index a48ca41b7ecf..7b52a16d2fea 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -449,7 +449,8 @@ static const struct nla_policy stab_policy[TCA_STAB_MAX + 1] = {
[TCA_STAB_DATA] = { .type = NLA_BINARY },
};
-static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
+static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct nlattr *tb[TCA_STAB_MAX + 1];
struct qdisc_size_table *stab;
@@ -458,23 +459,31 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
u16 *tab = NULL;
int err;
- err = nla_parse_nested(tb, TCA_STAB_MAX, opt, stab_policy, NULL);
- if (err < 0)
+ err = nla_parse_nested(tb, TCA_STAB_MAX, opt, stab_policy, extack);
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Failed to parse stab netlink msg");
return ERR_PTR(err);
- if (!tb[TCA_STAB_BASE])
+ }
+ if (!tb[TCA_STAB_BASE]) {
+ NL_SET_ERR_MSG(extack, "Stab base is missing");
return ERR_PTR(-EINVAL);
+ }
s = nla_data(tb[TCA_STAB_BASE]);
if (s->tsize > 0) {
- if (!tb[TCA_STAB_DATA])
+ if (!tb[TCA_STAB_DATA]) {
+ NL_SET_ERR_MSG(extack, "Stab data is missing");
return ERR_PTR(-EINVAL);
+ }
tab = nla_data(tb[TCA_STAB_DATA]);
tsize = nla_len(tb[TCA_STAB_DATA]) / sizeof(u16);
}
- if (tsize != s->tsize || (!tab && tsize > 0))
+ if (tsize != s->tsize || (!tab && tsize > 0)) {
+ NL_SET_ERR_MSG(extack, "Invalid data length of stab data");
return ERR_PTR(-EINVAL);
+ }
list_for_each_entry(stab, &qdisc_stab_list, list) {
if (memcmp(&stab->szopts, s, sizeof(*s)))
@@ -486,8 +495,10 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
}
stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
- if (!stab)
+ if (!stab) {
+ NL_SET_ERR_MSG(extack, "Failed to allocate memory for stab data");
return ERR_PTR(-ENOMEM);
+ }
stab->refcnt = 1;
stab->szopts = *s;
@@ -896,7 +907,8 @@ static void notify_and_destroy(struct net *net, struct sk_buff *skb,
static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
struct sk_buff *skb, struct nlmsghdr *n, u32 classid,
- struct Qdisc *new, struct Qdisc *old)
+ struct Qdisc *new, struct Qdisc *old,
+ struct netlink_ext_ack *extack)
{
struct Qdisc *q = old;
struct net *net = dev_net(dev);
@@ -911,8 +923,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
(new && new->flags & TCQ_F_INGRESS)) {
num_q = 1;
ingress = 1;
- if (!dev_ingress_queue(dev))
+ if (!dev_ingress_queue(dev)) {
+ NL_SET_ERR_MSG(extack, "Cannot find ingress queue for specified netdev");
return -ENOENT;
+ }
}
if (dev->flags & IFF_UP)
@@ -958,10 +972,12 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
if (cops && cops->graft) {
unsigned long cl = cops->find(parent, classid);
- if (cl)
+ if (cl) {
err = cops->graft(parent, cl, new, &old);
- else
+ } else {
+ NL_SET_ERR_MSG(extack, "Specified class not found");
err = -ENOENT;
+ }
}
if (!err)
notify_and_destroy(net, skb, n, classid, old, new);
@@ -982,7 +998,8 @@ static struct lock_class_key qdisc_rx_lock;
static struct Qdisc *qdisc_create(struct net_device *dev,
struct netdev_queue *dev_queue,
struct Qdisc *p, u32 parent, u32 handle,
- struct nlattr **tca, int *errp)
+ struct nlattr **tca, int *errp,
+ struct netlink_ext_ack *extack)
{
int err;
struct nlattr *kind = tca[TCA_KIND];
@@ -1020,11 +1037,14 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
#endif
err = -ENOENT;
- if (!ops)
+ if (!ops) {
+ NL_SET_ERR_MSG(extack, "Specified qdisc not found");
goto err_out;
+ }
sch = qdisc_alloc(dev_queue, ops);
if (IS_ERR(sch)) {
+ NL_SET_ERR_MSG(extack, "Failed to allocate qdisc");
err = PTR_ERR(sch);
goto err_out2;
}
@@ -1039,8 +1059,10 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
if (handle == 0) {
handle = qdisc_alloc_handle(dev);
err = -ENOMEM;
- if (handle == 0)
+ if (handle == 0) {
+ NL_SET_ERR_MSG(extack, "Failed to allocate qdisc handle");
goto err_out3;
+ }
}
lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
if (!netif_is_multiqueue(dev))
@@ -1069,16 +1091,20 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
if (qdisc_is_percpu_stats(sch)) {
sch->cpu_bstats =
netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
- if (!sch->cpu_bstats)
+ if (!sch->cpu_bstats) {
+ NL_SET_ERR_MSG(extack, "Failed to allocate qdisc per cpu bstats");
goto err_out4;
+ }
sch->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
- if (!sch->cpu_qstats)
+ if (!sch->cpu_qstats) {
+ NL_SET_ERR_MSG(extack, "Failed to allocate qdisc per cpu qstats");
goto err_out4;
+ }
}
if (tca[TCA_STAB]) {
- stab = qdisc_get_stab(tca[TCA_STAB]);
+ stab = qdisc_get_stab(tca[TCA_STAB], extack);
if (IS_ERR(stab)) {
err = PTR_ERR(stab);
goto err_out4;
@@ -1089,8 +1115,10 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
seqcount_t *running;
err = -EOPNOTSUPP;
- if (sch->flags & TCQ_F_MQROOT)
+ if (sch->flags & TCQ_F_MQROOT) {
+ NL_SET_ERR_MSG(extack, "Invalid qdisc flag TCQ_F_MQROOT");
goto err_out4;
+ }
if (sch->parent != TC_H_ROOT &&
!(sch->flags & TCQ_F_INGRESS) &&
@@ -1105,8 +1133,10 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
NULL,
running,
tca[TCA_RATE]);
- if (err)
+ if (err) {
+ NL_SET_ERR_MSG(extack, "Failed to generate new estimator");
goto err_out4;
+ }
}
qdisc_hash_add(sch, false);
@@ -1139,21 +1169,24 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
goto err_out3;
}
-static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
+static int qdisc_change(struct Qdisc *sch, struct nlattr **tca,
+ struct netlink_ext_ack *extack)
{
struct qdisc_size_table *ostab, *stab = NULL;
int err = 0;
if (tca[TCA_OPTIONS]) {
- if (!sch->ops->change)
+ if (!sch->ops->change) {
+ NL_SET_ERR_MSG(extack, "Change operation not supported by qdisc");
return -EINVAL;
+ }
err = sch->ops->change(sch, tca[TCA_OPTIONS]);
if (err)
return err;
}
if (tca[TCA_STAB]) {
- stab = qdisc_get_stab(tca[TCA_STAB]);
+ stab = qdisc_get_stab(tca[TCA_STAB], extack);
if (IS_ERR(stab))
return PTR_ERR(stab);
}
@@ -1235,24 +1268,32 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
int err;
if ((n->nlmsg_type != RTM_GETQDISC) &&
- !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
+ !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+ NL_SET_ERR_MSG(extack, "Net admin permission required for this operation");
return -EPERM;
+ }
err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL, extack);
- if (err < 0)
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Failed to parse tcm netlink message");
return err;
+ }
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
- if (!dev)
+ if (!dev) {
+ NL_SET_ERR_MSG(extack, "Failed to find specified netdev");
return -ENODEV;
+ }
clid = tcm->tcm_parent;
if (clid) {
if (clid != TC_H_ROOT) {
if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
p = qdisc_lookup(dev, TC_H_MAJ(clid));
- if (!p)
+ if (!p) {
+ NL_SET_ERR_MSG(extack, "Failed to find qdisc with specified classid");
return -ENOENT;
+ }
q = qdisc_leaf(p, clid);
} else if (dev_ingress_queue(dev)) {
q = dev_ingress_queue(dev)->qdisc_sleeping;
@@ -1260,26 +1301,38 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
} else {
q = dev->qdisc;
}
- if (!q)
+ if (!q) {
+ NL_SET_ERR_MSG(extack, "Cannot find specified qdisc on specified netdev");
return -ENOENT;
+ }
- if (tcm->tcm_handle && q->handle != tcm->tcm_handle)
+ if (tcm->tcm_handle && q->handle != tcm->tcm_handle) {
+ NL_SET_ERR_MSG(extack, "Invalid handle");
return -EINVAL;
+ }
} else {
q = qdisc_lookup(dev, tcm->tcm_handle);
- if (!q)
+ if (!q) {
+ NL_SET_ERR_MSG(extack, "Failed to find qdisc with specified handle");
return -ENOENT;
+ }
}
- if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
+ if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) {
+ NL_SET_ERR_MSG(extack, "Invalid qdisc name");
return -EINVAL;
+ }
if (n->nlmsg_type == RTM_DELQDISC) {
- if (!clid)
+ if (!clid) {
+ NL_SET_ERR_MSG(extack, "Classid cannot be zero");
return -EINVAL;
- if (q->handle == 0)
+ }
+ if (q->handle == 0) {
+ NL_SET_ERR_MSG(extack, "Cannot delete qdisc with handle of zero");
return -ENOENT;
- err = qdisc_graft(dev, p, skb, n, clid, NULL, q);
+ }
+ err = qdisc_graft(dev, p, skb, n, clid, NULL, q, extack);
if (err != 0)
return err;
} else {
@@ -1303,30 +1356,38 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct Qdisc *q, *p;
int err;
- if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
+ if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+ NL_SET_ERR_MSG(extack, "Net admin permission required for this operation");
return -EPERM;
+ }
replay:
/* Reinit, just in case something touches this. */
err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL, extack);
- if (err < 0)
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Failed to parse netlink TC attributes");
return err;
+ }
tcm = nlmsg_data(n);
clid = tcm->tcm_parent;
q = p = NULL;
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
- if (!dev)
+ if (!dev) {
+ NL_SET_ERR_MSG(extack, "Failed to find specified netdev");
return -ENODEV;
+ }
if (clid) {
if (clid != TC_H_ROOT) {
if (clid != TC_H_INGRESS) {
p = qdisc_lookup(dev, TC_H_MAJ(clid));
- if (!p)
+ if (!p) {
+ NL_SET_ERR_MSG(extack, "Failed to find specified qdisc");
return -ENOENT;
+ }
q = qdisc_leaf(p, clid);
} else if (dev_ingress_queue_create(dev)) {
q = dev_ingress_queue(dev)->qdisc_sleeping;
@@ -1341,21 +1402,33 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) {
if (tcm->tcm_handle) {
- if (q && !(n->nlmsg_flags & NLM_F_REPLACE))
+ if (q && !(n->nlmsg_flags & NLM_F_REPLACE)) {
+ NL_SET_ERR_MSG(extack, "NLM_F_REPLACE needed to override");
return -EEXIST;
- if (TC_H_MIN(tcm->tcm_handle))
+ }
+ if (TC_H_MIN(tcm->tcm_handle)) {
+ NL_SET_ERR_MSG(extack, "Invalid minor handle");
return -EINVAL;
+ }
q = qdisc_lookup(dev, tcm->tcm_handle);
- if (!q)
+ if (!q) {
+ NL_SET_ERR_MSG(extack, "No qdisc found for specified handle");
goto create_n_graft;
- if (n->nlmsg_flags & NLM_F_EXCL)
+ }
+ if (n->nlmsg_flags & NLM_F_EXCL) {
+ NL_SET_ERR_MSG(extack, "Exclusivity flag on, cannot override");
return -EEXIST;
+ }
if (tca[TCA_KIND] &&
- nla_strcmp(tca[TCA_KIND], q->ops->id))
+ nla_strcmp(tca[TCA_KIND], q->ops->id)) {
+ NL_SET_ERR_MSG(extack, "Invalid qdisc name");
return -EINVAL;
+ }
if (q == p ||
- (p && check_loop(q, p, 0)))
+ (p && check_loop(q, p, 0))) {
+ NL_SET_ERR_MSG(extack, "Too many references");
return -ELOOP;
+ }
qdisc_refcount_inc(q);
goto graft;
} else {
@@ -1390,33 +1463,45 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
}
}
} else {
- if (!tcm->tcm_handle)
+ if (!tcm->tcm_handle) {
+ NL_SET_ERR_MSG(extack, "Handle cannot be zero");
return -EINVAL;
+ }
q = qdisc_lookup(dev, tcm->tcm_handle);
}
/* Change qdisc parameters */
- if (!q)
+ if (!q) {
+ NL_SET_ERR_MSG(extack, "No qdisc available");
return -ENOENT;
- if (n->nlmsg_flags & NLM_F_EXCL)
+ }
+ if (n->nlmsg_flags & NLM_F_EXCL) {
+ NL_SET_ERR_MSG(extack, "Exclusivity flag on, cannot modify");
return -EEXIST;
- if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
+ }
+ if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) {
+ NL_SET_ERR_MSG(extack, "Invalid qdisc name");
return -EINVAL;
- err = qdisc_change(q, tca);
+ }
+ err = qdisc_change(q, tca, extack);
if (err == 0)
qdisc_notify(net, skb, n, clid, NULL, q);
return err;
create_n_graft:
- if (!(n->nlmsg_flags & NLM_F_CREATE))
+ if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+ NL_SET_ERR_MSG(extack, "Qdisc not found. To create specify NLM_F_CREATE flag");
return -ENOENT;
+ }
if (clid == TC_H_INGRESS) {
- if (dev_ingress_queue(dev))
+ if (dev_ingress_queue(dev)) {
q = qdisc_create(dev, dev_ingress_queue(dev), p,
tcm->tcm_parent, tcm->tcm_parent,
- tca, &err);
- else
+ tca, &err, extack);
+ } else {
+ NL_SET_ERR_MSG(extack, "Cannot find ingress queue for specified netdev");
err = -ENOENT;
+ }
} else {
struct netdev_queue *dev_queue;
@@ -1429,7 +1514,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
q = qdisc_create(dev, dev_queue, p,
tcm->tcm_parent, tcm->tcm_handle,
- tca, &err);
+ tca, &err, extack);
}
if (q == NULL) {
if (err == -EAGAIN)
@@ -1438,7 +1523,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
}
graft:
- err = qdisc_graft(dev, p, skb, n, clid, q, NULL);
+ err = qdisc_graft(dev, p, skb, n, clid, q, NULL, extack);
if (err) {
if (q)
qdisc_destroy(q);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 0/6] net: sched: sch: introduce extack support
From: Alexander Aring @ 2017-12-06 16:08 UTC (permalink / raw)
To: davem
Cc: jhs, xiyou.wangcong, jiri, netdev, kernel, Alexander Aring,
David Ahern
Hi,
this patch series basically add support for extack in common qdisc handling.
Additional it adds extack pointer to common qdisc callback handling this
offers per qdisc implementation to setting the extack message for each
failure over netlink.
The extack message will be set deeper in qdisc functions but going not
deeper as net core api. For qdisc module callback handling, the extack
will not be set. This will be part of per qdisc extack handling.
I also want to prepare patches to handle extack per qdisc module...
so there will come a lot of more patches, just cut them down to make
it reviewable.
There are some above 80-chars width warnings, which I ignore because
it looks more ugly otherwise.
This patch-series based on patches by David Ahren which gave me some
hints how to deal with extack support.
Cc: David Ahern <dsahern@gmail.com>
- Alex
Alexander Aring (6):
net: sched: sch_api: handle generic qdisc errors
net: sched: sch: add extack for init callback
net: sched: sch: add extack for change qdisc ops
net: sched: sch: add extack to change class
net: sched: sch: add extack for block callback
net: sched: sch: add extack for graft callback
include/net/sch_generic.h | 15 ++--
net/sched/cls_api.c | 4 +-
net/sched/sch_api.c | 204 ++++++++++++++++++++++++++++++++--------------
net/sched/sch_atm.c | 3 +-
net/sched/sch_cbq.c | 10 ++-
net/sched/sch_cbs.c | 8 +-
net/sched/sch_choke.c | 8 +-
net/sched/sch_codel.c | 8 +-
net/sched/sch_drr.c | 12 ++-
net/sched/sch_dsmark.c | 12 ++-
net/sched/sch_fifo.c | 5 +-
net/sched/sch_fq.c | 8 +-
net/sched/sch_fq_codel.c | 11 ++-
net/sched/sch_generic.c | 8 +-
net/sched/sch_gred.c | 6 +-
net/sched/sch_hfsc.c | 14 ++--
net/sched/sch_hhf.c | 8 +-
net/sched/sch_htb.c | 10 ++-
net/sched/sch_ingress.c | 12 ++-
net/sched/sch_mq.c | 5 +-
net/sched/sch_mqprio.c | 5 +-
net/sched/sch_multiq.c | 13 +--
net/sched/sch_netem.c | 10 ++-
net/sched/sch_pie.c | 8 +-
net/sched/sch_plug.c | 6 +-
net/sched/sch_prio.c | 13 +--
net/sched/sch_qfq.c | 12 ++-
net/sched/sch_red.c | 10 ++-
net/sched/sch_sfb.c | 16 ++--
net/sched/sch_sfq.c | 6 +-
net/sched/sch_tbf.c | 10 ++-
net/sched/sch_teql.c | 3 +-
32 files changed, 321 insertions(+), 162 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: [PATCH] net: mvmdio: disable/unprepare clocks in EPROBE_DEFER case
From: Andrew Lunn @ 2017-12-06 16:03 UTC (permalink / raw)
To: Tobias Jordan; +Cc: netdev, linux-kernel, ldv-project
In-Reply-To: <20171206142323.6hbm54leg2maanbj@agrajag.zerfleddert.de>
On Wed, Dec 06, 2017 at 03:23:23PM +0100, Tobias Jordan wrote:
> add appropriate calls to clk_disable_unprepare() by jumping to out_mdio
> in case orion_mdio_probe() returns -EPROBE_DEFER.
>
> Found by Linux Driver Verification project (linuxtesting.org).
>
> Fixes: 3d604da1e954 net: mvmdio: get and enable optional clock
> Signed-off-by: Tobias Jordan <Tobias.Jordan@elektrobit.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Thanks Tobais
Andrew
^ permalink raw reply
* Re: [ethtool] ethtool: Add extended compliance codes parsing to sfp modules
From: John W. Linville @ 2017-12-06 15:49 UTC (permalink / raw)
To: Gal Pressman
Cc: David S. Miller, netdev, Saeed Mahameed, Eran Ben Elisha,
Ariel Almog, Zvi Rechtman
In-Reply-To: <1511095767-11609-1-git-send-email-galp@mellanox.com>
On Sun, Nov 19, 2017 at 02:49:27PM +0200, Gal Pressman wrote:
> Update parsing according to SFP28 spec with extended compliance codes.
> SFF-8472, SFF-8024 specify the description of module capability present
> in the 36th byte.
>
> Signed-off-by: Gal Pressman <galp@mellanox.com>
> Reviewed-by: Eran Ben Elisha <eranbe@mellanox.com>
Applied -- sorry for the delay!
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [ethtool] ethtool: Fix coding style warnings and errors reported by checkpatch
From: John W. Linville @ 2017-12-06 15:48 UTC (permalink / raw)
To: Gal Pressman; +Cc: netdev, Saeed Mahameed
In-Reply-To: <1509029084-18788-1-git-send-email-galp@mellanox.com>
On Thu, Oct 26, 2017 at 05:44:43PM +0300, Gal Pressman wrote:
> Checkpatch had a lot to say about ethtool.c, this will handle a lot of
> the reported issues.
>
> Signed-off-by: Gal Pressman <galp@mellanox.com>
> Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
Applied -- sorry for the delay!
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [PATCH] ptr_ring: Add barriers to fix NULL-pointer exception
From: Michael S. Tsirkin @ 2017-12-06 15:57 UTC (permalink / raw)
To: Cherian, George
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
virtualization@lists.linux-foundation.org, edumazet@google.com,
davem@davemloft.net
In-Reply-To: <BN3PR0701MB1702F47F81C945950E284DE0F9320@BN3PR0701MB1702.namprd07.prod.outlook.com>
On Wed, Dec 06, 2017 at 02:08:54PM +0000, Cherian, George wrote:
> > @@ -275,6 +281,13 @@ static inline void *__ptr_ring_consume(struct ptr_ring
> *r)
> > if (ptr)
> > __ptr_ring_discard_one(r);
> >
> > + /*
> > + * This barrier is necessary in order to prevent race condition with
> > + * with __ptr_ring_produce(). Make sure all the elements of ptr is
> > + * in sync with the earlier writes which was done prior to pushing
> > + * it to ring
> > + */
> > + rmb();
> > return ptr;
> > }
>
> You are trying to synchronise two CPUs so non-smp barriers make no
> sense. wmb/rmb are for synchronising with MMIO.
>
> What happens when CONFIG_SMP is not set. smp_wmb/rmb becomes compiler barriers
> (atleast for arm64).
And that is because all read and writes always appear in order when done
from the same CPU.
In case of reads, we do not need a barrier at all (except on dec alpha)
because a read through a pointer can't bypass a read of a pointer.
> I guess that is not what we need.
Maybe, but I don't yet see why not.
> An SMP barrier cannot
> replace a mandatory barrier, but a mandatory barrier can replace an SMP
> barrier.
This does imply that you can always replace a weak barrier with a strong
one, but does not mean you should.
> I will try out your patch too and update the results.
> But I would need couple of days time. Sorry for the delay.
Thanks for the testing.
--
MST
^ permalink raw reply
* [PATCH] net_sched: use macvlan real dev trans_start in dev_trans_start()
From: Chris Dion @ 2017-12-06 15:50 UTC (permalink / raw)
Cc: Chris Dion, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
David S. Miller, netdev, linux-kernel
Macvlan devices are similar to vlans and do not update their
own trans_start. In order for arp monitoring to work for a bond device
when the slaves are macvlans, obtain its real device.
Signed-off-by: Chris Dion <christopher.dion@dell.com>
---
net/sched/sch_generic.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3839cbb..cd1b200 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -26,6 +26,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/if_vlan.h>
+#include <linux/if_macvlan.h>
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
#include <net/dst.h>
@@ -277,6 +278,8 @@ unsigned long dev_trans_start(struct net_device *dev)
if (is_vlan_dev(dev))
dev = vlan_dev_real_dev(dev);
+ else if (netif_is_macvlan(dev))
+ dev = macvlan_dev_real_dev(dev);
res = netdev_get_tx_queue(dev, 0)->trans_start;
for (i = 1; i < dev->num_tx_queues; i++) {
val = netdev_get_tx_queue(dev, i)->trans_start;
--
1.9.4
^ permalink raw reply related
* Re: WARNING in strp_data_ready
From: Dmitry Vyukov @ 2017-12-06 15:44 UTC (permalink / raw)
To: Tom Herbert
Cc: John Fastabend, syzbot, David S. Miller, Eric Biggers, LKML,
Linux Kernel Network Developers, syzkaller-bugs, Tom Herbert,
Cong Wang
In-Reply-To: <CALx6S35x+8HM-Lf7wuDGqnjoVUvPCNgFMvLNeLCNRoT_LZcxLA@mail.gmail.com>
On Mon, Oct 30, 2017 at 11:06 PM, Tom Herbert <tom@herbertland.com> wrote:
> On Mon, Oct 30, 2017 at 2:44 PM, John Fastabend
> <john.fastabend@gmail.com> wrote:
>> On 10/24/2017 08:20 AM, syzbot wrote:
>>> Hello,
>>>
>>> syzkaller hit the following crash on 73d3393ada4f70fa3df5639c8d438f2f034c0ecb
>>> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
>>> compiler: gcc (GCC) 7.1.1 20170620
>>> .config is attached
>>> Raw console output is attached.
>>> C reproducer is attached
>>> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
>>> for information about syzkaller reproducers
>>>
>>>
>>> WARNING: CPU: 0 PID: 2996 at ./include/net/sock.h:1505 sock_owned_by_me include/net/sock.h:1505 [inline]
>>> WARNING: CPU: 0 PID: 2996 at ./include/net/sock.h:1505 sock_owned_by_user include/net/sock.h:1511 [inline]
>>> WARNING: CPU: 0 PID: 2996 at ./include/net/sock.h:1505 strp_data_ready+0x2b7/0x390 net/strparser/strparser.c:404
>>> Kernel panic - not syncing: panic_on_warn set ...
>>>
>>> CPU: 0 PID: 2996 Comm: syzkaller142210 Not tainted 4.14.0-rc5+ #138
>>> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
>>> Call Trace:
>>> <IRQ>
>>> __dump_stack lib/dump_stack.c:16 [inline]
>>> dump_stack+0x194/0x257 lib/dump_stack.c:52
>>> panic+0x1e4/0x417 kernel/panic.c:181
>>> __warn+0x1c4/0x1d9 kernel/panic.c:542
>>> report_bug+0x211/0x2d0 lib/bug.c:183
>>> fixup_bug+0x40/0x90 arch/x86/kernel/traps.c:178
>>> do_trap_no_signal arch/x86/kernel/traps.c:212 [inline]
>>> do_trap+0x260/0x390 arch/x86/kernel/traps.c:261
>>> do_error_trap+0x120/0x390 arch/x86/kernel/traps.c:298
>>> do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:311
>>> invalid_op+0x18/0x20 arch/x86/entry/entry_64.S:905
>>> RIP: 0010:sock_owned_by_me include/net/sock.h:1505 [inline]
>>> RIP: 0010:sock_owned_by_user include/net/sock.h:1511 [inline]
>>> RIP: 0010:strp_data_ready+0x2b7/0x390 net/strparser/strparser.c:404
>>> RSP: 0018:ffff8801db206b18 EFLAGS: 00010206
>>> RAX: ffff8801d1e02080 RBX: ffff8801dad74c48 RCX: 0000000000000000
>>> RDX: 0000000000000100 RSI: ffff8801d29fa0a0 RDI: ffffffff85cbede0
>>> RBP: ffff8801db206b38 R08: 0000000000000005 R09: 1ffffffff0ce0bcd
>>> R10: ffff8801db206a00 R11: dffffc0000000000 R12: ffff8801d29fa000
>>> R13: ffff8801dad74c50 R14: ffff8801d4350a92 R15: 0000000000000001
>>> psock_data_ready+0x56/0x70 net/kcm/kcmsock.c:353
>>
>> Looks like KCM is calling sk_data_ready() without first taking the
>> sock lock.
>>
>> /* Called with lower sock held */
>> static void kcm_rcv_strparser(struct strparser *strp, struct sk_buff *skb)
>> {
>> [...]
>> if (kcm_queue_rcv_skb(&kcm->sk, skb)) {
>>
>> In this case kcm->sk is not the same lock the comment is referring to.
>> And kcm_queue_rcv_skb() will eventually call sk_data_ready().
>>
>> @Tom, how about wrapping the sk_data_ready call in {lock|release}_sock?
>> I don't have anything better in mind immediately.
>>
> The sock locks are taken in reverse order in the send path so so
> grabbing kcm sock lock with lower lock held to call sk_data_ready may
> lead to deadlock like I think.
>
> It might be possible to change the order in the send path to do this.
> Something like:
>
> trylock on lower socket lock
> -if trylock fails
> - release kcm sock lock
> - lock lower sock
> - lock kcm sock
> - call sendpage locked function
>
> I admit that dealing with two levels of socket locks in the data path
> is quite a pain :-)
up
still happening and we've lost 50K+ test VMs on this
^ permalink raw reply
* Re: [PATCH net-next 00/12] sctp: Implement Stream Interleave: The I-DATA Chunk Supporting User Message Interleaving
From: Neil Horman @ 2017-12-06 15:20 UTC (permalink / raw)
To: Xin Long; +Cc: Marcelo Ricardo Leitner, network dev, linux-sctp, davem
In-Reply-To: <CADvbK_ck6w7T-fT9TSYQ2qKx0DGFB_5zkad6JvNLj7FQFxypzg@mail.gmail.com>
On Wed, Dec 06, 2017 at 11:21:46AM +0800, Xin Long wrote:
> On Wed, Dec 6, 2017 at 1:30 AM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Tue, Dec 05, 2017 at 11:15:57PM +0800, Xin Long wrote:
> >> Stream Interleave would be Implemented in two Parts:
> >> 1. The I-DATA Chunk Supporting User Message Interleaving
> >> 2. Interaction with Other SCTP Extensions
> >>
> >
> > I have reviewed this patchset a couple of times already before the
> > posting and other than the missing blank line (heh), it looks good to
> > me. Would ack it now but we'll need a respin for the newline.
> OK, thanks !
>
> >
> > Xin, please wait a bit before respining it. Maybe Neil and others have
> > more comments on it.
> Sure,
>
> I added the part 2 (Interaction with Other SCTP Extensions) only
> as an attachment here, so that it would be more clear to know the
> big picture by checking it. (patchset_2.tar.gz)
>
>
> I also added the test cases here I've done, based on sctp-tests
> (conformance.tar.gz). It includes:
> idata with ulp layer process
> idata with stream reconfig
> idata with stream scheduler
> idata with sctp prsctp
> idata with auth
>
> (idata with sctp-tests others old tests)
>
> and note that another file (debug.tar.gz) is some patches for sctp
> to make these tests easier to be done.
Thanks, I'll look at this shortly
Neil
^ permalink raw reply
* Re: [PATCH net-next 07/12] sctp: implement ulpevent_data for sctp_stream_interleave
From: Neil Horman @ 2017-12-06 15:16 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: Xin Long, network dev, linux-sctp, davem
In-Reply-To: <20171205184853.GC3328@localhost.localdomain>
On Tue, Dec 05, 2017 at 04:48:53PM -0200, Marcelo Ricardo Leitner wrote:
> On Tue, Dec 05, 2017 at 01:28:55PM -0500, Neil Horman wrote:
> > On Tue, Dec 05, 2017 at 11:16:04PM +0800, Xin Long wrote:
> > > ulpevent_data is added as a member of sctp_stream_interleave, used to
> > > do the most process in ulpq, including to convert data or idata chunk
> > > to event, reasm them in reasm queue and put them in lobby queue in
> > > right order, and deliver them up to user sk rx queue.
> > >
> > > This procedure is described in section 2.2.3 of RFC8260.
> > >
> > > It adds most functions for idata here to do the similar process as
> > > the old functions for data. But since the details are very different
> > > between them, the old functions can not be reused for idata.
> > >
> > > event->ssn and event->ppid settings are moved to ulpevent_data from
> > > sctp_ulpevent_make_rcvmsg, so that sctp_ulpevent_make_rcvmsg could
> > > work for both data and idata.
> > >
> > > Note that mid is added in sctp_ulpevent for idata, __packed has to
> > > be used for defining sctp_ulpevent, or it would exceeds the skb cb
> > > that saves a sctp_ulpevent variable for ulp layer process.
> > >
> > > Signed-off-by: Xin Long <lucien.xin@gmail.com>
> > > ---
> > > include/net/sctp/stream_interleave.h | 2 +
> > > include/net/sctp/structs.h | 3 +
> > > include/net/sctp/ulpevent.h | 20 +-
> > > net/sctp/sm_sideeffect.c | 5 +-
> > > net/sctp/stream_interleave.c | 418 +++++++++++++++++++++++++++++++++++
> > > net/sctp/ulpevent.c | 2 -
> > > net/sctp/ulpqueue.c | 12 +-
> > > 7 files changed, 451 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/include/net/sctp/stream_interleave.h b/include/net/sctp/stream_interleave.h
> > > index d8d1b51..02f60f5 100644
> > > --- a/include/net/sctp/stream_interleave.h
> > > +++ b/include/net/sctp/stream_interleave.h
> > > @@ -39,6 +39,8 @@ struct sctp_stream_interleave {
> > > int len, __u8 flags, gfp_t gfp);
> > > void (*assign_number)(struct sctp_chunk *chunk);
> > > bool (*validate_data)(struct sctp_chunk *chunk);
> > > + int (*ulpevent_data)(struct sctp_ulpq *ulpq,
> > > + struct sctp_chunk *chunk, gfp_t gfp);
> > > };
> > >
> > > void sctp_stream_interleave_init(struct sctp_stream *stream);
> > > diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> > > index 348b25e..d7da719 100644
> > > --- a/include/net/sctp/structs.h
> > > +++ b/include/net/sctp/structs.h
> > > @@ -411,6 +411,8 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
> > > #define sctp_mid_skip(stream, type, sid, mid) \
> > > ((stream)->type[sid].mid = mid + 1)
> > >
> > > +#define sctp_stream_in(asoc, sid) (&(asoc)->stream.in[sid])
> > > +
> > > /*
> > > * Pointers to address related SCTP functions.
> > > * (i.e. things that depend on the address family.)
> > > @@ -1386,6 +1388,7 @@ struct sctp_stream_in {
> > > __u16 ssn;
> > > };
> > > __u32 fsn;
> > > + char pd_mode;
> > > };
> > >
> > > struct sctp_stream {
> > > diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
> > > index 231dc42..ce4f2aa 100644
> > > --- a/include/net/sctp/ulpevent.h
> > > +++ b/include/net/sctp/ulpevent.h
> > > @@ -45,19 +45,29 @@
> > > /* A structure to carry information to the ULP (e.g. Sockets API) */
> > > /* Warning: This sits inside an skb.cb[] area. Be very careful of
> > > * growing this structure as it is at the maximum limit now.
> > > + *
> > > + * sctp_ulpevent is saved in sk->cb(48 bytes), whose last 4 bytes
> > > + * have been taken by sock_skb_cb, So here it has to use 'packed'
> > > + * to make sctp_ulpevent fit into the rest 44 bytes.
> > > */
> > > struct sctp_ulpevent {
> > > struct sctp_association *asoc;
> > > struct sctp_chunk *chunk;
> > > unsigned int rmem_len;
> > > - __u32 ppid;
> > > + union {
> > > + __u32 mid;
> > > + __u16 ssn;
> > > + };
> > > + union {
> > > + __u32 ppid;
> > > + __u32 fsn;
> > > + };
> > > __u32 tsn;
> > > __u32 cumtsn;
> > > __u16 stream;
> > > - __u16 ssn;
> > > __u16 flags;
> > > __u16 msg_flags;
> > > -};
> > > +} __packed;
> > >
> > What kind of performance do you see before and after this patch? I ask because
> > it seems like the members between ppid through stream are going to be misaligned
> > (not on a 4 byte boundary), now that you've made this structure packed.
>
> It shouldn't be misaligned because the __u16 ssn field is wrapped on a union
> with __u32 mid, causing the next field to be aligned on the largest member,
> which is __u32.
>
> FWIW, before:
> struct sctp_ulpevent {
> struct sctp_association * asoc; /* 0 8 */
> struct sctp_chunk * chunk; /* 8 8 */
> unsigned int rmem_len; /* 16 4 */
> __u32 ppid; /* 20 4 */
> __u32 tsn; /* 24 4 */
> __u32 cumtsn; /* 28 4 */
> __u16 stream; /* 32 2 */
> __u16 ssn; /* 34 2 */
> __u16 flags; /* 36 2 */
> __u16 msg_flags; /* 38 2 */
>
> /* size: 40, cachelines: 1, members: 10 */
> /* last cacheline: 40 bytes */
> };
>
> and after:
> struct sctp_ulpevent {
> struct sctp_association * asoc; /* 0 8 */
> struct sctp_chunk * chunk; /* 8 8 */
> unsigned int rmem_len; /* 16 4 */
> union {
> __u32 mid; /* 4 */
> __u16 ssn; /* 2 */
> }; /* 20 4 */
> union {
> __u32 ppid; /* 4 */
> __u32 fsn; /* 4 */
> }; /* 24 4 */
> __u32 tsn; /* 28 4 */
> __u32 cumtsn; /* 32 4 */
> __u16 stream; /* 36 2 */
> __u16 flags; /* 38 2 */
> __u16 msg_flags; /* 40 2 */
>
> /* size: 42, cachelines: 1, members: 10 */
> /* last cacheline: 42 bytes */
> };
>
> Marcelo
You're right, my bad.
Neil
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v4 net-next] net/tcp: trace all TCP/IP state transition with tcp_set_state tracepoint
From: Yafang Shao @ 2017-12-06 15:01 UTC (permalink / raw)
To: davem, songliubraving, marcelo.leitner
Cc: kuznet, yoshfuji, rostedt, bgregg, netdev, linux-kernel,
Yafang Shao
The TCP/IP transition from TCP_LISTEN to TCP_SYN_RECV and some other
transitions are not traced with tcp_set_state tracepoint.
In order to trace the whole tcp lifespans, two helpers are introduced,
void sk_set_state(struct sock *sk, int state);
void sk_state_store(struct sock *sk, int newstate);
When do TCP/IP state transition, we should use these two helpers or use
tcp_set_state() other than assigning a value to sk_state directly.
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Acked-by: Song Liu <songliubraving@fb.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
v3->v4: Do not trace DCCP socket
v2->v3: Per suggestion from Marcelo Ricardo Leitner, inverting __
to sk_state_store.
---
include/net/sock.h | 8 ++++++--
net/core/sock.c | 16 ++++++++++++++++
net/ipv4/inet_connection_sock.c | 5 +++--
net/ipv4/inet_hashtables.c | 2 +-
net/ipv4/tcp.c | 2 +-
5 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 79e1a2c..1cf7685 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2349,18 +2349,22 @@ static inline int sk_state_load(const struct sock *sk)
}
/**
- * sk_state_store - update sk->sk_state
+ * __sk_state_store - update sk->sk_state
* @sk: socket pointer
* @newstate: new state
*
* Paired with sk_state_load(). Should be used in contexts where
* state change might impact lockless readers.
*/
-static inline void sk_state_store(struct sock *sk, int newstate)
+static inline void __sk_state_store(struct sock *sk, int newstate)
{
smp_store_release(&sk->sk_state, newstate);
}
+/* For tcp_set_state tracepoint */
+void sk_state_store(struct sock *sk, int newstate);
+void sk_set_state(struct sock *sk, int state);
+
void sock_enable_timestamp(struct sock *sk, int flag);
int sock_get_timestamp(struct sock *, struct timeval __user *);
int sock_get_timestampns(struct sock *, struct timespec __user *);
diff --git a/net/core/sock.c b/net/core/sock.c
index c0b5b2f..5d4f6f4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -138,6 +138,7 @@
#include <net/sock_reuseport.h>
#include <trace/events/sock.h>
+#include <trace/events/tcp.h>
#include <net/tcp.h>
#include <net/busy_poll.h>
@@ -2859,6 +2860,21 @@ int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
}
EXPORT_SYMBOL(sock_get_timestampns);
+void sk_state_store(struct sock *sk, int newstate)
+{
+ /* Don't trace DCCP socket */
+ if (sk->sk_type == SOCK_STREAM)
+ trace_tcp_set_state(sk, sk->sk_state, newstate);
+ __sk_state_store(sk, newstate);
+}
+
+void sk_set_state(struct sock *sk, int state)
+{
+ if (sk->sk_type == SOCK_STREAM)
+ trace_tcp_set_state(sk, sk->sk_state, state);
+ sk->sk_state = state;
+}
+
void sock_enable_timestamp(struct sock *sk, int flag)
{
if (!sock_flag(sk, flag)) {
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 4ca46dc..41f9c87 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -783,7 +783,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
if (newsk) {
struct inet_connection_sock *newicsk = inet_csk(newsk);
- newsk->sk_state = TCP_SYN_RECV;
+ sk_set_state(newsk, TCP_SYN_RECV);
newicsk->icsk_bind_hash = NULL;
inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
@@ -888,7 +888,8 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
return 0;
}
- sk->sk_state = TCP_CLOSE;
+ sk_set_state(sk, TCP_CLOSE);
+
return err;
}
EXPORT_SYMBOL_GPL(inet_csk_listen_start);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index f6f5810..5973693 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -544,7 +544,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk)
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
} else {
percpu_counter_inc(sk->sk_prot->orphan_count);
- sk->sk_state = TCP_CLOSE;
+ sk_set_state(sk, TCP_CLOSE);
sock_set_flag(sk, SOCK_DEAD);
inet_csk_destroy_sock(sk);
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1803116..ac98dc6 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2065,7 +2065,7 @@ void tcp_set_state(struct sock *sk, int state)
/* Change state AFTER socket is unhashed to avoid closed
* socket sitting in hash tables.
*/
- sk_state_store(sk, state);
+ __sk_state_store(sk, state);
#ifdef STATE_TRACE
SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n", sk, statename[oldstate], statename[state]);
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next] net: ethernet: ti: cpdma: correct error handling for chan create
From: Ivan Khoronzhuk @ 2017-12-06 14:54 UTC (permalink / raw)
To: grygorii.strashko
Cc: netdev, davem, linux-omap, linux-kernel, Ivan Khoronzhuk
It's not correct to return NULL when that is actually an error and
function returns errors in any other wrong case. In the same time,
the cpsw driver and davinci emac doesn't check error case while
creating channel and it can miss actual error. Correct this mess.
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
drivers/net/ethernet/ti/cpsw.c | 12 +++++++++---
drivers/net/ethernet/ti/davinci_cpdma.c | 2 +-
drivers/net/ethernet/ti/davinci_emac.c | 9 +++++++--
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a60a378..ee58f48 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -3065,10 +3065,16 @@ static int cpsw_probe(struct platform_device *pdev)
}
cpsw->txv[0].ch = cpdma_chan_create(cpsw->dma, 0, cpsw_tx_handler, 0);
+ if (WARN_ON(IS_ERR(cpsw->txv[0].ch))) {
+ dev_err(priv->dev, "error initializing tx dma channel\n");
+ ret = PTR_ERR(cpsw->txv[0].ch);
+ goto clean_dma_ret;
+ }
+
cpsw->rxv[0].ch = cpdma_chan_create(cpsw->dma, 0, cpsw_rx_handler, 1);
- if (WARN_ON(!cpsw->rxv[0].ch || !cpsw->txv[0].ch)) {
- dev_err(priv->dev, "error initializing dma channels\n");
- ret = -ENOMEM;
+ if (WARN_ON(IS_ERR(cpsw->rxv[0].ch))) {
+ dev_err(priv->dev, "error initializing rx dma channel\n");
+ ret = PTR_ERR(cpsw->rxv[0].ch);
goto clean_dma_ret;
}
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index dbe9167..a9fab42 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -893,7 +893,7 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
chan_num = rx_type ? rx_chan_num(chan_num) : tx_chan_num(chan_num);
if (__chan_linear(chan_num) >= ctlr->num_chan)
- return NULL;
+ return ERR_PTR(-EINVAL);
chan = devm_kzalloc(ctlr->dev, sizeof(*chan), GFP_KERNEL);
if (!chan)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index f58c0c6..3d4af64 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1870,10 +1870,15 @@ static int davinci_emac_probe(struct platform_device *pdev)
priv->txchan = cpdma_chan_create(priv->dma, EMAC_DEF_TX_CH,
emac_tx_handler, 0);
+ if (WARN_ON(IS_ERR(priv->txchan))) {
+ rc = PTR_ERR(priv->txchan);
+ goto no_cpdma_chan;
+ }
+
priv->rxchan = cpdma_chan_create(priv->dma, EMAC_DEF_RX_CH,
emac_rx_handler, 1);
- if (WARN_ON(!priv->txchan || !priv->rxchan)) {
- rc = -ENOMEM;
+ if (WARN_ON(IS_ERR(priv->rxchan))) {
+ rc = PTR_ERR(priv->rxchan);
goto no_cpdma_chan;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next] net: ethernet: ti: cpdma: rate is not changed - correct case
From: Ivan Khoronzhuk @ 2017-12-06 14:41 UTC (permalink / raw)
To: grygorii.strashko
Cc: netdev, davem, linux-omap, linux-kernel, Ivan Khoronzhuk
If rate is the same as set it's correct case.
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
Based on net-next/master
drivers/net/ethernet/ti/davinci_cpdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index e4d6edf..dbe9167 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -841,7 +841,7 @@ int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate)
return -EINVAL;
if (ch->rate == rate)
- return rate;
+ return 0;
ctlr = ch->ctlr;
spin_lock_irqsave(&ctlr->lock, flags);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 2/2 v6] net: ethernet: Add a driver for Gemini gigabit ethernet
From: David Miller @ 2017-12-06 14:39 UTC (permalink / raw)
To: linus.walleij
Cc: netdev, mirq-linux, janos.dev, paulius.zaleckas, linux-arm-kernel,
ulli.kroll, f.fainelli, tobias.waldvogel
In-Reply-To: <CACRpkdbbcG8E6OCPb0Hgmp3owZqn2ab3hWEp1auwj-W_hMVbWw@mail.gmail.com>
From: Linus Walleij <linus.walleij@linaro.org>
Date: Wed, 6 Dec 2017 14:02:49 +0100
> On Mon, Dec 4, 2017 at 12:21 AM, David Miller <davem@davemloft.net> wrote:
>
>>> +static irqreturn_t gemini_port_irq_thread(int irq, void *data)
>>> +{
>>> + struct gemini_ethernet_port *port = data;
>>> + struct gemini_ethernet *geth = port->geth;
>>> + unsigned long irqmask = SWFQ_EMPTY_INT_BIT;
>>> + unsigned long flags;
>>
>> Always order local variables in reverse-christmas-tree format,
>> which is longest to shortest line.
>
> It's hard to do in cases like this where I use the variable
> when defining another variable:
>
> struct gemini_ethernet_port *port = netdev_priv(netdev);
> void __iomem *status_reg = port->gmac_base + GMAC_STATUS;
>
> But I understand the aesthetic, so I fix it as well as I can.
>
> If you want me to even rewrite the above using more lines of code
> to keep the aestetic (moving assignment out of the variable
> definitions), tell me and I can fix that too, whatever you like.
Yes, that is the way generally we recommend doing this. Move
the troublesome assignment down into the actual function body.
^ permalink raw reply
* Re: ethtool-copy.h out of sync with linux header file?
From: John W. Linville @ 2017-12-06 14:19 UTC (permalink / raw)
To: Scott Branden; +Cc: Greenwalt, Paul, netdev
In-Reply-To: <418b362a-6a77-1fd8-9df8-056f55cc8f55@broadcom.com>
On Tue, Dec 05, 2017 at 12:25:51PM -0800, Scott Branden wrote:
> Hi Paul,
>
>
> On 17-12-04 01:00 PM, Greenwalt, Paul wrote:
> > John,
> >
> > Can this patch be reverted? As Stephen Hemminger mentioned
> > there is an ABI compatibility issue with this patch:
> I can add the revert into a patch series followed by the sync of
> ethtool-copy.h with net-netx ethtool.h
Yes, exactly. I see that you did just that in your later series
submission.
Thanks!
John
> >
> > https://patchwork.ozlabs.org/patch/806049/#1757846
> >
> > Thanks,
> > Paul
> >
> > > -----Original Message-----
> > > From: Scott Branden [mailto:scott.branden@broadcom.com]
> > > Sent: Monday, December 4, 2017 12:07 PM
> > > To: linville@tuxdriver.com; Greenwalt, Paul <paul.greenwalt@intel.com>
> > > Cc: netdev <netdev@vger.kernel.org>
> > > Subject: ethtool-copy.h out of sync with linux header file?
> > >
> > > Hi Paul/John,
> > >
> > > I see a commit "ethtool: Add DMA Coalescing support" was added to
> > > ethtool-copy.h yet I cannot find the change in the ethtool.h in the
> > > linux kernel.
> > >
> > > As such, I am unable to commit a change to ethtool-copy.h to sync it
> > > with net-next. If I sync then ethtool will fail to compile.
> > >
> > > Please advise.
> > >
> > > Thanks,
> > >
> > > Scott
> > >
> > >
>
>
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* [PATCH] net: mvmdio: disable/unprepare clocks in EPROBE_DEFER case
From: Tobias Jordan @ 2017-12-06 14:23 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ldv-project
add appropriate calls to clk_disable_unprepare() by jumping to out_mdio
in case orion_mdio_probe() returns -EPROBE_DEFER.
Found by Linux Driver Verification project (linuxtesting.org).
Fixes: 3d604da1e954 net: mvmdio: get and enable optional clock
Signed-off-by: Tobias Jordan <Tobias.Jordan@elektrobit.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index c9798210fa0f..0495487f7b42 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -344,7 +344,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
dev->regs + MVMDIO_ERR_INT_MASK);
} else if (dev->err_interrupt == -EPROBE_DEFER) {
- return -EPROBE_DEFER;
+ ret = -EPROBE_DEFER;
+ goto out_mdio;
}
if (pdev->dev.of_node)
--
2.11.0
^ permalink raw reply related
* Re: [PATCH V2] selinux: Add SCTP support
From: Paul Moore @ 2017-12-06 14:15 UTC (permalink / raw)
To: Marcelo Ricardo Leitner
Cc: Richard Haines, selinux, netdev, linux-sctp,
linux-security-module, Vlad Yasevich, nhorman, Stephen Smalley,
Eric Paris
In-Reply-To: <20171206124638.GD3328@localhost.localdomain>
On Wed, Dec 6, 2017 at 7:46 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Wed, Dec 06, 2017 at 10:17:36AM +0000, Richard Haines wrote:
>> The SELinux SCTP implementation is explained in:
>> Documentation/security/SELinux-sctp.rst
>>
>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>> ---
>> V2 Changes
>> Remove lock from selinux_sctp_assoc_request()
>> Fix selinux_sctp_sk_clone() kbuild test robot catch [1]
>>
>> [1] https://marc.info/?l=selinux&m=151198281817779&w=2
>>
>
> Is this patchset going in via netdev tree or selinux one?
> I see Dave is tracking the v1
> (http://patchwork.ozlabs.org/patch/841842/) so I'm thinking netdev but
> for netdev it would require a repost of the entire patchset, even if
> the first ones weren't changed.
This should go in via the SELinux tree, although I would like to see
ACKs from Dave and/or other netdev folks for the core stack bits.
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [PATCH] ptr_ring: Add barriers to fix NULL-pointer exception
From: Cherian, George @ 2017-12-06 14:08 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
virtualization@lists.linux-foundation.org, edumazet@google.com,
davem@davemloft.net
In-Reply-To: <20171206153349-mutt-send-email-mst@kernel.org>
[-- Attachment #1.1: Type: text/plain, Size: 9391 bytes --]
Hi Michael,
_____________________________
From: Michael S. Tsirkin <mst@redhat.com>
Sent: Wednesday, December 6, 2017 7:05 PM
Subject: Re: [PATCH] ptr_ring: Add barriers to fix NULL-pointer exception
To: Cherian, George <george.cherian@cavium.com>
Cc: <linux-kernel@vger.kernel.org>, <davem@davemloft.net>, <jasowang@redhat.com>, <edumazet@google.com>, <netdev@vger.kernel.org>, <virtualization@lists.linux-foundation.org>
On Wed, Dec 06, 2017 at 09:57:41AM +0000, George Cherian wrote:
> While running a multiple VM testscase with each VM running iperf
> traffic between others the following kernel NULL pointer exception
> was seen.
>
> Race appears when the tun driver instance of one VM calls skb_array_produce
> (from tun_net_xmit) and the the destined VM's skb_array_consume
> (from tun_ring_recv), which could run concurrently on another core. Due to
> which the sock_wfree gets called again from the tun_ring_recv context.
>
> The fix is to add write/read barrier calls to be sure that we get proper
> values in the tun_ring_recv context.
>
> Crash log
> [35321.580227] Unable to handle kernel NULL pointer dereference at virtual address 00000060
> [35321.596720] pgd = ffff809ee552f000
> [35321.603723] [00000060] *pgd=0000009f514ac003, *pud=0000009f54f7c003, *pmd=0000000000000000
> [35321.620588] Internal error: Oops: 96000006 1 SMP
> [35321.630461] Modules linked in: xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_4
> [35321.728501] CPU: 114 PID: 5560 Comm: qemu-system-aar Not tainted 4.11.8-4k-vhe-lse+ #3
> [35321.744510] Hardware name: Cavium Inc. Unknown/Unknown, BIOS 1.0 07/24/2017
> [35321.758602] task: ffff80bed7fca880 task.stack: ffff80beb5128000
> [35321.770600] PC is at sock_wfree+0x24/0x80
> [35321.778746] LR is at skb_release_head_state+0x68/0xf8
> [35321.788979] pc : [<ffff000008a772fc>] lr : [<ffff000008a79238>] pstate: 40400149
> [35321.803930] sp : ffff80beb512bc30
> [35321.810648] x29: ffff80beb512bc30 x28: ffff80bed7fca880
> [35321.821400] x27: 000000000000004e x26: 0000000000000000
> [35321.832156] x25: 000000000000000c x24: 0000000000000000
> [35321.842947] x23: ffff809ece3e4900 x22: ffff80beb512be00
> [35321.853729] x21: ffff000009138000 x20: 0000000000000144
> [35321.864507] x19: 0000000000000000 x18: 0000000000000014
> [35321.875276] x17: 0000ffff9d9689a0 x16: ffff00000828b3f8
> [35321.886048] x15: 0000504d7b000000 x14: e90ab50c48680a08
> [35321.896824] x13: 0101000017773f52 x12: 1080d422c00e5db6
> [35321.907595] x11: 68c322bd3930cf7a x10: a8c0d07aa8c0ad16
> [35321.918352] x9 : 000000001da4ed90 x8 : b50c48680a080101
> [35321.929099] x7 : 000017770c521080 x6 : 000000001d6c13f2
> [35321.939865] x5 : 000000001d6c13f2 x4 : 000000000000000e
> [35321.950619] x3 : 000000085ff97d82 x2 : 0000000000000000
> [35321.961376] x1 : ffff000008a772d8 x0 : 0000000000000500
> [35321.975193] Process qemu-system-aar (pid: 5560, stack limit = 0xffff80beb5128000)
> [35321.990347] Stack: (0xffff80beb512bc30 to 0xffff80beb512c000)
> [35322.001982] bc20: ffff80beb512bc50 ffff000008a79238
> [35322.017817] bc40: ffff809e8fd7be00 000000000000004e ffff80beb512bc70 ffff000008a79488
> [35322.033651] bc60: ffff809e8fd7be00 ffff00000881307c ffff80beb512bc90 ffff000008a79678
> [35322.049489] bc80: ffff809e8fd7be00 ffff80beb512be00 ffff80beb512bcb0 ffff000008812f24
> [35322.065321] bca0: ffff809e8fd7be00 000000000000004e ffff80beb512bd50 ffff0000088133f0
> [35322.081165] bcc0: ffff809ece3e4900 0000000000011000 ffff80beb512bdd8 ffff80beb512be00
> [35322.097001] bce0: 000000001d6c13a4 0000000000000015 0000000000000124 000000000000003f
> [35322.112866] bd00: ffff000008bc2000 ffff00000847b5ac 0000000000020000 ffff80be00080000
> [35322.128701] bd20: 0022000000000001 ffff80bed7fc0010 ffff000008100c38 0000000000000000
> [35322.144539] bd40: 0000000000000000 0000000000040b08 ffff80beb512bd80 ffff000008288f80
> [35322.160395] bd60: ffff000009138000 ffff809ee7cd3500 0000000000011000 ffff80beb512beb0
> [35322.176255] bd80: ffff80beb512be30 ffff00000828a224 0000000000011000 ffff809ee7cd3500
> [35322.192109] bda0: 000000001d6c13a4 ffff80beb512beb0 0000000000011000 0000000000000000
> [35322.207974] bdc0: 0000000000000000 000000001d6c13a4 0000000000011000 ffff809ee7cd3500
> [35322.223822] bde0: 000000000000004e 0000000000000000 0000000000000000 0000000000000000
> [35322.239661] be00: ffff80be00000000 000000000000004e 0000000000010fb2 ffff80beb512bdc8
> [35322.255519] be20: 0000000000000001 0000000000040b08 ffff80beb512be70 ffff00000828b464
> [35322.271392] be40: ffff000009138000 ffff809ee7cd3501 ffff809ee7cd3500 000000001d6c13a4
> [35322.287255] be60: 0000000000011000 0000000000000015 0000000000000000 ffff0000080833f0
> [35322.303090] be80: 0000000000000000 000080bef0071000 ffffffffffffffff 0000ffff9d9689cc
> [35322.318951] bea0: 0000000080000000 000080bef0071000 000000000000004e 0000000000040b08
> [35322.334771] bec0: 000000000000000e 000000001d6c13a4 0000000000011000 0000ffff9cc89108
> [35322.350640] bee0: 0000000000000002 0000ffff9cc89000 0000ffff9cc896f0 0000000000000000
> [35322.366500] bf00: 000000000000003f 000000001da4ed90 a8c0d07aa8c0ad16 68c322bd3930cf7a
> [35322.382358] bf20: 1080d422c00e5db6 0101000017773f52 e90ab50c48680a08 0000504d7b000000
> [35322.398209] bf40: 0000000000000000 0000ffff9d9689a0 0000000000000014 0000000000000030
> [35322.414063] bf60: 000000001d6c13a4 000000001d6c0db0 000000001d6d1db0 00000000006fbbc8
> [35322.429901] bf80: 0000000000011000 000000001d6ab3e8 000000001d6ab3a4 00000000007ee4c8
> [35322.445751] bfa0: 0000000000000000 0000fffff363ab70 0000ffff9d9689b8 0000fffff363ab30
> [35322.461588] bfc0: 0000ffff9d9689cc 0000000080000000 000000000000000e 000000000000003f
> [35322.477445] bfe0: 0000000000000000 0000000000000000 ffff809ed043d758 0000000000000000
> [35322.493283] Call trace:
> [35322.498275] Exception stack(0xffff80beb512ba40 to 0xffff80beb512bb70)
> [35322.511303] ba40: 0000000000000000 0001000000000000 ffff80beb512bc30 ffff000008a772fc
> [35322.527152] ba60: 0000000040400149 0000000000000049 ffff000008bc2000 ffff80bed7fca880
> [35322.542992] ba80: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> [35322.558863] baa0: 0000000000000000 000000001d895758 ffff80beb512bb78 0000000000000000
> [35322.574702] bac0: 000000050000000b 0000000800000001 0000000a00000001 0000000b00000001
> [35322.590550] bae0: 0000000e00000001 0000001800010001 ffff80beb512bbf0 0000000000040b08
> [35322.606416] bb00: 0000000000000500 ffff000008a772d8 0000000000000000 000000085ff97d82
> [35322.622287] bb20: 000000000000000e 000000001d6c13f2 000000001d6c13f2 000017770c521080
> [35322.638144] bb40: b50c48680a080101 000000001da4ed90 a8c0d07aa8c0ad16 68c322bd3930cf7a
> [35322.653992] bb60: 1080d422c00e5db6 0101000017773f52
> [35322.663908] [<ffff000008a772fc>] sock_wfree+0x24/0x80
> [35322.674168] [<ffff000008a79238>] skb_release_head_state+0x68/0xf8
> [35322.686535] [<ffff000008a79488>] skb_release_all+0x20/0x40
> [35322.697663] [<ffff000008a79678>] consume_skb+0x38/0xd8
> [35322.708120] [<ffff000008812f24>] tun_do_read.part.9+0x20c/0x4f0
> [35322.720149] [<ffff0000088133f0>] tun_chr_read_iter+0xc0/0xe0
> [35322.731638] [<ffff000008288f80>] __vfs_read+0x100/0x160
> [35322.742249] [<ffff00000828a224>] vfs_read+0x8c/0x148
> [35322.752344] [<ffff00000828b464>] SyS_read+0x6c/0xd8
> [35322.762263] [<ffff0000080833f0>] el0_svc_naked+0x24/0x28
> [35322.773042] Code: d503201f f9400e93 b940e280 91051274 (f9403261)
>
> Reported-by: Joseph DeVincentis <Joseph.DeVincentis@cavium.com>
> Signed-off-by: George Cherian <george.cherian@cavium.com>
> ---
> include/linux/ptr_ring.h | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
> index 37b4bb2..bc3b36b 100644
> --- a/include/linux/ptr_ring.h
> +++ b/include/linux/ptr_ring.h
> @@ -106,6 +106,12 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr)
> {
> if (unlikely(!r->size) || r->queue[r->producer])
> return -ENOSPC;
> + /*
> + * This barrier is necessary in order to prevent race condition with
> + * with __ptr_ring_consume(). By this we make sure all the prior
> + * writes to *ptr elements are updated.
> + */
> + wmb();
>
> r->queue[r->producer++] = ptr;
> if (unlikely(r->producer >= r->size))
> @@ -275,6 +281,13 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r)
> if (ptr)
> __ptr_ring_discard_one(r);
>
> + /*
> + * This barrier is necessary in order to prevent race condition with
> + * with __ptr_ring_produce(). Make sure all the elements of ptr is
> + * in sync with the earlier writes which was done prior to pushing
> + * it to ring
> + */
> + rmb();
> return ptr;
> }
You are trying to synchronise two CPUs so non-smp barriers make no
sense. wmb/rmb are for synchronising with MMIO.
What happens when CONFIG_SMP is not set. smp_wmb/rmb becomes compiler barriers(atleast for arm64). I guess that is not what we need. An SMP barrier cannot replace a mandatory barrier, but a mandatory barrier can replace an SMP barrier.
I will try out your patch too and update the results.
But I would need couple of days time. Sorry for the delay.
> --
> 2.1.4
[-- Attachment #1.2: Type: text/html, Size: 11619 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH v2] vsock.7: document VSOCK socket address family
From: Jorgen S. Hansen @ 2017-12-06 14:06 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: linux-man@vger.kernel.org, netdev@vger.kernel.org,
G. Branden Robinson, Dexuan Cui
In-Reply-To: <20171205105618.30049-1-stefanha@redhat.com>
> On Dec 5, 2017, at 11:56 AM, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> The AF_VSOCK address family has been available since Linux 3.9 without a
> corresponding man page.
>
> This patch adds vsock.7 and describes its use along the same lines as
> existing ip.7, unix.7, and netlink.7 man pages.
>
> CC: Jorgen Hansen <jhansen@vmware.com>
> CC: Dexuan Cui <decui@microsoft.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> man7/vsock.7 | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 180 insertions(+)
> create mode 100644 man7/vsock.7
>
> diff --git a/man7/vsock.7 b/man7/vsock.7
> new file mode 100644
> index 000000000..46dc561f5
> --- /dev/null
> +++ b/man7/vsock.7
> @@ -0,0 +1,180 @@
> +.TH VSOCK 7 2017-11-30 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +vsock \- Linux VSOCK address family
> +.SH SYNOPSIS
> +.B #include <sys/socket.h>
> +.br
> +.B #include <linux/vm_sockets.h>
> +.PP
> +.IB stream_socket " = socket(AF_VSOCK, SOCK_STREAM, 0);"
> +.br
> +.IB datagram_socket " = socket(AF_VSOCK, SOCK_DGRAM, 0);"
> +.SH DESCRIPTION
> +The VSOCK address family facilitates communication between virtual machines and
> +the host they are running on. This address family is used by guest agents and
> +hypervisor services that need a communications channel that is independent of
> +virtual machine network configuration.
> +.PP
> +Valid socket types are
> +.B SOCK_STREAM
> +and
> +.BR SOCK_DGRAM .
> +.B SOCK_STREAM
> +provides connection-oriented byte streams with guaranteed, in-order delivery.
> +.B SOCK_DGRAM
> +provides a connectionless datagram packet service with best-effort delivery and
> +best-effort ordering. Availability of these socket types is dependent on the
> +underlying hypervisor.
> +.PP
> +A new socket is created with
> +.PP
> + socket(AF_VSOCK, socket_type, 0);
> +.PP
> +When a process wants to establish a connection it calls
> +.BR connect (2)
> +with a given destination socket address. The socket is automatically bound to
> +a free port if unbound.
> +.PP
> +A process can listen for incoming connections by first binding to a socket
> +address using
> +.BR bind (2)
> +and then calling
> +.BR listen (2).
> +.PP
> +Data is transferred using the usual
> +.BR send (2)
> +and
> +.BR recv (2)
> +family of socket system calls.
> +.SS Address format
> +A socket address is defined as a combination of a 32-bit Context Identifier
> +(CID) and a 32-bit port number. The CID identifies the source or destination,
> +which is either a virtual machine or the host. The port number differentiates
> +between multiple services running on a single machine.
> +.PP
> +.in +4n
> +.EX
> +struct sockaddr_vm {
> + sa_family_t svm_family; /* address family: AF_VSOCK */
> + unsigned short svm_reserved1;
> + unsigned int svm_port; /* port in native byte order */
> + unsigned int svm_cid; /* address in native byte order */
> +};
> +.EE
> +.in
> +.PP
> +.I svm_family
> +is always set to
> +.BR AF_VSOCK .
> +.I svm_reserved1
> +is always set to 0.
> +.I svm_port
> +contains the port in native byte order.
> +The port numbers below 1024 are called
> +.IR "privileged ports" .
> +Only a process with
> +.B CAP_NET_BIND_SERVER
> +capability may
> +.BR bind (2)
> +to these port numbers.
> +.PP
> +There are several special addresses:
> +.B VMADDR_CID_ANY
> +(-1U)
> +means any address for binding;
> +.B VMADDR_CID_HYPERVISOR
> +(0) is reserved for services built into the hypervisor;
> +.B VMADDR_CID_RESERVED
> +(1) must not be used;
> +.B VMADDR_CID_HOST
> +(2)
> +is the well-known address of the host.
> +.PP
> +The special constant
> +.B VMADDR_PORT_ANY
> +(-1U)
> +means any port number for binding.
> +.SS Live migration
> +Sockets are affected by live migration of virtual machines. Connected
> +.B SOCK_STREAM
> +sockets become disconnected when the virtual machine migrates to a new host.
> +Applications must reconnect when this happens.
> +.PP
> +The local CID may change across live migration if the old CID is not available
> +on the new host. Bound sockets are automatically updated to the new CID.
> +.SS Ioctls
> +.TP
> +.B IOCTL_VM_SOCKETS_GET_LOCAL_CID
> +Get the CID of the local machine. The argument is a pointer to an unsigned int.
> +.IP
> +.in +4n
> +.EX
> +.IB error " = ioctl(" socket ", " IOCTL_VM_SOCKETS_GET_LOCAL_CID ", " &cid ");"
> +.EE
> +.in
> +.IP
> +Consider using
> +.B VMADDR_CID_ANY
> +when binding instead of getting the local CID with
> +.BR IOCTL_VM_SOCKETS_GET_LOCAL_CID .
> +.SH ERRORS
> +.TP
> +.B EACCES
> +Unable to bind to a privileged port without the
> +.B CAP_NET_BIND_SERVICE
> +capability.
> +.TP
> +.B EINVAL
> +Invalid parameters. This includes:
> +attempting to bind a socket that is already bound, providing an invalid struct
> +.BR sockaddr_vm ,
> +and other input validation errors.
> +.TP
> +.B EOPNOTSUPP
> +Operation not supported. This includes:
> +the
> +.B MSG_OOB
> +flag that is not implemented for
> +.BR sendmsg (2)
> +and
> +.B MSG_PEEK
> +for
> +.BR recvmsg (2).
> +.TP
> +.B EADDRINUSE
> +Unable to bind to a port that is already in use.
> +.TP
> +.B EADDRNOTAVAIL
> +Unable to find a free port for binding or unable to bind to a non-local CID.
> +.TP
> +.B ENOTCONN
> +Unable to perform operation on an unconnected socket.
> +.TP
> +.B ENOPROTOOPT
> +Invalid socket option in
> +.BR setsockopt (2)
> +or
> +.BR getsockopt (2).
> +.TP
> +.B EPROTONOSUPPORT
> +Invalid socket protocol number. Protocol should always be 0.
> +.TP
> +.B ESOCKTNOSUPPORT
> +Unsupported socket type in
> +.BR socket (2).
> +Only
> +.B SOCK_STREAM
> +and
> +.B SOCK_DGRAM
> +are valid.
> +.SH VERSIONS
> +Support for VMware (VMCI) has been available since Linux 3.9. KVM (virtio) is
> +supported since Linux 4.8. Hyper-V is supported since 4.14.
> +.SH SEE ALSO
> +.BR socket (2),
> +.BR bind (2),
> +.BR connect (2),
> +.BR listen (2),
> +.BR send (2),
> +.BR recv (2),
> +.BR capabilities (7)
> --
> 2.14.3
>
Looks great to me. Thanks for doing this. I don’t have anything to add.
Reviewed-by: Jorgen Hansen <jhansen@vmware.com>
^ permalink raw reply
* Re: dsa: dsa_slave_port_obj_del calls multiple times with SWITCHDEV_OBJ_ID_HOST_MDB obj id
From: Andrew Lunn @ 2017-12-06 13:56 UTC (permalink / raw)
To: Tristram.Ha; +Cc: f.fainelli, netdev, UNGLinuxDriver
In-Reply-To: <93AF473E2DA327428DE3D46B72B1E9FD4113DE40@CHN-SV-EXMX02.mchp-main.com>
On Wed, Dec 06, 2017 at 02:33:07AM +0000, Tristram.Ha@microchip.com wrote:
> I found the latest net-next kernel calls dsa_slave_port_obj_del() multiple times,
> one for each port, with host port as the parameter.
Hi Tristram
SWITCHDEV_OBJ_ID_HOST_MDB is used, when there is a join/leave on the
bridge interface. It happens for each interface in the bridge, and it
means, packets which match the group that ingress on that interface
should be forwarded to the CPU.
> As the base driver cannot find an entry with that host port, it returns an error
> and so users will see a lot of failures from the DSA switch.
You have a few options:
1) Just forward all multicast traffic to the cpu, and ignore
SWITCHDEV_OBJ_ID_HOST_MDB.
2) Implement SWITCHDEV_OBJ_ID_HOST_MDB so you setup your tables to
just forward the requested multicast to the cpu.
3) You can also forward a bit too much, e.g. if you cannot set filters
per ingress port, just send all the traffic for the group from any
port.
The bridge will discard whatever it does not need.
> Is this a new behavior and the driver needs to handle that? In previous versions
> I do not think I saw that.
SWITCHDEV_OBJ_ID_HOST_MDB is new. However, dsa_slave_port_obj_del()
can be called for all sorts of objects, and you should only be
reacting on those your support. So adding a new object should not of
changed anything.
> Typical operation is a PC connected to a port in a switch wants to send multicast
> packets. It broadcasts an IGMP membership join message. Function
> dsa_slave_port_obj_add is called to setup an entry in the lookup table. When
> IGMP membership leave message is received dsa_slave_port_obj_del will be
> called after a delay. But then it is called for each port with host port as the
> parameter.
Correct. switchdev is a generic API. It also needs to work for Top of
Rack switches, which generally have a match/action architecture. I can
imagine that this match/action happens per port, so we need to call
switchdev per port. However, switches supported by DSA tend to have
central management of all ports, so one call would be sufficient. With
a DSA driver, you just need to expect redundant calls, and do the
right thing.
Andrew
^ permalink raw reply
* Re: [PATCH] ptr_ring: Add barriers to fix NULL-pointer exception
From: Michael S. Tsirkin @ 2017-12-06 13:35 UTC (permalink / raw)
To: George Cherian; +Cc: netdev, linux-kernel, virtualization, edumazet, davem
In-Reply-To: <1512554261-5030-1-git-send-email-george.cherian@cavium.com>
On Wed, Dec 06, 2017 at 09:57:41AM +0000, George Cherian wrote:
> While running a multiple VM testscase with each VM running iperf
> traffic between others the following kernel NULL pointer exception
> was seen.
>
> Race appears when the tun driver instance of one VM calls skb_array_produce
> (from tun_net_xmit) and the the destined VM's skb_array_consume
> (from tun_ring_recv), which could run concurrently on another core. Due to
> which the sock_wfree gets called again from the tun_ring_recv context.
>
> The fix is to add write/read barrier calls to be sure that we get proper
> values in the tun_ring_recv context.
>
> Crash log
> [35321.580227] Unable to handle kernel NULL pointer dereference at virtual address 00000060
> [35321.596720] pgd = ffff809ee552f000
> [35321.603723] [00000060] *pgd=0000009f514ac003, *pud=0000009f54f7c003, *pmd=0000000000000000
> [35321.620588] Internal error: Oops: 96000006 1 SMP
> [35321.630461] Modules linked in: xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_4
> [35321.728501] CPU: 114 PID: 5560 Comm: qemu-system-aar Not tainted 4.11.8-4k-vhe-lse+ #3
> [35321.744510] Hardware name: Cavium Inc. Unknown/Unknown, BIOS 1.0 07/24/2017
> [35321.758602] task: ffff80bed7fca880 task.stack: ffff80beb5128000
> [35321.770600] PC is at sock_wfree+0x24/0x80
> [35321.778746] LR is at skb_release_head_state+0x68/0xf8
> [35321.788979] pc : [<ffff000008a772fc>] lr : [<ffff000008a79238>] pstate: 40400149
> [35321.803930] sp : ffff80beb512bc30
> [35321.810648] x29: ffff80beb512bc30 x28: ffff80bed7fca880
> [35321.821400] x27: 000000000000004e x26: 0000000000000000
> [35321.832156] x25: 000000000000000c x24: 0000000000000000
> [35321.842947] x23: ffff809ece3e4900 x22: ffff80beb512be00
> [35321.853729] x21: ffff000009138000 x20: 0000000000000144
> [35321.864507] x19: 0000000000000000 x18: 0000000000000014
> [35321.875276] x17: 0000ffff9d9689a0 x16: ffff00000828b3f8
> [35321.886048] x15: 0000504d7b000000 x14: e90ab50c48680a08
> [35321.896824] x13: 0101000017773f52 x12: 1080d422c00e5db6
> [35321.907595] x11: 68c322bd3930cf7a x10: a8c0d07aa8c0ad16
> [35321.918352] x9 : 000000001da4ed90 x8 : b50c48680a080101
> [35321.929099] x7 : 000017770c521080 x6 : 000000001d6c13f2
> [35321.939865] x5 : 000000001d6c13f2 x4 : 000000000000000e
> [35321.950619] x3 : 000000085ff97d82 x2 : 0000000000000000
> [35321.961376] x1 : ffff000008a772d8 x0 : 0000000000000500
> [35321.975193] Process qemu-system-aar (pid: 5560, stack limit = 0xffff80beb5128000)
> [35321.990347] Stack: (0xffff80beb512bc30 to 0xffff80beb512c000)
> [35322.001982] bc20: ffff80beb512bc50 ffff000008a79238
> [35322.017817] bc40: ffff809e8fd7be00 000000000000004e ffff80beb512bc70 ffff000008a79488
> [35322.033651] bc60: ffff809e8fd7be00 ffff00000881307c ffff80beb512bc90 ffff000008a79678
> [35322.049489] bc80: ffff809e8fd7be00 ffff80beb512be00 ffff80beb512bcb0 ffff000008812f24
> [35322.065321] bca0: ffff809e8fd7be00 000000000000004e ffff80beb512bd50 ffff0000088133f0
> [35322.081165] bcc0: ffff809ece3e4900 0000000000011000 ffff80beb512bdd8 ffff80beb512be00
> [35322.097001] bce0: 000000001d6c13a4 0000000000000015 0000000000000124 000000000000003f
> [35322.112866] bd00: ffff000008bc2000 ffff00000847b5ac 0000000000020000 ffff80be00080000
> [35322.128701] bd20: 0022000000000001 ffff80bed7fc0010 ffff000008100c38 0000000000000000
> [35322.144539] bd40: 0000000000000000 0000000000040b08 ffff80beb512bd80 ffff000008288f80
> [35322.160395] bd60: ffff000009138000 ffff809ee7cd3500 0000000000011000 ffff80beb512beb0
> [35322.176255] bd80: ffff80beb512be30 ffff00000828a224 0000000000011000 ffff809ee7cd3500
> [35322.192109] bda0: 000000001d6c13a4 ffff80beb512beb0 0000000000011000 0000000000000000
> [35322.207974] bdc0: 0000000000000000 000000001d6c13a4 0000000000011000 ffff809ee7cd3500
> [35322.223822] bde0: 000000000000004e 0000000000000000 0000000000000000 0000000000000000
> [35322.239661] be00: ffff80be00000000 000000000000004e 0000000000010fb2 ffff80beb512bdc8
> [35322.255519] be20: 0000000000000001 0000000000040b08 ffff80beb512be70 ffff00000828b464
> [35322.271392] be40: ffff000009138000 ffff809ee7cd3501 ffff809ee7cd3500 000000001d6c13a4
> [35322.287255] be60: 0000000000011000 0000000000000015 0000000000000000 ffff0000080833f0
> [35322.303090] be80: 0000000000000000 000080bef0071000 ffffffffffffffff 0000ffff9d9689cc
> [35322.318951] bea0: 0000000080000000 000080bef0071000 000000000000004e 0000000000040b08
> [35322.334771] bec0: 000000000000000e 000000001d6c13a4 0000000000011000 0000ffff9cc89108
> [35322.350640] bee0: 0000000000000002 0000ffff9cc89000 0000ffff9cc896f0 0000000000000000
> [35322.366500] bf00: 000000000000003f 000000001da4ed90 a8c0d07aa8c0ad16 68c322bd3930cf7a
> [35322.382358] bf20: 1080d422c00e5db6 0101000017773f52 e90ab50c48680a08 0000504d7b000000
> [35322.398209] bf40: 0000000000000000 0000ffff9d9689a0 0000000000000014 0000000000000030
> [35322.414063] bf60: 000000001d6c13a4 000000001d6c0db0 000000001d6d1db0 00000000006fbbc8
> [35322.429901] bf80: 0000000000011000 000000001d6ab3e8 000000001d6ab3a4 00000000007ee4c8
> [35322.445751] bfa0: 0000000000000000 0000fffff363ab70 0000ffff9d9689b8 0000fffff363ab30
> [35322.461588] bfc0: 0000ffff9d9689cc 0000000080000000 000000000000000e 000000000000003f
> [35322.477445] bfe0: 0000000000000000 0000000000000000 ffff809ed043d758 0000000000000000
> [35322.493283] Call trace:
> [35322.498275] Exception stack(0xffff80beb512ba40 to 0xffff80beb512bb70)
> [35322.511303] ba40: 0000000000000000 0001000000000000 ffff80beb512bc30 ffff000008a772fc
> [35322.527152] ba60: 0000000040400149 0000000000000049 ffff000008bc2000 ffff80bed7fca880
> [35322.542992] ba80: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> [35322.558863] baa0: 0000000000000000 000000001d895758 ffff80beb512bb78 0000000000000000
> [35322.574702] bac0: 000000050000000b 0000000800000001 0000000a00000001 0000000b00000001
> [35322.590550] bae0: 0000000e00000001 0000001800010001 ffff80beb512bbf0 0000000000040b08
> [35322.606416] bb00: 0000000000000500 ffff000008a772d8 0000000000000000 000000085ff97d82
> [35322.622287] bb20: 000000000000000e 000000001d6c13f2 000000001d6c13f2 000017770c521080
> [35322.638144] bb40: b50c48680a080101 000000001da4ed90 a8c0d07aa8c0ad16 68c322bd3930cf7a
> [35322.653992] bb60: 1080d422c00e5db6 0101000017773f52
> [35322.663908] [<ffff000008a772fc>] sock_wfree+0x24/0x80
> [35322.674168] [<ffff000008a79238>] skb_release_head_state+0x68/0xf8
> [35322.686535] [<ffff000008a79488>] skb_release_all+0x20/0x40
> [35322.697663] [<ffff000008a79678>] consume_skb+0x38/0xd8
> [35322.708120] [<ffff000008812f24>] tun_do_read.part.9+0x20c/0x4f0
> [35322.720149] [<ffff0000088133f0>] tun_chr_read_iter+0xc0/0xe0
> [35322.731638] [<ffff000008288f80>] __vfs_read+0x100/0x160
> [35322.742249] [<ffff00000828a224>] vfs_read+0x8c/0x148
> [35322.752344] [<ffff00000828b464>] SyS_read+0x6c/0xd8
> [35322.762263] [<ffff0000080833f0>] el0_svc_naked+0x24/0x28
> [35322.773042] Code: d503201f f9400e93 b940e280 91051274 (f9403261)
>
> Reported-by: Joseph DeVincentis <Joseph.DeVincentis@cavium.com>
> Signed-off-by: George Cherian <george.cherian@cavium.com>
> ---
> include/linux/ptr_ring.h | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
> index 37b4bb2..bc3b36b 100644
> --- a/include/linux/ptr_ring.h
> +++ b/include/linux/ptr_ring.h
> @@ -106,6 +106,12 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr)
> {
> if (unlikely(!r->size) || r->queue[r->producer])
> return -ENOSPC;
> + /*
> + * This barrier is necessary in order to prevent race condition with
> + * with __ptr_ring_consume(). By this we make sure all the prior
> + * writes to *ptr elements are updated.
> + */
> + wmb();
>
> r->queue[r->producer++] = ptr;
> if (unlikely(r->producer >= r->size))
> @@ -275,6 +281,13 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r)
> if (ptr)
> __ptr_ring_discard_one(r);
>
> + /*
> + * This barrier is necessary in order to prevent race condition with
> + * with __ptr_ring_produce(). Make sure all the elements of ptr is
> + * in sync with the earlier writes which was done prior to pushing
> + * it to ring
> + */
> + rmb();
> return ptr;
> }
You are trying to synchronise two CPUs so non-smp barriers make no
sense. wmb/rmb are for synchronising with MMIO.
> --
> 2.1.4
^ permalink raw reply
* [PATCH net-next v3 2/2] net: thunderx: add timestamping support
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney,
Sunil Goutham
In-Reply-To: <20171206133100.26436-1-aleksey.makarov@cavium.com>
From: Sunil Goutham <sgoutham@cavium.com>
This adds timestamping support for both receive and transmit
paths. On the receive side no filters are supported i.e either
all pkts will get a timestamp appended infront of the packet or none.
On the transmit side HW doesn't support timestamp insertion but
only generates a separate CQE with transmitted packet's timestamp.
Also HW supports only one packet at a time for timestamping on the
transmit side.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
drivers/net/ethernet/cavium/Kconfig | 1 +
drivers/net/ethernet/cavium/thunder/nic.h | 15 ++
drivers/net/ethernet/cavium/thunder/nic_main.c | 58 ++++++-
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 +++-
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 173 ++++++++++++++++++++-
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 26 ++++
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 29 ++++
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 4 +
9 files changed, 330 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index fabe0ffcc2d4..6d003cbe197c 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -27,6 +27,7 @@ config THUNDER_NIC_PF
config THUNDER_NIC_VF
tristate "Thunder Virtual function driver"
+ select CAVIUM_PTP
depends on 64BIT
---help---
This driver supports Thunder's NIC virtual function
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 4a02e618e318..204b234beb9d 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -263,6 +263,8 @@ struct nicvf_drv_stats {
struct u64_stats_sync syncp;
};
+struct cavium_ptp;
+
struct nicvf {
struct nicvf *pnicvf;
struct net_device *netdev;
@@ -312,6 +314,12 @@ struct nicvf {
struct tasklet_struct qs_err_task;
struct work_struct reset_task;
+ /* PTP timestamp */
+ struct cavium_ptp *ptp_clock;
+ bool hw_rx_tstamp;
+ struct sk_buff *ptp_skb;
+ atomic_t tx_ptp_skbs;
+
/* Interrupt coalescing settings */
u32 cq_coalesce_usecs;
u32 msg_enable;
@@ -371,6 +379,7 @@ struct nicvf {
#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */
#define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */
#define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */
+#define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */
#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
@@ -521,6 +530,11 @@ struct pfc {
u8 fc_tx;
};
+struct set_ptp {
+ u8 msg;
+ bool enable;
+};
+
/* 128 bit shared memory between PF and each VF */
union nic_mbx {
struct { u8 msg; } msg;
@@ -540,6 +554,7 @@ union nic_mbx {
struct set_loopback lbk;
struct reset_stat_cfg reset_stat;
struct pfc pfc;
+ struct set_ptp ptp;
};
#define NIC_NODE_ID_MASK 0x03
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 8f1dd55b3e08..4c1c5414a162 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -426,13 +426,22 @@ static void nic_init_hw(struct nicpf *nic)
/* Enable backpressure */
nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03);
- /* TNS and TNS bypass modes are present only on 88xx */
+ /* TNS and TNS bypass modes are present only on 88xx
+ * Also offset of this CSR has changed in 81xx and 83xx.
+ */
if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) {
/* Disable TNS mode on both interfaces */
nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG,
- (NIC_TNS_BYPASS_MODE << 7) | BGX0_BLOCK);
+ (NIC_TNS_BYPASS_MODE << 7) |
+ BGX0_BLOCK | (1ULL << 16));
nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8),
- (NIC_TNS_BYPASS_MODE << 7) | BGX1_BLOCK);
+ (NIC_TNS_BYPASS_MODE << 7) |
+ BGX1_BLOCK | (1ULL << 16));
+ } else {
+ /* Configure timestamp generation timeout to 10us */
+ for (i = 0; i < nic->hw->bgx_cnt; i++)
+ nic_reg_write(nic, NIC_PF_INTFX_SEND_CFG | (i << 3),
+ (1ULL << 16));
}
nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG,
@@ -880,6 +889,46 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
}
}
+/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */
+static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
+{
+ struct pkind_cfg *pkind;
+ u8 lmac, bgx_idx;
+ u64 pkind_val, pkind_idx;
+
+ if (vf >= nic->num_vf_en)
+ return;
+
+ bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+ pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX;
+ pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3));
+ pkind = (struct pkind_cfg *)&pkind_val;
+
+ if (ptp->enable && !pkind->hdr_sl) {
+ /* Skiplen to exclude 8byte timestamp while parsing pkt
+ * If not configured, will result in L2 errors.
+ */
+ pkind->hdr_sl = 4;
+ /* Adjust max packet length allowed */
+ pkind->maxlen += (pkind->hdr_sl * 2);
+ bgx_config_timestamping(nic->node, bgx_idx, lmac, true);
+ nic_reg_write(nic,
+ NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+ (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588);
+ } else if (!ptp->enable && pkind->hdr_sl) {
+ pkind->maxlen -= (pkind->hdr_sl * 2);
+ pkind->hdr_sl = 0;
+ bgx_config_timestamping(nic->node, bgx_idx, lmac, false);
+ nic_reg_write(nic,
+ NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+ (1ULL << 16) | ETH_P_8021Q); /* reset value */
+ }
+
+ nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
+}
+
/* Interrupt handler to handle mailbox messages from VFs */
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
{
@@ -1022,6 +1071,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
case NIC_MBOX_MSG_PFC:
nic_pause_frame(nic, vf, &mbx.pfc);
goto unlock;
+ case NIC_MBOX_MSG_PTP_CFG:
+ nic_config_timestamp(nic, vf, &mbx.ptp);
+ break;
default:
dev_err(&nic->pdev->dev,
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 80d46337cf29..a16c48a1ebb2 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -99,6 +99,7 @@
#define NIC_PF_ECC3_DBE_INT_W1S (0x2708)
#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710)
#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718)
+#define NIC_PF_INTFX_SEND_CFG (0x4000)
#define NIC_PF_MCAM_0_191_ENA (0x100000)
#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000)
#define NIC_PF_MCAM_CTRL (0x120000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index b9ece9cbf98b..ed9f10bdf41e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -9,12 +9,14 @@
/* ETHTOOL Support for VNIC_VF Device*/
#include <linux/pci.h>
+#include <linux/net_tstamp.h>
#include "nic_reg.h"
#include "nic.h"
#include "nicvf_queues.h"
#include "q_struct.h"
#include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
#define DRV_NAME "thunder-nicvf"
#define DRV_VERSION "1.0"
@@ -824,6 +826,31 @@ static int nicvf_set_pauseparam(struct net_device *dev,
return 0;
}
+static int nicvf_get_ts_info(struct net_device *netdev,
+ struct ethtool_ts_info *info)
+{
+ struct nicvf *nic = netdev_priv(netdev);
+
+ if (!nic->ptp_clock)
+ return ethtool_op_get_ts_info(netdev, info);
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);
+
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static const struct ethtool_ops nicvf_ethtool_ops = {
.get_link = nicvf_get_link,
.get_drvinfo = nicvf_get_drvinfo,
@@ -847,7 +874,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
.set_channels = nicvf_set_channels,
.get_pauseparam = nicvf_get_pauseparam,
.set_pauseparam = nicvf_set_pauseparam,
- .get_ts_info = ethtool_op_get_ts_info,
+ .get_ts_info = nicvf_get_ts_info,
.get_link_ksettings = nicvf_get_link_ksettings,
};
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 52b3a6044f85..487d09a32b6d 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -20,11 +20,13 @@
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <linux/filter.h>
+#include <linux/net_tstamp.h>
#include "nic_reg.h"
#include "nic.h"
#include "nicvf_queues.h"
#include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
#define DRV_NAME "thunder-nicvf"
#define DRV_VERSION "1.0"
@@ -601,6 +603,44 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
return false;
}
+static void nicvf_snd_ptp_handler(struct net_device *netdev,
+ struct cqe_send_t *cqe_tx)
+{
+ struct nicvf *nic = netdev_priv(netdev);
+ struct skb_shared_hwtstamps ts;
+ u64 ns;
+
+ nic = nic->pnicvf;
+
+ /* Sync for 'ptp_skb' */
+ smp_rmb();
+
+ /* New timestamp request can be queued now */
+ atomic_set(&nic->tx_ptp_skbs, 0);
+
+ /* Check for timestamp requested skb */
+ if (!nic->ptp_skb)
+ return;
+
+ /* Check if timestamping is timedout, which is set to 10us */
+ if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
+ cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
+ goto no_tstamp;
+
+ /* Get the timestamp */
+ memset(&ts, 0, sizeof(ts));
+ ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
+ ts.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(nic->ptp_skb, &ts);
+
+no_tstamp:
+ /* Free the original skb */
+ dev_kfree_skb_any(nic->ptp_skb);
+ nic->ptp_skb = NULL;
+ /* Sync 'ptp_skb' */
+ smp_wmb();
+}
+
static void nicvf_snd_pkt_handler(struct net_device *netdev,
struct cqe_send_t *cqe_tx,
int budget, int *subdesc_cnt,
@@ -657,7 +697,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
prefetch(skb);
(*tx_pkts)++;
*tx_bytes += skb->len;
- napi_consume_skb(skb, budget);
+ /* If timestamp is requested for this skb, don't free it */
+ if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+ !nic->pnicvf->ptp_skb)
+ nic->pnicvf->ptp_skb = skb;
+ else
+ napi_consume_skb(skb, budget);
sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
} else {
/* In case of SW TSO on 88xx, only last segment will have
@@ -696,6 +741,21 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
skb_set_hash(skb, hash, hash_type);
}
+static inline void nicvf_set_rxtstamp(struct nicvf *nic, struct sk_buff *skb)
+{
+ u64 ns;
+
+ if (!nic->ptp_clock || !nic->hw_rx_tstamp)
+ return;
+
+ /* The first 8 bytes is the timestamp */
+ ns = cavium_ptp_tstamp2time(nic->ptp_clock,
+ be64_to_cpu(*(u64 *)skb->data));
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
+
+ __skb_pull(skb, 8);
+}
+
static void nicvf_rcv_pkt_handler(struct net_device *netdev,
struct napi_struct *napi,
struct cqe_rx_t *cqe_rx, struct snd_queue *sq)
@@ -746,6 +806,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
return;
}
+ nicvf_set_rxtstamp(nic, skb);
nicvf_set_rxhash(netdev, cqe_rx, skb);
skb_record_rx_queue(skb, rq_idx);
@@ -820,10 +881,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
&tx_pkts, &tx_bytes);
tx_done++;
break;
+ case CQE_TYPE_SEND_PTP:
+ nicvf_snd_ptp_handler(netdev, (void *)cq_desc);
+ break;
case CQE_TYPE_INVALID:
case CQE_TYPE_RX_SPLIT:
case CQE_TYPE_RX_TCP:
- case CQE_TYPE_SEND_PTP:
/* Ignore for now */
break;
}
@@ -1319,12 +1382,28 @@ int nicvf_stop(struct net_device *netdev)
nicvf_free_cq_poll(nic);
+ /* Free any pending SKB saved to receive timestamp */
+ if (nic->ptp_skb) {
+ dev_kfree_skb_any(nic->ptp_skb);
+ nic->ptp_skb = NULL;
+ }
+
/* Clear multiqset info */
nic->pnicvf = nic;
return 0;
}
+static int nicvf_config_hw_rx_tstamp(struct nicvf *nic, bool enable)
+{
+ union nic_mbx mbx = {};
+
+ mbx.ptp.msg = NIC_MBOX_MSG_PTP_CFG;
+ mbx.ptp.enable = enable;
+
+ return nicvf_send_msg_to_pf(nic, &mbx);
+}
+
static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
{
union nic_mbx mbx = {};
@@ -1394,6 +1473,12 @@ int nicvf_open(struct net_device *netdev)
if (nic->sqs_mode)
nicvf_get_primary_vf_struct(nic);
+ /* Configure PTP timestamp */
+ if (nic->ptp_clock)
+ nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
+ atomic_set(&nic->tx_ptp_skbs, 0);
+ nic->ptp_skb = NULL;
+
/* Configure receive side scaling and MTU */
if (!nic->sqs_mode) {
nicvf_rss_init(nic);
@@ -1820,6 +1905,77 @@ static void nicvf_xdp_flush(struct net_device *dev)
return;
}
+int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr)
+{
+ struct hwtstamp_config config;
+ struct nicvf *nic = netdev_priv(netdev);
+
+ if (!nic->ptp_clock)
+ return -ENODEV;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ case HWTSTAMP_TX_ON:
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ nic->hw_rx_tstamp = false;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_SOME:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ nic->hw_rx_tstamp = true;
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (netif_running(netdev)) {
+ if (nic->hw_rx_tstamp)
+ nicvf_config_hw_rx_tstamp(nic, true);
+ else
+ nicvf_config_hw_rx_tstamp(nic, false);
+ }
+
+ if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
+{
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return nicvf_config_hwtstamp(netdev, req);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct net_device_ops nicvf_netdev_ops = {
.ndo_open = nicvf_open,
.ndo_stop = nicvf_stop,
@@ -1833,6 +1989,7 @@ static const struct net_device_ops nicvf_netdev_ops = {
.ndo_bpf = nicvf_xdp,
.ndo_xdp_xmit = nicvf_xdp_xmit,
.ndo_xdp_flush = nicvf_xdp_flush,
+ .ndo_do_ioctl = nicvf_ioctl,
};
static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1842,6 +1999,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct nicvf *nic;
int err, qcount;
u16 sdevid;
+ struct cavium_ptp *ptp_clock;
+
+ ptp_clock = cavium_ptp_get();
+ if (IS_ERR(ptp_clock)) {
+ if (PTR_ERR(ptp_clock) == -ENODEV)
+ /* In virtualized environment we proceed without ptp */
+ ptp_clock = NULL;
+ else
+ return PTR_ERR(ptp_clock);
+ }
err = pci_enable_device(pdev);
if (err) {
@@ -1896,6 +2063,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
if (!nic->t88)
nic->max_queues *= 2;
+ nic->ptp_clock = ptp_clock;
/* MAP VF's configuration registers */
nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
@@ -2009,6 +2177,7 @@ static void nicvf_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
if (nic->drv_stats)
free_percpu(nic->drv_stats);
+ cavium_ptp_put(nic->ptp_clock);
free_netdev(netdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 095c18aeb8d5..9a999c62d6ba 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -978,6 +978,9 @@ void nicvf_qset_config(struct nicvf *nic, bool enable)
qs_cfg->be = 1;
#endif
qs_cfg->vnic = qs->vnic_id;
+ /* Enable Tx timestamping capability */
+ if (nic->ptp_clock)
+ qs_cfg->send_tstmp_ena = 1;
}
nicvf_send_msg_to_pf(nic, &mbx);
}
@@ -1383,6 +1386,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
hdr->inner_l3_offset = skb_network_offset(skb) - 2;
this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
}
+
+ /* Check if timestamp is requested */
+ if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ skb_tx_timestamp(skb);
+ return;
+ }
+
+ /* Tx timestamping not supported along with TSO, so ignore request */
+ if (skb_shinfo(skb)->gso_size)
+ return;
+
+ /* HW supports only a single outstanding packet to timestamp */
+ if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
+ return;
+
+ /* Mark the SKB for later reference */
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ /* Finally enable timestamp generation
+ * Since 'post_cqe' is also set, two CQEs will be posted
+ * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
+ */
+ hdr->tstmp = 1;
}
/* SQ GATHER subdescriptor
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 5e5c4d7796b8..0f23999c5bcf 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -245,6 +245,35 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
}
EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
+/* Enables or disables timestamp insertion by BGX for Rx packets */
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable)
+{
+ struct bgx *bgx = get_bgx(node, bgx_idx);
+ struct lmac *lmac;
+ u64 csr_offset, cfg;
+
+ if (!bgx)
+ return;
+
+ lmac = &bgx->lmac[lmacid];
+
+ if (lmac->lmac_type == BGX_MODE_SGMII ||
+ lmac->lmac_type == BGX_MODE_QSGMII ||
+ lmac->lmac_type == BGX_MODE_RGMII)
+ csr_offset = BGX_GMP_GMI_RXX_FRM_CTL;
+ else
+ csr_offset = BGX_SMUX_RX_FRM_CTL;
+
+ cfg = bgx_reg_read(bgx, lmacid, csr_offset);
+
+ if (enable)
+ cfg |= BGX_PKT_RX_PTP_EN;
+ else
+ cfg &= ~BGX_PKT_RX_PTP_EN;
+ bgx_reg_write(bgx, lmacid, csr_offset, cfg);
+}
+EXPORT_SYMBOL(bgx_config_timestamping);
+
void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
{
struct pfc *pfc = (struct pfc *)pause;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 23acdc5ab896..5a7567d31138 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -122,6 +122,8 @@
#define SPU_DBG_CTL_AN_NONCE_MCT_DIS BIT_ULL(29)
#define BGX_SMUX_RX_INT 0x20000
+#define BGX_SMUX_RX_FRM_CTL 0x20020
+#define BGX_PKT_RX_PTP_EN BIT_ULL(12)
#define BGX_SMUX_RX_JABBER 0x20030
#define BGX_SMUX_RX_CTL 0x20048
#define SMU_RX_CTL_STATUS (3ull << 0)
@@ -172,6 +174,7 @@
#define GMI_PORT_CFG_SPEED_MSB BIT_ULL(8)
#define GMI_PORT_CFG_RX_IDLE BIT_ULL(12)
#define GMI_PORT_CFG_TX_IDLE BIT_ULL(13)
+#define BGX_GMP_GMI_RXX_FRM_CTL 0x38028
#define BGX_GMP_GMI_RXX_JABBER 0x38038
#define BGX_GMP_GMI_TXX_THRESH 0x38210
#define BGX_GMP_GMI_TXX_APPEND 0x38218
@@ -223,6 +226,7 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
void bgx_lmac_internal_loopback(int node, int bgx_idx,
int lmac_idx, bool enable);
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable);
void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
--
2.15.1
^ permalink raw reply related
* [PATCH net-next v3 1/2] net: add support for Cavium PTP coprocessor
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney
In-Reply-To: <20171206133100.26436-1-aleksey.makarov@cavium.com>
From: Radoslaw Biernacki <rad@semihalf.com>
This patch adds support for the Precision Time Protocol
Clocks and Timestamping hardware found on Cavium ThunderX
processors.
Signed-off-by: Radoslaw Biernacki <rad@semihalf.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
drivers/net/ethernet/cavium/Kconfig | 13 +
drivers/net/ethernet/cavium/Makefile | 1 +
drivers/net/ethernet/cavium/common/Makefile | 1 +
drivers/net/ethernet/cavium/common/cavium_ptp.c | 334 ++++++++++++++++++++++++
drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 ++++++
5 files changed, 427 insertions(+)
create mode 100644 drivers/net/ethernet/cavium/common/Makefile
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 63be75eb34d2..fabe0ffcc2d4 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -50,6 +50,19 @@ config THUNDER_NIC_RGX
This driver supports configuring XCV block of RGX interface
present on CN81XX chip.
+config CAVIUM_PTP
+ tristate "Cavium PTP coprocessor as PTP clock"
+ depends on 64BIT
+ depends on PTP_1588_CLOCK
+ select CAVIUM_RST
+ default y
+ ---help---
+ This driver adds support for the Precision Time Protocol Clocks and
+ Timestamping coprocessor (PTP) found on Cavium processors.
+ PTP provides timestamping mechanism that is suitable for use in IEEE 1588
+ Precision Time Protocol or other purposes. Timestamps can be used in
+ BGX, TNS, GTI, and NIC blocks.
+
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT
diff --git a/drivers/net/ethernet/cavium/Makefile b/drivers/net/ethernet/cavium/Makefile
index 872da9f7c31a..946bba84e81d 100644
--- a/drivers/net/ethernet/cavium/Makefile
+++ b/drivers/net/ethernet/cavium/Makefile
@@ -1,6 +1,7 @@
#
# Makefile for the Cavium ethernet device drivers.
#
+obj-$(CONFIG_NET_VENDOR_CAVIUM) += common/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/
diff --git a/drivers/net/ethernet/cavium/common/Makefile b/drivers/net/ethernet/cavium/common/Makefile
new file mode 100644
index 000000000000..dd8561b8060b
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CAVIUM_PTP) += cavium_ptp.o
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
new file mode 100644
index 000000000000..f4c738db27fd
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -0,0 +1,334 @@
+/*
+ * cavium_ptp.c - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/timecounter.h>
+#include <linux/pci.h>
+
+#include "cavium_ptp.h"
+
+#define DRV_NAME "Cavium PTP Driver"
+
+#define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C
+#define PCI_DEVICE_ID_CAVIUM_RST 0xA00E
+
+#define PCI_PTP_BAR_NO 0
+#define PCI_RST_BAR_NO 0
+
+#define PTP_CLOCK_CFG 0xF00ULL
+#define PTP_CLOCK_CFG_PTP_EN BIT(0)
+#define PTP_CLOCK_LO 0xF08ULL
+#define PTP_CLOCK_HI 0xF10ULL
+#define PTP_CLOCK_COMP 0xF18ULL
+
+#define RST_BOOT 0x1600ULL
+#define CLOCK_BASE_RATE 50000000ULL
+
+static u64 ptp_cavium_clock_get(void)
+{
+ struct pci_dev *pdev;
+ void __iomem *base;
+ u64 ret = CLOCK_BASE_RATE * 16;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_CAVIUM_RST, NULL);
+ if (!pdev)
+ goto error;
+
+ base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO);
+ if (!base)
+ goto error_put_pdev;
+
+ ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT) >> 33) & 0x3f);
+
+ iounmap(base);
+
+error_put_pdev:
+ pci_dev_put(pdev);
+
+error:
+ return ret;
+}
+
+struct cavium_ptp *cavium_ptp_get(void)
+{
+ struct cavium_ptp *ptp;
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_CAVIUM_PTP, NULL);
+ if (!pdev)
+ return ERR_PTR(-ENODEV);
+
+ ptp = pci_get_drvdata(pdev);
+ if (!ptp) {
+ pci_dev_put(pdev);
+ ptp = ERR_PTR(-EPROBE_DEFER);
+ }
+
+ return ptp;
+}
+EXPORT_SYMBOL(cavium_ptp_get);
+
+void cavium_ptp_put(struct cavium_ptp *ptp)
+{
+ pci_dev_put(ptp->pdev);
+}
+EXPORT_SYMBOL(cavium_ptp_put);
+
+/**
+ * cavium_ptp_adjfreq() - Adjust ptp frequency
+ * @ptp: PTP clock info
+ * @ppb: how much to adjust by, in parts-per-billion
+ */
+static int cavium_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 comp;
+ u64 adj;
+ bool neg_adj = false;
+
+ if (ppb < 0) {
+ neg_adj = true;
+ ppb = -ppb;
+ }
+
+ /* The hardware adds the clock compensation value to the PTP clock
+ * on every coprocessor clock cycle. Typical convention is that it
+ * represent number of nanosecond betwen each cycle. In this
+ * convention compensation value is in 64 bit fixed-point
+ * representation where upper 32 bits are number of nanoseconds
+ * and lower is fractions of nanosecond.
+ * The ppb represent the ratio in "parts per bilion" by which the
+ * compensation value should be corrected.
+ * To calculate new compenstation value we use 64bit fixed point
+ * arithmetic on following formula comp = tbase + tbase * ppb / 1G
+ * where tbase is the basic compensation value calculated initialy
+ * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian
+ * independent structure definition to write data to PTP register.
+ */
+ comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+ adj = comp * ppb;
+ adj = div_u64(adj, 1000000000ull);
+ comp = neg_adj ? comp - adj : comp + adj;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ writeq(comp, clock->reg_base + PTP_CLOCK_COMP);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_adjtime() - Adjust ptp time
+ * @ptp: PTP clock info
+ * @delta: how much to adjust by, in nanosecs
+ */
+static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ timecounter_adjtime(&clock->time_counter, delta);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ /* Sync, for network driver to get latest value */
+ smp_mb();
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_gettime() - Get hardware clock time with adjustment
+ * @ptp: PTP clock info
+ * @ts: timespec
+ */
+static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info,
+ struct timespec64 *ts)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 nsec;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ nsec = timecounter_read(&clock->time_counter);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ *ts = ns_to_timespec64(nsec);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_settime() - Set hardware clock time. Reset adjustment
+ * @ptp: PTP clock info
+ * @ts: timespec
+ */
+static int cavium_ptp_settime(struct ptp_clock_info *ptp_info,
+ const struct timespec64 *ts)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 nsec;
+
+ nsec = timespec64_to_ns(ts);
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_enable() - Check if PTP is enabled
+ * @ptp: PTP clock info
+ * @rq: request
+ * @on: is it on
+ */
+static int cavium_ptp_enable(struct ptp_clock_info *ptp_info,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static u64 cavium_ptp_cc_read(const struct cyclecounter *cc)
+{
+ struct cavium_ptp *clock =
+ container_of(cc, struct cavium_ptp, cycle_counter);
+
+ return readq(clock->reg_base + PTP_CLOCK_HI);
+}
+
+static int cavium_ptp_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ struct cavium_ptp *clock;
+ struct cyclecounter *cc;
+ u64 clock_cfg;
+ u64 clock_comp;
+ int err;
+
+ clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock)
+ return -ENOMEM;
+
+ clock->pdev = pdev;
+
+ err = pcim_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
+ if (err)
+ return err;
+
+ clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
+
+ spin_lock_init(&clock->spin_lock);
+
+ cc = &clock->cycle_counter;
+ cc->read = cavium_ptp_cc_read;
+ cc->mask = CYCLECOUNTER_MASK(64);
+ cc->mult = 1;
+ cc->shift = 0;
+
+ timecounter_init(&clock->time_counter, &clock->cycle_counter,
+ ktime_to_ns(ktime_get_real()));
+
+ clock->clock_rate = ptp_cavium_clock_get();
+
+ clock->ptp_info = (struct ptp_clock_info) {
+ .owner = THIS_MODULE,
+ .name = "ThunderX PTP",
+ .max_adj = 1000000000ull,
+ .n_ext_ts = 0,
+ .n_pins = 0,
+ .pps = 0,
+ .adjfreq = cavium_ptp_adjfreq,
+ .adjtime = cavium_ptp_adjtime,
+ .gettime64 = cavium_ptp_gettime,
+ .settime64 = cavium_ptp_settime,
+ .enable = cavium_ptp_enable,
+ };
+
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+
+ clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+ writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP);
+
+ clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev);
+ if (IS_ERR(clock->ptp_clock)) {
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+ return PTR_ERR(clock->ptp_clock);
+ }
+
+ pci_set_drvdata(pdev, clock);
+ return 0;
+}
+
+static void cavium_ptp_remove(struct pci_dev *pdev)
+{
+ struct cavium_ptp *clock = pci_get_drvdata(pdev);
+ u64 clock_cfg;
+
+ pci_set_drvdata(pdev, NULL);
+
+ ptp_clock_unregister(clock->ptp_clock);
+
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+}
+
+static const struct pci_device_id cavium_ptp_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP) },
+ { 0, }
+};
+
+static struct pci_driver cavium_ptp_driver = {
+ .name = DRV_NAME,
+ .id_table = cavium_ptp_id_table,
+ .probe = cavium_ptp_probe,
+ .remove = cavium_ptp_remove,
+};
+
+static int __init cavium_ptp_init_module(void)
+{
+ return pci_register_driver(&cavium_ptp_driver);
+}
+
+static void __exit cavium_ptp_cleanup_module(void)
+{
+ pci_unregister_driver(&cavium_ptp_driver);
+}
+
+module_init(cavium_ptp_init_module);
+module_exit(cavium_ptp_cleanup_module);
+
+MODULE_DESCRIPTION(DRV_NAME);
+MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table);
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h
new file mode 100644
index 000000000000..7a9dcb027a93
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h
@@ -0,0 +1,78 @@
+/*
+ * cavium_ptp.h - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#ifndef CAVIUM_PTP_H
+#define CAVIUM_PTP_H
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/timecounter.h>
+
+struct cavium_ptp {
+ struct pci_dev *pdev;
+
+ /* Serialize access to cycle_counter, time_counter and hw_registers */
+ spinlock_t spin_lock;
+ struct cyclecounter cycle_counter;
+ struct timecounter time_counter;
+ void __iomem *reg_base;
+
+ u32 clock_rate;
+
+ struct ptp_clock_info ptp_info;
+ struct ptp_clock *ptp_clock;
+};
+
+#ifdef CONFIG_CAVIUM_PTP
+
+struct cavium_ptp *cavium_ptp_get(void);
+void cavium_ptp_put(struct cavium_ptp *ptp);
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+ unsigned long flags;
+ u64 ret;
+
+ spin_lock_irqsave(&ptp->spin_lock, flags);
+ ret = timecounter_cyc2time(&ptp->time_counter, tstamp);
+ spin_unlock_irqrestore(&ptp->spin_lock, flags);
+
+ return ret;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+ return ptp_clock_index(clock->ptp_clock);
+}
+
+#else
+
+static inline struct cavium_ptp *cavium_ptp_get(void)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void cavium_ptp_put(struct cavium_ptp *ptp) {}
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+ return 0;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+ return -1;
+}
+
+#endif
+
+#endif
--
2.15.1
^ permalink raw reply related
* [PATCH net-next v3 0/2] net: thunderx: add support for PTP clock
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney
This series adds support for IEEE 1588 Precision Time Protocol
to Cavium ethernet driver.
The first patch adds support for the Precision Time Protocol Clocks and
Timestamping coprocessor (PTP) found on Cavium processors.
It registers a new PTP clock in the PTP core and provides functions
to use the counter in BGX, TNS, GTI, and NIC blocks.
The second patch introduces support for the PTP protocol to the
Cavium ThunderX ethernet driver.
v3:
- rebase to net-next
v2: https://lkml.kernel.org/r/20171117134909.8954-1-aleksey.makarov@cavium.com
- use readq()/writeq() in place of cavium_ptp_reg_read()/cavium_ptp_reg_write(),
don't use readq_relaxed()/writeq_relaxed() (David Daney)
v1: https://lkml.kernel.org/r/20171107190704.15458-1-aleksey.makarov@cavium.com
Radoslaw Biernacki (1):
net: add support for Cavium PTP coprocessor
Sunil Goutham (1):
net: thunderx: add timestamping support
drivers/net/ethernet/cavium/Kconfig | 14 +
drivers/net/ethernet/cavium/Makefile | 1 +
drivers/net/ethernet/cavium/common/Makefile | 1 +
drivers/net/ethernet/cavium/common/cavium_ptp.c | 334 +++++++++++++++++++++
drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 +++++
drivers/net/ethernet/cavium/thunder/nic.h | 15 +
drivers/net/ethernet/cavium/thunder/nic_main.c | 58 +++-
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 +-
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 173 ++++++++++-
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 26 ++
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 29 ++
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 4 +
13 files changed, 757 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/ethernet/cavium/common/Makefile
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h
--
2.15.1
^ 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