Netdev List
 help / color / mirror / Atom feed
* Re: r8169 needs CONFIG_REALTEK_PHY
From: Marc Dionne @ 2018-08-20 23:33 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: hkallweit1, netdev, David Miller
In-Reply-To: <29f25302-6a60-4a44-fd65-26b5a15ff35a@gmail.com>

On Mon, Aug 20, 2018 at 5:39 PM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> On 08/20/2018 12:44 PM, Marc Dionne wrote:
>> The r8169 adapter in one of my machines was not working after updating
>> to a current kernel from the merge window, which was fixed by enabling
>> CONFIG_REALTEK_PHY.
>>
>> So in addition to "select PHYLIB", should CONFIG_R8169 not also be
>> doing "select CONFIG_REALTEK_PHY" ?
>
> This is fixed in Linus' tree now with:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bfdd19ad80f203f42f05fd32a31c678c9c524ef9
> --
> Florian

Ah thanks for the quick reply, thought I had done a fresh pull before
reporting the problem; it is indeed fixed in Linus' current tree.

Sorry for the noise,
Marc

^ permalink raw reply

* Re: [PATCH] tipc: fix issue that tipc_dest neglects of big-endian
From: David Miller @ 2018-08-21  2:20 UTC (permalink / raw)
  To: Haiqing.Bai; +Cc: jon.maloy, ying.xue, zhenbo.gao, netdev, linux-kernel
In-Reply-To: <1534760761-30206-1-git-send-email-Haiqing.Bai@windriver.com>

From: Haiqing Bai <Haiqing.Bai@windriver.com>
Date: Mon, 20 Aug 2018 18:26:01 +0800

> The tipc multicast demo in tipcutils fails to work on big-endian hardware.
> The tipc multicast server can not receive the packets sent by the multicast
> client for that the dest port is always zero after tipc_dest_pop, then it
> is found that the struct tipc_dest fails to take big/little endian into
> account.
> 
> Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
> Signed-off-by: Zhenbo Gao <zhenbo.gao@windriver.com>

Jon and Ying, please review.

thank you.

^ permalink raw reply

* [PATCH iproute2 4/4] tc: drop extern from function prototypes
From: Stephen Hemminger @ 2018-08-20 23:02 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger
In-Reply-To: <20180820230231.24723-1-stephen@networkplumber.org>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/m_ematch.h  | 35 +++++++++++++++--------------------
 tc/m_pedit.h   | 31 +++++++++++++++----------------
 tc/tc_common.h | 30 +++++++++++++++---------------
 tc/tc_red.h    |  7 ++++---
 4 files changed, 49 insertions(+), 54 deletions(-)

diff --git a/tc/m_ematch.h b/tc/m_ematch.h
index f634f19164fa..ff02d7ac9112 100644
--- a/tc/m_ematch.h
+++ b/tc/m_ematch.h
@@ -12,17 +12,16 @@
 
 #define EMATCHKINDSIZ 16
 
-struct bstr
-{
+struct bstr {
 	char	*data;
 	unsigned int	len;
 	int		quoted;
 	struct bstr	*next;
 };
 
-extern struct bstr * bstr_alloc(const char *text);
+struct bstr *bstr_alloc(const char *text);
 
-static inline struct bstr * bstr_new(char *data, unsigned int len)
+static inline struct bstr *bstr_new(char *data, unsigned int len)
 {
 	struct bstr *b = calloc(1, sizeof(*b));
 
@@ -35,7 +34,7 @@ static inline struct bstr * bstr_new(char *data, unsigned int len)
 	return b;
 }
 
-static inline int bstrcmp(struct bstr *b, const char *text)
+static inline int bstrcmp(const struct bstr *b, const char *text)
 {
 	int len = strlen(text);
 	int d = b->len - len;
@@ -51,12 +50,10 @@ static inline struct bstr *bstr_next(struct bstr *b)
 	return b->next;
 }
 
-extern unsigned long bstrtoul(const struct bstr *b);
-extern void bstr_print(FILE *fd, const struct bstr *b, int ascii);
-
+unsigned long bstrtoul(const struct bstr *b);
+void bstr_print(FILE *fd, const struct bstr *b, int ascii);
 
-struct ematch
-{
+struct ematch {
 	struct bstr	*args;
 	int		index;
 	int		inverted;
@@ -66,7 +63,7 @@ struct ematch
 	struct ematch	*next;
 };
 
-static inline struct ematch * new_ematch(struct bstr *args, int inverted)
+static inline struct ematch *new_ematch(struct bstr *args, int inverted)
 {
 	struct ematch *e = calloc(1, sizeof(*e));
 
@@ -79,14 +76,12 @@ static inline struct ematch * new_ematch(struct bstr *args, int inverted)
 	return e;
 }
 
-extern void print_ematch_tree(const struct ematch *tree);
+void print_ematch_tree(const struct ematch *tree);
 
-
-struct ematch_util
-{
+struct ematch_util {
 	char			kind[EMATCHKINDSIZ];
 	int			kind_num;
-	int	(*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *,
+	int	(*parse_eopt)(struct nlmsghdr *, struct tcf_ematch_hdr *,
 			      struct bstr *);
 	int	(*parse_eopt_argv)(struct nlmsghdr *, struct tcf_ematch_hdr *,
 				   int, char **);
@@ -95,7 +90,7 @@ struct ematch_util
 	struct ematch_util	*next;
 };
 
-static inline int parse_layer(struct bstr *b)
+static inline int parse_layer(const struct bstr *b)
 {
 	if (*((char *) b->data) == 'l')
 		return TCF_LAYER_LINK;
@@ -107,9 +102,9 @@ static inline int parse_layer(struct bstr *b)
 		return INT_MAX;
 }
 
-extern int em_parse_error(int err, struct bstr *args, struct bstr *carg,
+int em_parse_error(int err, struct bstr *args, struct bstr *carg,
 		   struct ematch_util *, char *fmt, ...);
-extern int print_ematch(FILE *, const struct rtattr *);
-extern int parse_ematch(int *, char ***, int, struct nlmsghdr *);
+int print_ematch(FILE *, const struct rtattr *);
+int parse_ematch(int *, char ***, int, struct nlmsghdr *);
 
 #endif
diff --git a/tc/m_pedit.h b/tc/m_pedit.h
index a8b069581509..b6b274bd08c7 100644
--- a/tc/m_pedit.h
+++ b/tc/m_pedit.h
@@ -71,23 +71,22 @@ struct m_pedit_util {
 			       struct m_pedit_key *tkey);
 };
 
-extern int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
-extern int pack_key32(__u32 retain, struct m_pedit_sel *sel,
-		      struct m_pedit_key *tkey);
-extern int pack_key16(__u32 retain, struct m_pedit_sel *sel,
-		      struct m_pedit_key *tkey);
-extern int pack_key8(__u32 retain, struct m_pedit_sel *sel,
+int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
+int pack_key32(__u32 retain, struct m_pedit_sel *sel,
+	       struct m_pedit_key *tkey);
+int pack_key16(__u32 retain, struct m_pedit_sel *sel,
+	       struct m_pedit_key *tkey);
+int pack_key8(__u32 retain, struct m_pedit_sel *sel,
 		     struct m_pedit_key *tkey);
-extern int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type);
-extern int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type,
-		     __u32 retain,
-		     struct m_pedit_sel *sel, struct m_pedit_key *tkey);
-extern int parse_offset(int *argc_p, char ***argv_p,
-			struct m_pedit_sel *sel, struct m_pedit_key *tkey);
+int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type);
+int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type,
+	      __u32 retain,
+	      struct m_pedit_sel *sel, struct m_pedit_key *tkey);
+int parse_offset(int *argc_p, char ***argv_p,
+		 struct m_pedit_sel *sel, struct m_pedit_key *tkey);
 int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p,
 		int tca_id, struct nlmsghdr *n);
-extern int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
-extern int pedit_print_xstats(struct action_util *au, FILE *f,
-			      struct rtattr *xstats);
-
+int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
+int pedit_print_xstats(struct action_util *au, FILE *f,
+		       struct rtattr *xstats);
 #endif
diff --git a/tc/tc_common.h b/tc/tc_common.h
index 272d1727027d..371ca7d04602 100644
--- a/tc/tc_common.h
+++ b/tc/tc_common.h
@@ -5,26 +5,26 @@
 
 extern struct rtnl_handle rth;
 
-extern int do_qdisc(int argc, char **argv);
-extern int do_class(int argc, char **argv);
-extern int do_filter(int argc, char **argv, void *buf, size_t buflen);
-extern int do_chain(int argc, char **argv, void *buf, size_t buflen);
-extern int do_action(int argc, char **argv, void *buf, size_t buflen);
-extern int do_tcmonitor(int argc, char **argv);
-extern int do_exec(int argc, char **argv);
+int do_qdisc(int argc, char **argv);
+int do_class(int argc, char **argv);
+int do_filter(int argc, char **argv, void *buf, size_t buflen);
+int do_chain(int argc, char **argv, void *buf, size_t buflen);
+int do_action(int argc, char **argv, void *buf, size_t buflen);
+int do_tcmonitor(int argc, char **argv);
+int do_exec(int argc, char **argv);
 
-extern int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
+int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
 
 struct tc_estimator;
-extern int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
+int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
 
 struct tc_sizespec;
-extern int parse_size_table(int *p_argc, char ***p_argv, struct tc_sizespec *s);
-extern int check_size_table_opts(struct tc_sizespec *s);
+int parse_size_table(int *p_argc, char ***p_argv, struct tc_sizespec *s);
+int check_size_table_opts(struct tc_sizespec *s);
 
 extern int show_graph;
 extern bool use_names;
diff --git a/tc/tc_red.h b/tc/tc_red.h
index 88fba58b7416..6c6e6b039732 100644
--- a/tc/tc_red.h
+++ b/tc/tc_red.h
@@ -2,8 +2,9 @@
 #ifndef _TC_RED_H_
 #define _TC_RED_H_ 1
 
-extern int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
-extern int tc_red_eval_ewma(unsigned qmin, unsigned burst, unsigned avpkt);
-extern int tc_red_eval_idle_damping(int wlog, unsigned avpkt, unsigned bandwidth, __u8 *sbuf);
+int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
+int tc_red_eval_ewma(unsigned qmin, unsigned burst, unsigned avpkt);
+int tc_red_eval_idle_damping(int wlog, unsigned avpkt, unsigned bandwidth,
+			     __u8 *sbuf);
 
 #endif
-- 
2.18.0

^ permalink raw reply related

* [PATCH iproute2 3/4] genl: drop extern from function prototypes
From: Stephen Hemminger @ 2018-08-20 23:02 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger
In-Reply-To: <20180820230231.24723-1-stephen@networkplumber.org>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 genl/genl_utils.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/genl/genl_utils.h b/genl/genl_utils.h
index 6e6f44501aba..3de0da34bdba 100644
--- a/genl/genl_utils.h
+++ b/genl/genl_utils.h
@@ -10,9 +10,10 @@ struct genl_util
 	struct  genl_util *next;
 	char	name[16];
 	int	(*parse_genlopt)(struct genl_util *fu, int argc, char **argv);
-	int	(*print_genlopt)(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+	int	(*print_genlopt)(const struct sockaddr_nl *who,
+				 struct nlmsghdr *n, void *arg);
 };
 
-extern int genl_ctrl_resolve_family(const char *family);
+int genl_ctrl_resolve_family(const char *family);
 
 #endif
-- 
2.18.0

^ permalink raw reply related

* [PATCH iproute2 2/4] bridge: drop extern from function prototypes
From: Stephen Hemminger @ 2018-08-20 23:02 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger
In-Reply-To: <20180820230231.24723-1-stephen@networkplumber.org>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 bridge/br_common.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/bridge/br_common.h b/bridge/br_common.h
index 2f1cb8fd9f3d..7bf15e9548fc 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -6,20 +6,20 @@
 #define MDB_RTR_RTA(r) \
 		((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32))))
 
-extern void print_vlan_info(FILE *fp, struct rtattr *tb);
-extern int print_linkinfo(const struct sockaddr_nl *who,
+void print_vlan_info(FILE *fp, struct rtattr *tb);
+int print_linkinfo(const struct sockaddr_nl *who,
 			  struct nlmsghdr *n,
 			  void *arg);
-extern int print_fdb(const struct sockaddr_nl *who,
+int print_fdb(const struct sockaddr_nl *who,
 		     struct nlmsghdr *n, void *arg);
-extern int print_mdb(const struct sockaddr_nl *who,
+int print_mdb(const struct sockaddr_nl *who,
 		     struct nlmsghdr *n, void *arg);
 
-extern int do_fdb(int argc, char **argv);
-extern int do_mdb(int argc, char **argv);
-extern int do_monitor(int argc, char **argv);
-extern int do_vlan(int argc, char **argv);
-extern int do_link(int argc, char **argv);
+int do_fdb(int argc, char **argv);
+int do_mdb(int argc, char **argv);
+int do_monitor(int argc, char **argv);
+int do_vlan(int argc, char **argv);
+int do_link(int argc, char **argv);
 
 extern int preferred_family;
 extern int show_stats;
-- 
2.18.0

^ permalink raw reply related

* [PATCH iproute2 1/4] ip: drop extern from function prototype
From: Stephen Hemminger @ 2018-08-20 23:02 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger
In-Reply-To: <20180820230231.24723-1-stephen@networkplumber.org>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ip_common.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index 4d3227cbc389..200be5e23dd1 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -82,7 +82,7 @@ int do_netns(int argc, char **argv);
 int do_xfrm(int argc, char **argv);
 int do_ipl2tp(int argc, char **argv);
 int do_ipfou(int argc, char **argv);
-extern int do_ipila(int argc, char **argv);
+int do_ipila(int argc, char **argv);
 int do_tcp_metrics(int argc, char **argv);
 int do_ipnetconf(int argc, char **argv);
 int do_iptoken(int argc, char **argv);
-- 
2.18.0

^ permalink raw reply related

* [PATCH iproute2 0/4] drop extern from function prototypes
From: Stephen Hemminger @ 2018-08-20 23:02 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger

iproute2 uses kernel style guidelines

Stephen Hemminger (4):
  ip: drop extern from function prototype
  bridge: drop extern from function prototypes
  genl: drop extern from function prototypes
  tc: drop extern from function prototypes

 bridge/br_common.h | 18 +++++++++---------
 genl/genl_utils.h  |  5 +++--
 ip/ip_common.h     |  2 +-
 tc/m_ematch.h      | 35 +++++++++++++++--------------------
 tc/m_pedit.h       | 31 +++++++++++++++----------------
 tc/tc_common.h     | 30 +++++++++++++++---------------
 tc/tc_red.h        |  7 ++++---
 7 files changed, 62 insertions(+), 66 deletions(-)

-- 
2.18.0

^ permalink raw reply

* Re: [PATCH iproute2] iproute: make clang happy
From: Stephen Hemminger @ 2018-08-20 22:52 UTC (permalink / raw)
  To: Mahesh Bandewar; +Cc: netdev, Mahesh Bandewar
In-Reply-To: <20180820214215.218127-1-mahesh@bandewar.net>

On Mon, 20 Aug 2018 14:42:15 -0700
Mahesh Bandewar <mahesh@bandewar.net> wrote:

> diff --git a/tc/m_ematch.c b/tc/m_ematch.c
> index ace4b3dd738b..a524b520b276 100644
> --- a/tc/m_ematch.c
> +++ b/tc/m_ematch.c
> @@ -277,6 +277,7 @@ static int flatten_tree(struct ematch *head, struct ematch *tree)
>  	return count;
>  }
>  
> +__attribute__((format(printf, 5, 6)))
>  int em_parse_error(int err, struct bstr *args, struct bstr *carg,
>  		   struct ematch_util *e, char *fmt, ...)

I think the printf attribute needs to go on the function prototype
here:
tc/m_ematch.h:extern int em_parse_error(int err, struct bstr *args, struct bstr *carg,


PS: I need to take the extern of  those function prototypes.

^ permalink raw reply

* Re: [PATCH v2 06/29] mtd: Add support for reading MTD devices via the nvmem API
From: Alban @ 2018-08-20 22:53 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Aban Bedel, Srinivas Kandagatla, Bartosz Golaszewski,
	Jonathan Corbet, Sekhar Nori, Kevin Hilman, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, David Woodhouse, Brian Norris,
	Marek Vasut, Richard Weinberger, Grygorii Strashko,
	David S . Miller, Naren, Mauro Carvalho Chehab, Andrew Morton,
	Lukas Wunner, Dan 
In-Reply-To: <20180819184609.6dcdbb9a@bbrezillon>

[-- Attachment #1: Type: text/plain, Size: 6159 bytes --]

On Sun, 19 Aug 2018 18:46:09 +0200
Boris Brezillon <boris.brezillon@bootlin.com> wrote:

> On Sun, 19 Aug 2018 13:31:06 +0200
> Alban <albeu@free.fr> wrote:
> 
> > On Fri, 17 Aug 2018 18:27:20 +0200
> > Boris Brezillon <boris.brezillon@bootlin.com> wrote:
> >   
> > > Hi Bartosz,
> > > 
> > > On Fri, 10 Aug 2018 10:05:03 +0200
> > > Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > >     
> > > > From: Alban Bedel <albeu@free.fr>
> > > > 
> > > > Allow drivers that use the nvmem API to read data stored on MTD devices.
> > > > For this the mtd devices are registered as read-only NVMEM providers.
> > > > 
> > > > Signed-off-by: Alban Bedel <albeu@free.fr>
> > > > [Bartosz:
> > > >   - use the managed variant of nvmem_register(),
> > > >   - set the nvmem name]
> > > > Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>      
> > > 
> > > What happened to the 2 other patches of Alban's series? I'd really
> > > like the DT case to be handled/agreed on in the same patchset, but
> > > IIRC, Alban and Srinivas disagreed on how this should be represented.
> > > I hope this time we'll come to an agreement, because the MTD <-> NVMEM
> > > glue has been floating around for quite some time...    
> > 
> > These other patches were to fix what I consider a fundamental flaw in
> > the generic NVMEM bindings, however we couldn't agree on this point.
> > Bartosz later contacted me to take over this series and I suggested to
> > just change the MTD NVMEM binding to use a compatible string on the
> > NVMEM cells as an alternative solution to fix the clash with the old
> > style MTD partition.
> > 
> > However all this has no impact on the code needed to add NVMEM support
> > to MTD, so the above patch didn't change at all.  
> 
> It does have an impact on the supported binding though.
> nvmem->dev.of_node is automatically assigned to mtd->dev.of_node, which
> means people will be able to define their NVMEM cells directly under
> the MTD device and reference them from other nodes (even if it's not
> documented), and as you said, it conflict with the old MTD partition
> bindings. So we'd better agree on this binding before merging this
> patch.

Unless the nvmem cell node has a compatible string, then it won't be
considered as a partition by the MTD code. That is were the clash is,
both bindings allow free named child nodes without a compatible string.

> I see several options:
> 
> 1/ provide a way to tell the NVMEM framework not to use parent->of_node
>    even if it's != NULL. This way we really don't support defining
>    NVMEM cells in the DT, and also don't support referencing the nvmem
>    device using a phandle.

I really don't get what the point of this would be. Make the whole API
useless?

> 2/ define a new binding where all nvmem-cells are placed in an
>    "nvmem" subnode (just like we have this "partitions" subnode for
>    partitions), and then add a config->of_node field so that the
>    nvmem provider can explicitly specify the DT node representing the
>    nvmem device. We'll also need to set this field to ERR_PTR(-ENOENT)
>    in case this node does not exist so that the nvmem framework knows
>    that it should not assign nvmem->dev.of_node to parent->of_node

This is not good. First the NVMEM device is only a virtual concept of
the Linux kernel, it has no place in the DT. Secondly the NVMEM
provider (here the MTD device) then has to manually parse its DT node to
find this subnode, pass it to the NVMEM framework to later again
resolve it back to the MTD device. Not very complex but still a lot of
useless code, just registering the MTD device is a lot simpler and much
more inline with most other kernel API that register a "service"
available from a device.

> 3/ only declare partitions as nvmem providers. This would solve the
>    problem we have with partitions defined in the DT since
>    defining sub-partitions in the DT is not (yet?) supported and
>    partition nodes are supposed to be leaf nodes. Still, I'm not a big
>    fan of this solution because it will prevent us from supporting
>    sub-partitions if we ever want/need to.

That sound like a poor workaround. Remember that this problem could
appear with any device that has a binding that use child nodes.

> 4/ Add a ->of_xlate() hook that would be called if present by the
>    framework instead of using the default parsing we have right now.

That is a bit cleaner, but I don't think it would be worse the
complexity. Furthermore xlate functions are more about converting
from hardware parameters to internal kernel representation than to hide
extra DT parsing.

> 5/ Tell the nvmem framework the name of the subnode containing nvmem
>    cell definitions (if NULL that means cells are directly defined
>    under the nvmem provider node). We would set it to "nvmem-cells" (or
>    whatever you like) for the MTD case.

If so please match on compatible and not on the node name.

6/ Extend the current NVMEM cell lookup to check if the parent node of
the cell has a compatible string set to "nvmem-cells". If it doesn't it
mean we have the current binding and this node is the NVMEM device. If
it does the device node is just the next parent. This is trivial to
implement (literally 2 lines of code) and cover all the cases currently
known.

7/ Just add a compatible string to the nvmem cell. No code change is
needed, however as the nvmem cells have an address space (the offset in
byte in the storage) it might still clash with another address space
used by the main device biding (for example a number of child
functions).

> There are probably other options (some were proposed by Alban and
> Srinivas already), but I'd like to get this sorted out before we merge
> this patch.
> 
> Alban, Srinivas, any opinion?

My preference goes to 6/ as it is trivial to implement, solves all
known shortcomings and is backward compatible with the current binding.
All other solutions have limitations and/or require too complex
implementations compared to what they try to solve.

Alban

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH iproute2] iproute: make clang happy
From: Stephen Hemminger @ 2018-08-20 22:50 UTC (permalink / raw)
  To: Mahesh Bandewar; +Cc: netdev, Mahesh Bandewar
In-Reply-To: <20180820214215.218127-1-mahesh@bandewar.net>

On Mon, 20 Aug 2018 14:42:15 -0700
Mahesh Bandewar <mahesh@bandewar.net> wrote:

>  
>  		if (is_json_context()) {
> +			json_writer_t *jw;
> +
>  			open_json_object("bittiming");
>  			print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
> -			jsonw_float_field_fmt(get_json_writer(),
> -					      "sample_point", "%.3f",
> -					      (float) bt->sample_point / 1000.);
> +			jw = get_json_writer();
> +			jsonw_name(jw, "sample_point");
> +			jsonw_printf(jw, "%.3f",
> +				     (float) bt->sample_point / 1000);

I think it would be better to get rid of the is_json_context() here in  the CAN code
and just use the print_json functions completely.  Most of the other code is able to
do that already.

^ permalink raw reply

* Re: [PATCH] dt-bindings: can: rcar_can: Add r8a774a1 support
From: Rob Herring @ 2018-08-20 22:32 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Wolfgang Grandegger, Marc Kleine-Budde, Mark Rutland,
	Fabrizio Castro, David S. Miller, linux-can, netdev, devicetree,
	Simon Horman, Geert Uytterhoeven, Chris Paterson, Biju Das,
	linux-renesas-soc, linux-kernel
In-Reply-To: <1534516703-11448-1-git-send-email-fabrizio.castro@bp.renesas.com>

On Fri, 17 Aug 2018 15:38:23 +0100, Fabrizio Castro wrote:
> Document RZ/G2M (r8a774a1) SoC bindings.
> 
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> Reviewed-by: Biju Das <biju.das@bp.renesas.com>
> ---
> This patch applies on top of next-20180817
> 
>  Documentation/devicetree/bindings/net/can/rcar_can.txt | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* [PATCH iproute2] iproute: make clang happy
From: Mahesh Bandewar @ 2018-08-20 21:42 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Mahesh Bandewar

From: Mahesh Bandewar <maheshb@google.com>

These are primarily fixes for "string is not string literal" warnings
/ errors (with -Werror -Wformat-nonliteral). This should be a no-op
change. I had to replace couple of print helper functions with the
code they call as it was becoming harder to eliminate these warnings,
however these helpers were used only at couple of places, so no
major change as such.

Signed-off-by: Mahesh Bandewar <maheshb@google.com>
---
 include/json_writer.h |  2 --
 ip/iplink_can.c       | 19 ++++++++++++-------
 lib/color.c           |  1 +
 lib/json_print.c      |  1 +
 lib/json_writer.c     | 15 +--------------
 misc/ss.c             |  3 ++-
 tc/m_ematch.c         |  1 +
 7 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/include/json_writer.h b/include/json_writer.h
index 9ab88e1dbdd9..a111cc62e7b2 100644
--- a/include/json_writer.h
+++ b/include/json_writer.h
@@ -59,8 +59,6 @@ void jsonw_luint_field(json_writer_t *self, const char *prop,
 			unsigned long int num);
 void jsonw_lluint_field(json_writer_t *self, const char *prop,
 			unsigned long long int num);
-void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
-			   const char *fmt, double val);
 
 /* Collections */
 void jsonw_start_object(json_writer_t *self);
diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index 587413da15c4..c0deeb1f1fcf 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -316,11 +316,14 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
 
 		if (is_json_context()) {
+			json_writer_t *jw;
+
 			open_json_object("bittiming");
 			print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
-			jsonw_float_field_fmt(get_json_writer(),
-					      "sample_point", "%.3f",
-					      (float) bt->sample_point / 1000.);
+			jw = get_json_writer();
+			jsonw_name(jw, "sample_point");
+			jsonw_printf(jw, "%.3f",
+				     (float) bt->sample_point / 1000);
 			print_int(PRINT_ANY, "tq", NULL, bt->tq);
 			print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
 			print_int(PRINT_ANY, "phase_seg1",
@@ -415,12 +418,14 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 			RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
 
 		if (is_json_context()) {
+			json_writer_t *jw;
+
 			open_json_object("data_bittiming");
 			print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
-			jsonw_float_field_fmt(get_json_writer(),
-					      "sample_point",
-					      "%.3f",
-					      (float) dbt->sample_point / 1000.);
+			jw = get_json_writer();
+			jsonw_name(jw, "sample_point");
+			jsonw_printf(jw, "%.3f",
+				     (float) dbt->sample_point / 1000.);
 			print_int(PRINT_JSON, "tq", NULL, dbt->tq);
 			print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
 			print_int(PRINT_JSON, "phase_seg1",
diff --git a/lib/color.c b/lib/color.c
index eaf69e74d673..e5406294dfc4 100644
--- a/lib/color.c
+++ b/lib/color.c
@@ -132,6 +132,7 @@ void set_color_palette(void)
 		is_dark_bg = 1;
 }
 
+__attribute__((format(printf, 3, 4)))
 int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
 {
 	int ret = 0;
diff --git a/lib/json_print.c b/lib/json_print.c
index 5dc41bfabfd4..77902824a738 100644
--- a/lib/json_print.c
+++ b/lib/json_print.c
@@ -100,6 +100,7 @@ void close_json_array(enum output_type type, const char *str)
  * functions handling different types
  */
 #define _PRINT_FUNC(type_name, type)					\
+	__attribute__((format(printf, 4, 0)))				\
 	void print_color_##type_name(enum output_type t,		\
 				     enum color_attr color,		\
 				     const char *key,			\
diff --git a/lib/json_writer.c b/lib/json_writer.c
index aa9ce1c65e51..68890b34ee92 100644
--- a/lib/json_writer.c
+++ b/lib/json_writer.c
@@ -152,6 +152,7 @@ void jsonw_name(json_writer_t *self, const char *name)
 		putc(' ', self->out);
 }
 
+__attribute__((format(printf, 2, 3)))
 void jsonw_printf(json_writer_t *self, const char *fmt, ...)
 {
 	va_list ap;
@@ -205,11 +206,6 @@ void jsonw_null(json_writer_t *self)
 	jsonw_printf(self, "null");
 }
 
-void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
-{
-	jsonw_printf(self, fmt, num);
-}
-
 void jsonw_float(json_writer_t *self, double num)
 {
 	jsonw_printf(self, "%g", num);
@@ -274,15 +270,6 @@ void jsonw_float_field(json_writer_t *self, const char *prop, double val)
 	jsonw_float(self, val);
 }
 
-void jsonw_float_field_fmt(json_writer_t *self,
-			   const char *prop,
-			   const char *fmt,
-			   double val)
-{
-	jsonw_name(self, prop);
-	jsonw_float_fmt(self, fmt, val);
-}
-
 void jsonw_uint_field(json_writer_t *self, const char *prop, unsigned int num)
 {
 	jsonw_name(self, prop);
diff --git a/misc/ss.c b/misc/ss.c
index 41e7762bb61f..93b1baf5dc40 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -976,6 +976,7 @@ static int buf_update(int len)
 }
 
 /* Append content to buffer as part of the current field */
+__attribute__((format(printf, 1, 2)))
 static void out(const char *fmt, ...)
 {
 	struct column *f = current_field;
@@ -1093,7 +1094,7 @@ static void print_header(void)
 {
 	while (!field_is_last(current_field)) {
 		if (!current_field->disabled)
-			out(current_field->header);
+			out("%s", current_field->header);
 		field_next();
 	}
 }
diff --git a/tc/m_ematch.c b/tc/m_ematch.c
index ace4b3dd738b..a524b520b276 100644
--- a/tc/m_ematch.c
+++ b/tc/m_ematch.c
@@ -277,6 +277,7 @@ static int flatten_tree(struct ematch *head, struct ematch *tree)
 	return count;
 }
 
+__attribute__((format(printf, 5, 6)))
 int em_parse_error(int err, struct bstr *args, struct bstr *carg,
 		   struct ematch_util *e, char *fmt, ...)
 {
-- 
2.18.0.865.gffc8e1a3cd6-goog

^ permalink raw reply related

* Re: [PATCH v2 06/29] mtd: Add support for reading MTD devices via the nvmem API
From: Alban @ 2018-08-20 21:27 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Aban Bedel, Srinivas Kandagatla, Bartosz Golaszewski,
	Jonathan Corbet, Sekhar Nori, Kevin Hilman, Russell King,
	Arnd Bergmann, Greg Kroah-Hartman, David Woodhouse, Brian Norris,
	Marek Vasut, Richard Weinberger, Grygorii Strashko,
	David S . Miller, Naren, Mauro Carvalho Chehab, Andrew Morton,
	Lukas Wunner, Dan 
In-Reply-To: <20180820202038.5d3dc195@bbrezillon>

[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]

On Mon, 20 Aug 2018 20:20:38 +0200
Boris Brezillon <boris.brezillon@bootlin.com> wrote:

> On Mon, 20 Aug 2018 11:43:34 +0100
> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote:
> 
> > 
> > Overall am still not able to clear visualize on how MTD bindings with 
> > nvmem cells would look in both partition and un-partition usecases?
> > An example DT would be nice here!!  
> 
> Something along those lines:

We must also have a compatible string on the nvmem-cells node to make
sure we don't clash with the old style MTD partitions, or some other
device specific binding.

> 
> 	mtdnode {
> 		nvmem-cells {
                        compatible = "nvmem-cells";
> 			#address-cells = <1>;
> 			#size-cells = <1>;
> 
> 			cell@0 {
> 				reg = <0x0 0x14>;
> 			};
> 		};
> 
> 		partitions {
> 			compatible = "fixed-partitions";
> 			#address-cells = <1>;
> 			#size-cells = <1>;
> 
> 			partition@0 {
> 				reg = <0x0 0x20000>;
> 
> 				nvmem-cells {
                                        compatible = "nvmem-cells";
> 					#address-cells = <1>;
> 					#size-cells = <1>;
> 
> 					cell@0 {
> 						reg = <0x0 0x10>;
> 					};
> 				};
> 			};
> 		};
> 	};


Alban

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [bpf-next RFC 0/3] Introduce eBPF flow dissector
From: Alexei Starovoitov @ 2018-08-20 20:52 UTC (permalink / raw)
  To: Petar Penkov
  Cc: netdev, davem, ast, daniel, simon.horman, Petar Penkov, willemb
In-Reply-To: <20180816164423.14368-1-peterpenkov96@gmail.com>

On Thu, Aug 16, 2018 at 09:44:20AM -0700, Petar Penkov wrote:
> From: Petar Penkov <ppenkov@google.com>
> 
> This patch series hardens the RX stack by allowing flow dissection in BPF,
> as previously discussed [1]. Because of the rigorous checks of the BPF
> verifier, this provides significant security guarantees. In particular, the
> BPF flow dissector cannot get inside of an infinite loop, as with
> CVE-2013-4348, because BPF programs are guaranteed to terminate. It cannot
> read outside of packet bounds, because all memory accesses are checked.
> Also, with BPF the administrator can decide which protocols to support,
> reducing potential attack surface. Rarely encountered protocols can be
> excluded from dissection and the program can be updated without kernel
> recompile or reboot if a bug is discovered.
> 
> Patch 1 adds infrastructure to execute a BPF program in __skb_flow_dissect.
> This includes a new BPF program and attach type.
> 
> Patch 2 adds a flow dissector program in BPF. This parses most protocols in
> __skb_flow_dissect in BPF for a subset of flow keys (basic, control, ports,
> and address types).
> 
> Patch 3 adds a selftest that attaches the BPF program to the flow dissector
> and sends traffic with different levels of encapsulation.

Overall I fully support the direction. Few things to consider:

> This RFC patchset exposes a few design considerations:
> 
> 1/ Because the flow dissector key definitions live in
> include/linux/net/flow_dissector.h, they are not visible from userspace,
> and the flow keys definitions need to be copied in the BPF program.

I don't think copy-paste avoids the issue of uapi.
Anything used by BPF program is uapi.
The only exception is offsets of kernel internal structures
passed into bpf_probe_read().
So we have several options:
1. be honest and say 'struct flow_dissect_key*' is now uapi
2. wrap all of them into 'struct bpf_flow_dissect_key*' and do rewrites
  when/if 'struct flow_dissect_key*' changes
3. wait for BTF to solve it for tracing use case and for this one two.
The idea is that kernel internal structs can be defined in bpf prog
and since they will be described precisely in BTF that comes with the prog
the kernel can validate that prog's BTF matches what kernel thinks it has.
imo that's the most flexible, but BTF for all of vmlinux won't be ready
tomorrow and looks like this patch set is ready to go, so I would go with 1 or 2.

> 2/ An alternative to adding a new hook would have been to attach flow
> dissection programs at the XDP hook. Because this hook is executed before
> GRO, it would have to execute on every MSS, which would be more
> computationally expensive. Furthermore, the XDP hook is executed before an
> SKB has been allocated and there is no clear way to move the dissected keys
> into the SKB after it has been allocated. Eventually, perhaps a single pass
> can implement both GRO and flow dissection -- but napi_gro_cb shows that a
> lot more flow state would need to be parsed for this.

global flow_dissect bpf hook semantics are problematic for testing.
like patch 3 test affects the whole system including all containers.
should the hook be per-netns or may be per netdevice?

> 3/ The BPF program cannot use direct packet access everywhere because it
> uses an offset, initially supplied by the flow dissector.  Because the
> initial value of this non-constant offset comes from outside of the
> program, the verifier does not know what its value is, and it cannot verify
> that it is within packet bounds. Therefore, direct packet access programs
> get rejected.

this part doesn't seem to match the code.
direct packet access is allowed and usable even for fragmented skbs.
in such case only linear part of skb is in "direct access".

Last bit, I'm curious about, how the 'demo' flow dissector program
from patch 2 fairs vs in-kernel dissector when performance tested?

^ permalink raw reply

* Re: r8169 needs CONFIG_REALTEK_PHY
From: Florian Fainelli @ 2018-08-20 20:39 UTC (permalink / raw)
  To: Marc Dionne, hkallweit1, netdev, David Miller
In-Reply-To: <CAB9dFdurBUDvDkfFdK5aqAnM5J0MP7r5K83HbQRNJP_wWdAvvw@mail.gmail.com>

On 08/20/2018 12:44 PM, Marc Dionne wrote:
> The r8169 adapter in one of my machines was not working after updating
> to a current kernel from the merge window, which was fixed by enabling
> CONFIG_REALTEK_PHY.
> 
> So in addition to "select PHYLIB", should CONFIG_R8169 not also be
> doing "select CONFIG_REALTEK_PHY" ?

This is fixed in Linus' tree now with:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bfdd19ad80f203f42f05fd32a31c678c9c524ef9
-- 
Florian

^ permalink raw reply

* Re: r8169 needs CONFIG_REALTEK_PHY
From: Heiner Kallweit @ 2018-08-20 20:38 UTC (permalink / raw)
  To: Marc Dionne, netdev, David Miller
In-Reply-To: <CAB9dFdurBUDvDkfFdK5aqAnM5J0MP7r5K83HbQRNJP_wWdAvvw@mail.gmail.com>

On 20.08.2018 21:44, Marc Dionne wrote:
> The r8169 adapter in one of my machines was not working after updating
> to a current kernel from the merge window, which was fixed by enabling
> CONFIG_REALTEK_PHY.
> 
> So in addition to "select PHYLIB", should CONFIG_R8169 not also be
> doing "select CONFIG_REALTEK_PHY" ?
> 
This fix was applied already and is included in latest linux-next.
bfdd19ad80f2 ("r8169: add missing Kconfig dependency")

> Marc
> 

^ permalink raw reply

* Re: [PATCH net-next v8 0/7] net: vhost: improve performance when enable busyloop
From: Michael S. Tsirkin @ 2018-08-20 20:34 UTC (permalink / raw)
  To: xiangxia.m.yue; +Cc: jasowang, makita.toshiaki, virtualization, netdev
In-Reply-To: <1534680686-3108-1-git-send-email-xiangxia.m.yue@gmail.com>

On Sun, Aug 19, 2018 at 05:11:19AM -0700, xiangxia.m.yue@gmail.com wrote:
> From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
> 
> This patches improve the guest receive performance.
> On the handle_tx side, we poll the sock receive queue
> at the same time. handle_rx do that in the same way.
> 
> For more performance report, see patch 4, 6, 7


Thanks for the patches. I'm traveling this week,
will do my best to review next week.

> Tonghao Zhang (7):
>   net: vhost: lock the vqs one by one
>   net: vhost: replace magic number of lock annotation
>   net: vhost: factor out busy polling logic to vhost_net_busy_poll()
>   net: vhost: add rx busy polling in tx path
>   net: vhost: introduce bitmap for vhost_poll
>   net: vhost: disable rx wakeup during tx busypoll
>   net: vhost: make busyloop_intr more accurate
> 
>  drivers/vhost/net.c   | 169 +++++++++++++++++++++++++++++++-------------------
>  drivers/vhost/vhost.c |  41 ++++++------
>  drivers/vhost/vhost.h |   7 ++-
>  3 files changed, 133 insertions(+), 84 deletions(-)
> 
> -- 
> 1.8.3.1

^ permalink raw reply

* Re: Checkpatch False positive
From: Jeff Kirsher @ 2018-08-20 20:32 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Andy Whitcroft, Joe Perches, netdev, Linux Docs
In-Reply-To: <20180820202250.GA6345@bombadil.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]

On Mon, 2018-08-20 at 13:22 -0700, Matthew Wilcox wrote:
> On Mon, Aug 20, 2018 at 01:21:30PM -0700, Jeff Kirsher wrote:
> > Checkpatch.pl should probably exclude *.rst files from the SPDX
> > License
> > Identifier check, since they are documentational files, like
> > *.txt. 
> 
> They're still copyrighted work, so they should still have SPDX tags
> to identify their license.
> 
> checkpatch has:
> 
>                                 } elsif ($realfile =~ /\.rst$/) {
>                                         $comment = '..';
> 
> so we're explicitly including rst files in the checking for now.

Ah, sorry.  I did not catch that they started to include SPDX-License-
Identifiers for RST files, thanks Matthew.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [RFC RFT PATCH v4 4/4] gpiolib: Implement fast processing path in get/set array
From: Janusz Krzysztofik @ 2018-08-20 23:43 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jonathan Corbet, Miguel Ojeda Sandonis, Peter Korsgaard,
	Peter Rosin, Ulf Hansson, Andrew Lunn, Florian Fainelli,
	David S. Miller, Dominik Brodowski, Kishon Vijay Abraham I,
	Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
	Hartmut Knaack, Peter Meerwald-Stadler, Greg Kroah-Hartman,
	Jiri Slaby, linux-gpio, linux-doc, linux-i2c
In-Reply-To: <20180820234341.5271-1-jmkrzyszt@gmail.com>

Certain GPIO descriptor arrays returned by gpio_get_array() may contain
information on direct mapping of array members to pins of a single GPIO
chip in hardware order.  In such cases, bitmaps of values can be passed
directly from/to the chip's .get/set_multiple() callbacks without
wasting time on iterations.

Add respective code to gpiod_get/set_array_bitmap_complex() functions.
Pins not applicable for fast path are processed as before, skipping
over the 'fast' ones.

Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
 Documentation/driver-api/gpio/board.rst    | 15 ++++++
 Documentation/driver-api/gpio/consumer.rst |  8 +++
 drivers/gpio/gpiolib.c                     | 87 ++++++++++++++++++++++++++++--
 3 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
index 2c112553df84..c66821e033c2 100644
--- a/Documentation/driver-api/gpio/board.rst
+++ b/Documentation/driver-api/gpio/board.rst
@@ -193,3 +193,18 @@ And the table can be added to the board code as follows::
 
 The line will be hogged as soon as the gpiochip is created or - in case the
 chip was created earlier - when the hog table is registered.
+
+Arrays of pins
+--------------
+In addition to requesting pins belonging to a function one by one, a device may
+also request an array of pins assigned to the function.  The way those pins are
+mapped to the device determines if the array qualifies for fast bitmap
+processing.  If yes, a bitmap is passed over get/set array functions directly
+between a caller and a respective .get/set_multiple() callback of a GPIO chip.
+
+In order to qualify for fast bitmap processing, the pin mapping must meet the
+following requirements:
+- it must belong to the same chip as other 'fast' pins of the function,
+- its index within the function must match its hardware number within the chip.
+
+Open drain and open source pins are excluded from fast bitmap output processing.
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index 0afd95a12b10..cf992e5ab976 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -388,6 +388,14 @@ array_info should be set to NULL.
 Note that for optimal performance GPIOs belonging to the same chip should be
 contiguous within the array of descriptors.
 
+Still better performance may be achieved if array indexes of the descriptors
+match hardware pin numbers of a single chip.  If an array passed to a get/set
+array function matches the one obtained from gpiod_get_array() and array_info
+associated with the array is also passed, the function may take a fast bitmap
+processing path, passing the value_bitmap argument directly to the respective
+.get/set_multiple() callback of the chip.  That allows for utilization of GPIO
+banks as data I/O ports without much loss of performance.
+
 The return value of gpiod_get_array_value() and its variants is 0 on success
 or negative on error. Note the difference to gpiod_get_value(), which returns
 0 or 1 on success to convey the GPIO value. With the array functions, the GPIO
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4d26cdbdb7cf..b799a89c4c17 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2787,7 +2787,36 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 				  struct gpio_array *array_info,
 				  unsigned long *value_bitmap)
 {
-	int i = 0;
+	int err, i = 0;
+
+	/*
+	 * Validate array_info against desc_array and its size.
+	 * It should immediately follow desc_array if both
+	 * have been obtained from the same gpiod_get_array() call.
+	 */
+	if (array_info && array_info->desc == desc_array &&
+	    array_size <= array_info->size &&
+	    (void *)array_info == desc_array + array_info->size) {
+		if (!can_sleep)
+			WARN_ON(array_info->chip->can_sleep);
+
+		err = gpio_chip_get_multiple(array_info->chip,
+					     array_info->get_mask,
+					     value_bitmap);
+		if (err)
+			return err;
+
+		if (!raw && !bitmap_empty(array_info->invert_mask, array_size))
+			bitmap_xor(value_bitmap, value_bitmap,
+				   array_info->invert_mask, array_size);
+
+		if (bitmap_full(array_info->get_mask, array_size))
+			return 0;
+
+		i = find_first_zero_bit(array_info->get_mask, array_size);
+	} else {
+		array_info = NULL;
+	}
 
 	while (i < array_size) {
 		struct gpio_chip *chip = desc_array[i]->gdev->chip;
@@ -2818,7 +2847,12 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 			int hwgpio = gpio_chip_hwgpio(desc);
 
 			__set_bit(hwgpio, mask);
-			i++;
+
+			if (array_info)
+				find_next_zero_bit(array_info->get_mask,
+						   array_size, i);
+			else
+				i++;
 		} while ((i < array_size) &&
 			 (desc_array[i]->gdev->chip == chip));
 
@@ -2829,7 +2863,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 			return ret;
 		}
 
-		for (j = first; j < i; j++) {
+		for (j = first; j < i; ) {
 			const struct gpio_desc *desc = desc_array[j];
 			int hwgpio = gpio_chip_hwgpio(desc);
 			int value = test_bit(hwgpio, bits);
@@ -2838,6 +2872,11 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 				value = !value;
 			__assign_bit(j, value_bitmap, value);
 			trace_gpio_value(desc_to_gpio(desc), 1, value);
+
+			if (array_info)
+				find_next_zero_bit(array_info->get_mask, i, j);
+			else
+				j++;
 		}
 
 		if (mask != fastpath)
@@ -3039,6 +3078,32 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 {
 	int i = 0;
 
+	/*
+	 * Validate array_info against desc_array and its size.
+	 * It should immediately follow desc_array if both
+	 * have been obtained from the same gpiod_get_array() call.
+	 */
+	if (array_info && array_info->desc == desc_array &&
+	    array_size <= array_info->size &&
+	    (void *)array_info == desc_array + array_info->size) {
+		if (!can_sleep)
+			WARN_ON(array_info->chip->can_sleep);
+
+		if (!raw && !bitmap_empty(array_info->invert_mask, array_size))
+			bitmap_xor(value_bitmap, value_bitmap,
+				   array_info->invert_mask, array_size);
+
+		gpio_chip_set_multiple(array_info->chip, array_info->set_mask,
+				       value_bitmap);
+
+		if (bitmap_full(array_info->set_mask, array_size))
+			return 0;
+
+		i = find_first_zero_bit(array_info->set_mask, array_size);
+	} else {
+		array_info = NULL;
+	}
+
 	while (i < array_size) {
 		struct gpio_chip *chip = desc_array[i]->gdev->chip;
 		unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)];
@@ -3066,7 +3131,14 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 			int hwgpio = gpio_chip_hwgpio(desc);
 			int value = test_bit(i, value_bitmap);
 
-			if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+			/*
+			 * Pins applicable for fast input but not for
+			 * fast output processing may have been already
+			 * inverted inside the fast path, skip them.
+			 */
+			if (!raw && !(array_info &&
+			    test_bit(i, array_info->invert_mask)) &&
+			    test_bit(FLAG_ACTIVE_LOW, &desc->flags))
 				value = !value;
 			trace_gpio_value(desc_to_gpio(desc), 0, value);
 			/*
@@ -3085,7 +3157,12 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 					__clear_bit(hwgpio, bits);
 				count++;
 			}
-			i++;
+
+			if (array_info)
+				find_next_zero_bit(array_info->set_mask,
+						   array_size, i);
+			else
+				i++;
 		} while ((i < array_size) &&
 			 (desc_array[i]->gdev->chip == chip));
 		/* push collected bits to outputs */
-- 
2.16.4

^ permalink raw reply related

* [RFC RFT PATCH v4 3/4] gpiolib: Pass array info to get/set array functions
From: Janusz Krzysztofik @ 2018-08-20 23:43 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andrew Lunn, Ulf Hansson, linux-doc, linux-iio, Dominik Brodowski,
	netdev, linux-i2c, Peter Meerwald-Stadler, devel,
	Florian Fainelli, Jonathan Corbet, Janusz Krzysztofik,
	Kishon Vijay Abraham I, linux-serial, Jiri Slaby,
	Michael Hennerich, linux-gpio, Lars-Peter Clausen,
	Greg Kroah-Hartman, linux-mmc, linux-kernel, Peter Rosin,
	Miguel Ojeda Sandonis, Peter Korsgaard, Hartmut Knaack <kna
In-Reply-To: <20180820234341.5271-1-jmkrzyszt@gmail.com>

In order to make use of array info obtained from gpiod_get_array() and
speed up processing of arrays matching single GPIO chip layout, that
information must be passed to get/set array functions.  Extend the
functions' API with that additional parameter and update all users.
Pass NULL if a user bulids an array itself from single GPIOs.

Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
 Documentation/driver-api/gpio/consumer.rst  | 14 ++++++++++--
 drivers/auxdisplay/hd44780.c                | 12 ++++++----
 drivers/bus/ts-nbus.c                       |  6 +++--
 drivers/gpio/gpio-max3191x.c                |  6 +++--
 drivers/gpio/gpiolib.c                      | 34 ++++++++++++++++++++---------
 drivers/gpio/gpiolib.h                      |  2 ++
 drivers/i2c/muxes/i2c-mux-gpio.c            |  2 +-
 drivers/mmc/core/pwrseq_simple.c            |  2 +-
 drivers/mux/gpio.c                          |  3 ++-
 drivers/net/phy/mdio-mux-gpio.c             |  2 +-
 drivers/pcmcia/soc_common.c                 |  3 ++-
 drivers/phy/motorola/phy-mapphone-mdm6600.c |  4 +++-
 drivers/staging/iio/adc/ad7606.c            |  3 ++-
 drivers/tty/serial/serial_mctrl_gpio.c      |  2 +-
 include/linux/gpio/consumer.h               |  8 +++++++
 15 files changed, 75 insertions(+), 28 deletions(-)

diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index 7e0298b9a7b9..0afd95a12b10 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -325,28 +325,36 @@ The following functions get or set the values of an array of GPIOs::
 
 	int gpiod_get_array_value(unsigned int array_size,
 				  struct gpio_desc **desc_array,
+				  struct gpio_array *array_info,
 				  unsigned long *value_bitmap);
 	int gpiod_get_raw_array_value(unsigned int array_size,
 				      struct gpio_desc **desc_array,
+				      struct gpio_array *array_info,
 				      unsigned long *value_bitmap);
 	int gpiod_get_array_value_cansleep(unsigned int array_size,
 					   struct gpio_desc **desc_array,
+					   struct gpio_array *array_info,
 					   unsigned long *value_bitmap);
 	int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
 					   struct gpio_desc **desc_array,
+					   struct gpio_array *array_info,
 					   unsigned long *value_bitmap);
 
 	void gpiod_set_array_value(unsigned int array_size,
 				   struct gpio_desc **desc_array,
+				   struct gpio_array *array_info,
 				   unsigned long *value_bitmap)
 	void gpiod_set_raw_array_value(unsigned int array_size,
 				       struct gpio_desc **desc_array,
+				       struct gpio_array *array_info,
 				       unsigned long *value_bitmap)
 	void gpiod_set_array_value_cansleep(unsigned int array_size,
 					    struct gpio_desc **desc_array,
+					    struct gpio_array *array_info,
 					    unsigned long *value_bitmap)
 	void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
 						struct gpio_desc **desc_array,
+						struct gpio_array *array_info,
 						unsigned long *value_bitmap)
 
 The array can be an arbitrary set of GPIOs. The functions will try to access
@@ -358,6 +366,7 @@ accessed sequentially.
 The functions take three arguments:
 	* array_size	- the number of array elements
 	* desc_array	- an array of GPIO descriptors
+	* array_info	- optional information obtained from gpiod_array_get()
 	* value_bitmap	- a bitmap to store the GPIOs' values (get) or
 			  a bitmap of values to assign to the GPIOs (set)
 
@@ -368,12 +377,13 @@ the struct gpio_descs returned by gpiod_get_array()::
 
 	struct gpio_descs *my_gpio_descs = gpiod_get_array(...);
 	gpiod_set_array_value(my_gpio_descs->ndescs, my_gpio_descs->desc,
-			      my_gpio_value_bitmap);
+			      my_gpio_descs->info, my_gpio_value_bitmap);
 
 It is also possible to access a completely arbitrary array of descriptors. The
 descriptors may be obtained using any combination of gpiod_get() and
 gpiod_get_array(). Afterwards the array of descriptors has to be setup
-manually before it can be passed to one of the above functions.
+manually before it can be passed to one of the above functions.  In that case,
+array_info should be set to NULL.
 
 Note that for optimal performance GPIOs belonging to the same chip should be
 contiguous within the array of descriptors.
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index d340473aa142..6ae81632bc44 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -74,7 +74,8 @@ static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs)
 	}
 
 	/* Present the data to the port */
-	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], value_bitmap);
+	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], NULL,
+				       value_bitmap);
 
 	hd44780_strobe_gpio(hd);
 }
@@ -97,7 +98,8 @@ static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
 	value_bitmap[0] = value_bitmap[0] >> PIN_DATA4;
 
 	/* Present the data to the port */
-	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], value_bitmap);
+	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL,
+				       value_bitmap);
 
 	hd44780_strobe_gpio(hd);
 
@@ -106,7 +108,8 @@ static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
 	value_bitmap[0] |= val & ~((1 << PIN_DATA4) - 1);
 
 	/* Present the data to the port */
-	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], value_bitmap);
+	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL,
+				       value_bitmap);
 
 	hd44780_strobe_gpio(hd);
 }
@@ -169,7 +172,8 @@ static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd)
 	value_bitmap[0] = value_bitmap[0] >> PIN_DATA4;
 
 	/* Present the data to the port */
-	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], value_bitmap);
+	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL,
+				       value_bitmap);
 
 	hd44780_strobe_gpio(hd);
 }
diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c
index ce6c1e89236d..000d756eb42c 100644
--- a/drivers/bus/ts-nbus.c
+++ b/drivers/bus/ts-nbus.c
@@ -112,7 +112,8 @@ static void ts_nbus_reset_bus(struct ts_nbus *ts_nbus)
 {
 	unsigned long value_bitmap[1] = { 0, };
 
-	gpiod_set_array_value_cansleep(8, ts_nbus->data->desc, value_bitmap);
+	gpiod_set_array_value_cansleep(8, ts_nbus->data->desc,
+				       ts_nbus->data->info, value_bitmap);
 	gpiod_set_value_cansleep(ts_nbus->csn, 0);
 	gpiod_set_value_cansleep(ts_nbus->strobe, 0);
 	gpiod_set_value_cansleep(ts_nbus->ale, 0);
@@ -155,7 +156,8 @@ static void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte)
 	struct gpio_descs *gpios = ts_nbus->data;
 	unsigned long value_bitmap[1] = { byte, };
 
-	gpiod_set_array_value_cansleep(8, gpios->desc, value_bitmap);
+	gpiod_set_array_value_cansleep(8, gpios->desc, gpios->info,
+				       value_bitmap);
 }
 
 /*
diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c
index c4ec1c82af27..4b43b5dabfd2 100644
--- a/drivers/gpio/gpio-max3191x.c
+++ b/drivers/gpio/gpio-max3191x.c
@@ -313,6 +313,7 @@ static int max3191x_set_config(struct gpio_chip *gpio, unsigned int offset,
 
 static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
 						  struct gpio_desc **desc,
+						  struct gpio_array *info,
 						  int value)
 {
 	unsigned long *value_bitmap;
@@ -327,7 +328,7 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
 	else
 		bitmap_zero(value_bitmap, ndescs);
 
-	gpiod_set_array_value_cansleep(ndescs, desc, value_bitmap);
+	gpiod_set_array_value_cansleep(ndescs, desc, info, value_bitmap);
 	kfree(value_bitmap);
 }
 
@@ -400,7 +401,8 @@ static int max3191x_probe(struct spi_device *spi)
 	if (max3191x->modesel_pins)
 		gpiod_set_array_single_value_cansleep(
 				 max3191x->modesel_pins->ndescs,
-				 max3191x->modesel_pins->desc, max3191x->mode);
+				 max3191x->modesel_pins->desc,
+				 max3191x->modesel_pins->info, max3191x->mode);
 
 	max3191x->ignore_uv = device_property_read_bool(dev,
 						  "maxim,ignore-undervoltage");
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c1ed1c759345..4d26cdbdb7cf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -435,7 +435,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
 		int ret = gpiod_get_array_value_complex(false,
 							true,
 							lh->numdescs,
-							lh->descs,
+							lh->descs, NULL,
 							value_bitmap);
 		if (ret)
 			return ret;
@@ -467,7 +467,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
 		return gpiod_set_array_value_complex(false,
 					      true,
 					      lh->numdescs,
-					      lh->descs,
+					      lh->descs, NULL,
 					      value_bitmap);
 	}
 	return -EINVAL;
@@ -2784,6 +2784,7 @@ static int gpio_chip_get_multiple(struct gpio_chip *chip,
 int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 				  unsigned int array_size,
 				  struct gpio_desc **desc_array,
+				  struct gpio_array *array_info,
 				  unsigned long *value_bitmap)
 {
 	int i = 0;
@@ -2908,12 +2909,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);
  */
 int gpiod_get_raw_array_value(unsigned int array_size,
 			      struct gpio_desc **desc_array,
+			      struct gpio_array *array_info,
 			      unsigned long *value_bitmap)
 {
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_get_array_value_complex(true, false, array_size,
-					     desc_array, value_bitmap);
+					     desc_array, array_info,
+					     value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value);
 
@@ -2931,12 +2934,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value);
  */
 int gpiod_get_array_value(unsigned int array_size,
 			  struct gpio_desc **desc_array,
+			  struct gpio_array *array_info,
 			  unsigned long *value_bitmap)
 {
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_get_array_value_complex(false, false, array_size,
-					     desc_array, value_bitmap);
+					     desc_array, array_info,
+					     value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_get_array_value);
 
@@ -3029,6 +3034,7 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip,
 int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 				   unsigned int array_size,
 				   struct gpio_desc **desc_array,
+				   struct gpio_array *array_info,
 				   unsigned long *value_bitmap)
 {
 	int i = 0;
@@ -3166,12 +3172,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_value);
  */
 int gpiod_set_raw_array_value(unsigned int array_size,
 			 struct gpio_desc **desc_array,
+			 struct gpio_array *array_info,
 			 unsigned long *value_bitmap)
 {
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_set_array_value_complex(true, false, array_size,
-					desc_array, value_bitmap);
+					desc_array, array_info, value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
 
@@ -3189,12 +3196,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
  */
 void gpiod_set_array_value(unsigned int array_size,
 			   struct gpio_desc **desc_array,
+			   struct gpio_array *array_info,
 			   unsigned long *value_bitmap)
 {
 	if (!desc_array)
 		return;
 	gpiod_set_array_value_complex(false, false, array_size, desc_array,
-				      value_bitmap);
+				      array_info, value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_array_value);
 
@@ -3426,13 +3434,15 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
  */
 int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
 				       struct gpio_desc **desc_array,
+				       struct gpio_array *array_info,
 				       unsigned long *value_bitmap)
 {
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_get_array_value_complex(true, true, array_size,
-					     desc_array, value_bitmap);
+					     desc_array, array_info,
+					     value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value_cansleep);
 
@@ -3449,13 +3459,15 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value_cansleep);
  */
 int gpiod_get_array_value_cansleep(unsigned int array_size,
 				   struct gpio_desc **desc_array,
+				   struct gpio_array *array_info,
 				   unsigned long *value_bitmap)
 {
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_get_array_value_complex(false, true, array_size,
-					     desc_array, value_bitmap);
+					     desc_array, array_info,
+					     value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_get_array_value_cansleep);
 
@@ -3508,13 +3520,14 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
  */
 int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
 					struct gpio_desc **desc_array,
+					struct gpio_array *array_info,
 					unsigned long *value_bitmap)
 {
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return -EINVAL;
 	return gpiod_set_array_value_complex(true, true, array_size, desc_array,
-				      value_bitmap);
+				      array_info, value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep);
 
@@ -3548,13 +3561,14 @@ void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n)
  */
 void gpiod_set_array_value_cansleep(unsigned int array_size,
 				    struct gpio_desc **desc_array,
+				    struct gpio_array *array_info,
 				    unsigned long *value_bitmap)
 {
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return;
 	gpiod_set_array_value_complex(false, true, array_size, desc_array,
-				      value_bitmap);
+				      array_info, value_bitmap);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
 
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index b60905d558b1..b65ca896b24d 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -196,10 +196,12 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
 int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 				  unsigned int array_size,
 				  struct gpio_desc **desc_array,
+				  struct gpio_array *array_info,
 				  unsigned long *value_bitmap);
 int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 				   unsigned int array_size,
 				   struct gpio_desc **desc_array,
+				   struct gpio_array *array_info,
 				   unsigned long *value_bitmap);
 
 /* This is just passed between gpiolib and devres */
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index d675e0ca2fa4..aa3857ab42b5 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -34,7 +34,7 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
 		mux->values[i] = (val >> i) & 1;
 
 	gpiod_set_array_value_cansleep(mux->data.n_gpios,
-				       mux->gpios, value_bitmap);
+				       mux->gpios, NULL, value_bitmap);
 }
 
 static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 0d6e3a5be3ba..5cf7eda8f68f 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -46,7 +46,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
 		value_bitmap[0] = value;
 
 		gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc,
-					       value_bitmap);
+					       reset_gpios->info, value_bitmap);
 	}
 }
 
diff --git a/drivers/mux/gpio.c b/drivers/mux/gpio.c
index cc2d5f50472a..879f9f3f45dd 100644
--- a/drivers/mux/gpio.c
+++ b/drivers/mux/gpio.c
@@ -30,7 +30,8 @@ static int mux_gpio_set(struct mux_control *mux, int state)
 		mux_gpio->val[i] = (state >> i) & 1;
 
 	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
-				       mux_gpio->gpios->desc, value_bitmap);
+				       mux_gpio->gpios->desc,
+				       mux_gpio->gpios->info, value_bitmap);
 
 	return 0;
 }
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index 8e1ec750277e..c0ffa03c916b 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -37,7 +37,7 @@ static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
 		s->values[n] = (desired_child >> n) & 1;
 
 	gpiod_set_array_value_cansleep(s->gpios->ndescs, s->gpios->desc,
-				       value_bitmap);
+				       s->gpios->info, value_bitmap);
 
 	return 0;
 }
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index e0f89155c474..55978198cd2b 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -366,7 +366,8 @@ static int soc_common_pcmcia_config_skt(
 		}
 
 		if (n)
-			gpiod_set_array_value_cansleep(n, descs, value_bitmap);
+			gpiod_set_array_value_cansleep(n, descs, NULL,
+						       value_bitmap);
 
 		/*
 		 * This really needs a better solution.  The IRQ
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c
index b6477c3599c4..8f508338ec56 100644
--- a/drivers/phy/motorola/phy-mapphone-mdm6600.c
+++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c
@@ -162,7 +162,8 @@ static void phy_mdm6600_cmd(struct phy_mdm6600 *ddata, int val)
 	value_bitmap[0] = val & ((1 << PHY_MDM6600_NR_CMD_LINES) - 1);
 
 	gpiod_set_array_value_cansleep(PHY_MDM6600_NR_CMD_LINES,
-				       ddata->cmd_gpios->desc, value_bitmap);
+				       ddata->cmd_gpios->desc,
+				       ddata->cmd_gpios->info, value_bitmap);
 }
 
 /**
@@ -181,6 +182,7 @@ static void phy_mdm6600_status(struct work_struct *work)
 
 	error = gpiod_get_array_value_cansleep(PHY_MDM6600_NR_STATUS_LINES,
 					       ddata->status_gpios->desc,
+					       ddata->status_gpios->info,
 					       value_bitmap);
 	if (error)
 		return;
diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c
index 0eca047bc1cc..eb779d825724 100644
--- a/drivers/staging/iio/adc/ad7606.c
+++ b/drivers/staging/iio/adc/ad7606.c
@@ -230,7 +230,8 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
 		value_bitmap[0] = ret;
 
 		mutex_lock(&st->lock);
-		gpiod_set_array_value(3, st->gpio_os->desc, value_bitmap);
+		gpiod_set_array_value(3, st->gpio_os->desc, st->gpio_os->info,
+				      value_bitmap);
 		st->oversampling = val;
 		mutex_unlock(&st->lock);
 
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index bb8b4756d72d..8a04e3be5419 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -53,7 +53,7 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
 				     !!(mctrl & mctrl_gpios_desc[i].mctrl));
 			count++;
 		}
-	gpiod_set_array_value(count, desc_array, value_bitmap);
+	gpiod_set_array_value(count, desc_array, NULL, value_bitmap);
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_set);
 
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 8dede3e886af..bf037ebe2ed8 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -114,36 +114,44 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
 int gpiod_get_value(const struct gpio_desc *desc);
 int gpiod_get_array_value(unsigned int array_size,
 			  struct gpio_desc **desc_array,
+			  struct gpio_array *array_info,
 			  unsigned long *value_bitmap);
 void gpiod_set_value(struct gpio_desc *desc, int value);
 void gpiod_set_array_value(unsigned int array_size,
 			   struct gpio_desc **desc_array,
+			   struct gpio_array *array_info,
 			   unsigned long *value_bitmap);
 int gpiod_get_raw_value(const struct gpio_desc *desc);
 int gpiod_get_raw_array_value(unsigned int array_size,
 			      struct gpio_desc **desc_array,
+			      struct gpio_array *array_info,
 			      unsigned long *value_bitmap);
 void gpiod_set_raw_value(struct gpio_desc *desc, int value);
 int gpiod_set_raw_array_value(unsigned int array_size,
 			       struct gpio_desc **desc_array,
+			       struct gpio_array *array_info,
 			       unsigned long *value_bitmap);
 
 /* Value get/set from sleeping context */
 int gpiod_get_value_cansleep(const struct gpio_desc *desc);
 int gpiod_get_array_value_cansleep(unsigned int array_size,
 				   struct gpio_desc **desc_array,
+				   struct gpio_array *array_info,
 				   unsigned long *value_bitmap);
 void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
 void gpiod_set_array_value_cansleep(unsigned int array_size,
 				    struct gpio_desc **desc_array,
+				    struct gpio_array *array_info,
 				    unsigned long *value_bitmap);
 int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc);
 int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
 				       struct gpio_desc **desc_array,
+				       struct gpio_array *array_info,
 				       unsigned long *value_bitmap);
 void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
 int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
 					struct gpio_desc **desc_array,
+					struct gpio_array *array_info,
 					unsigned long *value_bitmap);
 
 int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
-- 
2.16.4

^ permalink raw reply related

* [RFC RFT PATCH v4 2/4] gpiolib: Identify arrays matching GPIO hardware
From: Janusz Krzysztofik @ 2018-08-20 23:43 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andrew Lunn, Ulf Hansson, linux-doc, linux-iio, Dominik Brodowski,
	netdev, linux-i2c, Peter Meerwald-Stadler, devel,
	Florian Fainelli, Jonathan Corbet, Janusz Krzysztofik,
	Kishon Vijay Abraham I, linux-serial, Jiri Slaby,
	Michael Hennerich, linux-gpio, Lars-Peter Clausen,
	Greg Kroah-Hartman, linux-mmc, linux-kernel, Peter Rosin,
	Miguel Ojeda Sandonis, Peter Korsgaard, Hartmut Knaack <kna
In-Reply-To: <20180820234341.5271-1-jmkrzyszt@gmail.com>

Certain GPIO array lookup results may map directly to GPIO pins of a
single GPIO chip in hardware order.  If that condition is recognized
and handled efficiently, significant performance gain of get/set array
functions may be possible.

While processing a request for an array of GPIO descriptors, identify
those which represent corresponding pins of a single GPIO chip.  Skip
over pins which require open source or open drain special processing.
Moreover, identify pins which require inversion.  Pass a pointer to
that information with the array to the caller so it can benefit from
enhanced performance as soon as get/set array functions can accept and
make efficient use of it.

Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
 Documentation/driver-api/gpio/consumer.rst |  4 +-
 drivers/gpio/gpiolib.c                     | 72 +++++++++++++++++++++++++++++-
 drivers/gpio/gpiolib.h                     |  9 ++++
 include/linux/gpio/consumer.h              |  9 ++++
 4 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index ed68042ddccf..7e0298b9a7b9 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -109,9 +109,11 @@ For a function using multiple GPIOs all of those can be obtained with one call::
 					   enum gpiod_flags flags)
 
 This function returns a struct gpio_descs which contains an array of
-descriptors::
+descriptors.  It also contains a pointer to a gpiolib private structure which,
+if passed back to get/set array functions, may speed up I/O proocessing::
 
 	struct gpio_descs {
+		struct gpio_array *info;
 		unsigned int ndescs;
 		struct gpio_desc *desc[];
 	}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f0e9ffa8cab6..c1ed1c759345 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -4174,7 +4174,9 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
 {
 	struct gpio_desc *desc;
 	struct gpio_descs *descs;
-	int count;
+	struct gpio_array *array_info = NULL;
+	struct gpio_chip *chip;
+	int count, bitmap_size;
 
 	count = gpiod_count(dev, con_id);
 	if (count < 0)
@@ -4190,9 +4192,77 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
 			gpiod_put_array(descs);
 			return ERR_CAST(desc);
 		}
+
 		descs->desc[descs->ndescs] = desc;
+
+		chip = gpiod_to_chip(desc);
+		/*
+		 * Select a chip of first array member
+		 * whose index matches its pin hardware number
+		 * as a candidate for fast bitmap processing.
+		 */
+		if (!array_info && gpio_chip_hwgpio(desc) == descs->ndescs) {
+			struct gpio_descs *array;
+
+			bitmap_size = BITS_TO_LONGS(chip->ngpio > count ?
+						    chip->ngpio : count);
+
+			array = kzalloc(struct_size(descs, desc, count) +
+					struct_size(array_info, invert_mask,
+					3 * bitmap_size), GFP_KERNEL);
+			if (!array) {
+				gpiod_put_array(descs);
+				return ERR_PTR(-ENOMEM);
+			}
+
+			memcpy(array, descs,
+			       struct_size(descs, desc, descs->ndescs + 1));
+			kfree(descs);
+
+			descs = array;
+			array_info = (void *)(descs->desc + count);
+			array_info->get_mask = array_info->invert_mask +
+						  bitmap_size;
+			array_info->set_mask = array_info->get_mask +
+						  bitmap_size;
+
+			array_info->desc = descs->desc;
+			array_info->size = count;
+			array_info->chip = chip;
+			bitmap_set(array_info->get_mask, descs->ndescs,
+				   count - descs->ndescs);
+			bitmap_set(array_info->set_mask, descs->ndescs,
+				   count - descs->ndescs);
+			descs->info = array_info;
+		}
+		/*
+		 * Unmark members which don't qualify for fast bitmap
+		 * processing (different chip, not in hardware order)
+		 */
+		if (array_info && (chip != array_info->chip ||
+		    gpio_chip_hwgpio(desc) != descs->ndescs)) {
+			__clear_bit(descs->ndescs, array_info->get_mask);
+			__clear_bit(descs->ndescs, array_info->set_mask);
+		} else if (array_info) {
+			/* Exclude open drain or open source from fast output */
+			if (gpiochip_line_is_open_drain(chip, descs->ndescs) ||
+			    gpiochip_line_is_open_source(chip, descs->ndescs))
+				__clear_bit(descs->ndescs,
+					    array_info->set_mask);
+			/* Identify 'fast' pins which require invertion */
+			if (gpiod_is_active_low(desc))
+				__set_bit(descs->ndescs,
+					  array_info->invert_mask);
+		}
+
 		descs->ndescs++;
 	}
+	if (array_info)
+		dev_dbg(dev,
+			"GPIO array info: chip=%s, size=%d, get_mask=%lx, set_mask=%lx, invert_mask=%lx\n",
+			array_info->chip->label, array_info->size,
+			*array_info->get_mask, *array_info->set_mask,
+			*array_info->invert_mask);
 	return descs;
 }
 EXPORT_SYMBOL_GPL(gpiod_get_array);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 11e83d2eef89..b60905d558b1 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -183,6 +183,15 @@ static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
 }
 #endif
 
+struct gpio_array {
+	struct gpio_desc	**desc;
+	unsigned int		size;
+	struct gpio_chip	*chip;
+	unsigned long		*get_mask;
+	unsigned long		*set_mask;
+	unsigned long		invert_mask[];
+};
+
 struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
 int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 				  unsigned int array_size,
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 1b21dc7b0fad..8dede3e886af 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -17,11 +17,20 @@ struct device;
  */
 struct gpio_desc;
 
+/**
+ * Opaque descriptor for a structure of GPIO array attributes.  This structure
+ * is attached to struct gpiod_descs obtained from gpiod_get_array() and can be
+ * passed back to get/set array functions in order to activate fast processing
+ * path if applicable.
+ */
+struct gpio_array;
+
 /**
  * Struct containing an array of descriptors that can be obtained using
  * gpiod_get_array().
  */
 struct gpio_descs {
+	struct gpio_array *info;
 	unsigned int ndescs;
 	struct gpio_desc *desc[];
 };
-- 
2.16.4

^ permalink raw reply related

* [RFC RFT PATCH 0/4] gpiolib: speed up GPIO array processing
From: Janusz Krzysztofik @ 2018-08-20 23:43 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andrew Lunn, Ulf Hansson, linux-doc, linux-iio, Dominik Brodowski,
	netdev, linux-i2c, Peter Meerwald-Stadler, devel,
	Florian Fainelli, Jonathan Corbet, Janusz Krzysztofik,
	Kishon Vijay Abraham I, linux-serial, Jiri Slaby,
	Michael Hennerich, linux-gpio, Lars-Peter Clausen,
	Greg Kroah-Hartman, linux-mmc, linux-kernel, Peter Rosin,
	Miguel Ojeda Sandonis, Peter Korsgaard, Hartmut Knaack <kna
In-Reply-To: <20180813223448.21316-1-jmkrzyszt@gmail.com>


This series is a follow up of the former "mtd: rawnand: ams-delta: Use
gpio-omap accessors for data I/O" which already contained some changes
to gpiolib.  Those previous attempts were commented by Borris Brezillon
who suggested using GPIO API modified to accept bitmaps, and by Linus
Walleij who suggested still more great ideas for further immprovement
of the proposed API changes - thanks!

The goal is to boost performans of get/set array functions while
processing GPIO arrays which represent pins of a signle chip in
hardware order.  If resulting performance is close to PIO, GPIO API
can be used for data I/O without much loss of speed.

Created and tested on a low end Amstrad Delta board with NAND driver
updated to use GPIO API for data I/O.  Performance degrade compared to
PIO is much better than before the optimization but still not quite
satisfactory.


Janusz Krzysztofik (4):
      gpiolib: Pass bitmaps, not integer arrays, to get/set array
      gpiolib: Identify arrays matching GPIO hardware
      gpiolib: Pass array info to get/set array functions
      gpiolib: Implement fast processing path in get/set array


 Documentation/driver-api/gpio/board.rst     |   15 +
 Documentation/driver-api/gpio/consumer.rst  |   48 +++-
 drivers/auxdisplay/hd44780.c                |   64 +++---
 drivers/bus/ts-nbus.c                       |   25 --
 drivers/gpio/gpio-max3191x.c                |   23 +-
 drivers/gpio/gpiolib.c                      |  279 ++++++++++++++++++++++------
 drivers/gpio/gpiolib.h                      |   15 +
 drivers/i2c/muxes/i2c-mux-gpio.c            |    5 
 drivers/mmc/core/pwrseq_simple.c            |   15 -
 drivers/mux/gpio.c                          |    7 
 drivers/net/phy/mdio-mux-gpio.c             |    5 
 drivers/pcmcia/soc_common.c                 |   14 -
 drivers/phy/motorola/phy-mapphone-mdm6600.c |   21 +-
 drivers/staging/iio/adc/ad7606.c            |   12 -
 drivers/tty/serial/serial_mctrl_gpio.c      |    9 
 include/linux/gpio/consumer.h               |   35 ++-
 16 files changed, 410 insertions(+), 182 deletions(-)

^ permalink raw reply

* Re: Checkpatch False positive
From: Matthew Wilcox @ 2018-08-20 20:22 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: Andy Whitcroft, Joe Perches, netdev, Linux Docs
In-Reply-To: <8cf91e5fb848eecd98a2f9493387906b3a5f1506.camel@intel.com>

On Mon, Aug 20, 2018 at 01:21:30PM -0700, Jeff Kirsher wrote:
> Checkpatch.pl should probably exclude *.rst files from the SPDX License
> Identifier check, since they are documentational files, like *.txt. 

They're still copyrighted work, so they should still have SPDX tags
to identify their license.

checkpatch has:

                                } elsif ($realfile =~ /\.rst$/) {
                                        $comment = '..';

so we're explicitly including rst files in the checking for now.

^ permalink raw reply

* Checkpatch False positive
From: Jeff Kirsher @ 2018-08-20 20:21 UTC (permalink / raw)
  To: Andy Whitcroft, Joe Perches; +Cc: netdev, Linux Docs

[-- Attachment #1: Type: text/plain, Size: 845 bytes --]

Checkpatch.pl should probably exclude *.rst files from the SPDX License
Identifier check, since they are documentational files, like *.txt. 
Here is the warning message I got on a recent documentation patch I
created.

WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
#28: FILE: Documentation/networking/fm10k.rst:1:
+Linux* Base Driver for Intel(R) Ethernet Multi-host Controller

total: 0 errors, 1 warnings, 0 checks, 162 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-
inplace.

.apply/v4-Documentation-fm10k-Add-kernel-documentation.patch has style
problems, please review.

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [PATCH net] net/ipv6: Put lwtstate when destroying fib6_info
From: dsahern @ 2018-08-20 20:02 UTC (permalink / raw)
  To: netdev; +Cc: davem, David Ahern

From: David Ahern <dsahern@gmail.com>

Prior to the introduction of fib6_info lwtstate was managed by the dst
code. With fib6_info releasing lwtstate needs to be done when the struct
is freed.

Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes")
Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/ip6_fib.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index d212738e9d10..c861a6d4671d 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -198,6 +198,8 @@ void fib6_info_destroy_rcu(struct rcu_head *head)
 		}
 	}
 
+	lwtstate_put(f6i->fib6_nh.nh_lwtstate);
+
 	if (f6i->fib6_nh.nh_dev)
 		dev_put(f6i->fib6_nh.nh_dev);
 
-- 
2.11.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox