* [PATCH net-next 13/14] tipc: add name table dump to new netlink api
From: richard.alpe @ 2014-09-11 8:29 UTC (permalink / raw)
To: netdev; +Cc: tipc-discussion
In-Reply-To: <1410424167-17427-1-git-send-email-richard.alpe@ericsson.com>
From: Richard Alpe <richard.alpe@ericsson.com>
Add TIPC_NL_NAME_TABLE_GET command to the new tipc netlink API.
This command supports dumping the name table of all nodes.
Netlink logical layout of name table response message:
-> name table
-> publication
-> type
-> lower
-> upper
-> scope
-> node
-> ref
-> key
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
include/uapi/linux/tipc_config.h | 11 +++
net/tipc/name_table.c | 190 +++++++++++++++++++++++++++++++++++++-
net/tipc/name_table.h | 4 +-
net/tipc/netlink.c | 9 +-
4 files changed, 211 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 6fdb819..3d1a4ab 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -63,6 +63,7 @@ enum {
TIPC_NL_NODE_GET,
TIPC_NL_NET_GET,
TIPC_NL_NET_SET,
+ TIPC_NL_NAME_TABLE_GET,
__TIPC_NL_CMD_MAX,
TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -77,6 +78,7 @@ enum {
TIPC_NLA_MEDIA, /* nest */
TIPC_NLA_NODE, /* nest */
TIPC_NLA_NET, /* nest */
+ TIPC_NLA_NAME_TABLE, /* nest */
__TIPC_NLA_MAX,
TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -152,6 +154,15 @@ enum {
TIPC_NLA_NET_MAX = __TIPC_NLA_NET_MAX - 1
};
+/* Name table info */
+enum {
+ TIPC_NLA_NAME_TABLE_UNSPEC,
+ TIPC_NLA_NAME_TABLE_PUBL, /* nest */
+
+ __TIPC_NLA_NAME_TABLE_MAX,
+ TIPC_NLA_NAME_TABLE_MAX = __TIPC_NLA_NAME_TABLE_MAX - 1
+};
+
/* Nest, publication info */
enum {
TIPC_NLA_PUBL_UNSPEC,
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 3a6a0a7..7d69229 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1,7 +1,7 @@
/*
* net/tipc/name_table.c: TIPC name table code
*
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2014, Ericsson AB
* Copyright (c) 2004-2008, 2010-2011, Wind River Systems
* All rights reserved.
*
@@ -42,6 +42,12 @@
#define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */
+static const struct nla_policy
+tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = {
+ [TIPC_NLA_NAME_TABLE_UNSPEC] = { .type = NLA_UNSPEC },
+ [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED }
+};
+
/**
* struct name_info - name sequence publication info
* @node_list: circular list of publications made by own node
@@ -995,3 +1001,185 @@ void tipc_nametbl_stop(void)
table.types = NULL;
write_unlock_bh(&tipc_nametbl_lock);
}
+
+int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, struct name_seq *seq,
+ struct sub_seq *sseq, u32 *last_publ)
+{
+ void *hdr;
+ struct nlattr *attrs;
+ struct nlattr *publ;
+ struct publication *p;
+
+ if (*last_publ) {
+ list_for_each_entry(p, &sseq->info->zone_list, zone_list)
+ if (p->key == *last_publ)
+ break;
+ if (p->key != *last_publ)
+ return -EPIPE;
+ } else {
+ p = list_first_entry(&sseq->info->zone_list, struct publication,
+ zone_list);
+ }
+
+ list_for_each_entry_from(p, &sseq->info->zone_list, zone_list) {
+ *last_publ = p->key;
+
+ hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
+ &tipc_genl_family, NLM_F_MULTI,
+ TIPC_NL_NAME_TABLE_GET);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ attrs = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE);
+ if (!attrs)
+ goto msg_full;
+
+ publ = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
+ if (!publ)
+ goto attr_msg_full;
+
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, seq->type))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sseq->lower))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sseq->upper))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->ref))
+ goto publ_msg_full;
+ if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
+ goto publ_msg_full;
+
+ nla_nest_end(msg->skb, publ);
+ nla_nest_end(msg->skb, attrs);
+ genlmsg_end(msg->skb, hdr);
+ }
+ *last_publ = 0;
+
+ return 0;
+
+publ_msg_full:
+ nla_nest_cancel(msg->skb, publ);
+attr_msg_full:
+ nla_nest_cancel(msg->skb, attrs);
+msg_full:
+ genlmsg_cancel(msg->skb, hdr);
+
+ return -EMSGSIZE;
+}
+
+int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq,
+ u32 *last_lower, u32 *last_publ)
+{
+ struct sub_seq *sseq;
+ struct sub_seq *sseq_start;
+ int err;
+
+ if (*last_lower) {
+ sseq_start = nameseq_find_subseq(seq, *last_lower);
+ if (!sseq_start)
+ return -EPIPE;
+ } else {
+ sseq_start = seq->sseqs;
+ }
+
+ for (sseq = sseq_start; sseq != &seq->sseqs[seq->first_free]; sseq++) {
+ err = __tipc_nl_add_nametable_publ(msg, seq, sseq, last_publ);
+ if (err) {
+ *last_lower = sseq->lower;
+ return err;
+ }
+ }
+ *last_lower = 0;
+
+ return 0;
+}
+
+int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, u32 *last_lower,
+ u32 *last_publ)
+{
+ struct hlist_head *seq_head;
+ struct name_seq *seq;
+ int err;
+ int i;
+
+ if (*last_type)
+ i = hash(*last_type);
+ else
+ i = 0;
+
+ for (; i < TIPC_NAMETBL_SIZE; i++) {
+ seq_head = &table.types[i];
+
+ if (*last_type) {
+ seq = nametbl_find_seq(*last_type);
+ if (!seq)
+ return -EPIPE;
+ } else {
+ seq = hlist_entry_safe((seq_head)->first,
+ struct name_seq, ns_list);
+ if (!seq)
+ continue;
+ }
+
+ hlist_for_each_entry_from(seq, ns_list) {
+ spin_lock_bh(&seq->lock);
+
+ err = __tipc_nl_subseq_list(msg, seq, last_lower,
+ last_publ);
+
+ if (err) {
+ *last_type = seq->type;
+ spin_unlock_bh(&seq->lock);
+ return err;
+ }
+ spin_unlock_bh(&seq->lock);
+ }
+ *last_type = 0;
+ }
+ return 0;
+}
+
+int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int err;
+ int done = cb->args[3];
+ u32 last_type = cb->args[0];
+ u32 last_lower = cb->args[1];
+ u32 last_publ = cb->args[2];
+ struct tipc_nl_msg msg;
+
+ if (done)
+ return 0;
+
+ msg.skb = skb;
+ msg.portid = NETLINK_CB(cb->skb).portid;
+ msg.seq = cb->nlh->nlmsg_seq;
+
+ read_lock_bh(&tipc_nametbl_lock);
+
+ err = __tipc_nl_seq_list(&msg, &last_type, &last_lower, &last_publ);
+ if (!err) {
+ done = 1;
+ } else if (err != -EMSGSIZE) {
+ /* We never set seq or call nl_dump_check_consistent() this
+ * means that setting prev_seq here will cause the consistence
+ * check to fail in the netlink callback handler. Resulting in
+ * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
+ * we got an error.
+ */
+ cb->prev_seq = 1;
+ }
+
+ read_unlock_bh(&tipc_nametbl_lock);
+
+ cb->args[0] = last_type;
+ cb->args[1] = last_lower;
+ cb->args[2] = last_publ;
+ cb->args[3] = done;
+
+ return skb->len;
+}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f02f48b..b38ebec 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -1,7 +1,7 @@
/*
* net/tipc/name_table.h: Include file for TIPC name table code
*
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2014, Ericsson AB
* Copyright (c) 2004-2005, 2010-2011, Wind River Systems
* All rights reserved.
*
@@ -84,6 +84,8 @@ struct publication {
extern rwlock_t tipc_nametbl_lock;
+int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 7803aa9..11a2fd8 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -37,6 +37,7 @@
#include "core.h"
#include "config.h"
#include "socket.h"
+#include "name_table.h"
#include "bearer.h"
#include "link.h"
#include "node.h"
@@ -80,7 +81,8 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
[TIPC_NLA_LINK] = { .type = NLA_NESTED, },
[TIPC_NLA_MEDIA] = { .type = NLA_NESTED, },
[TIPC_NLA_NODE] = { .type = NLA_NESTED, },
- [TIPC_NLA_NET] = { .type = NLA_NESTED, }
+ [TIPC_NLA_NET] = { .type = NLA_NESTED, },
+ [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, }
};
struct genl_family tipc_genl_family = {
@@ -164,6 +166,11 @@ static const struct genl_ops tipc_genl_ops[] = {
.cmd = TIPC_NL_NET_SET,
.doit = tipc_nl_net_set,
.policy = tipc_nl_policy,
+ },
+ {
+ .cmd = TIPC_NL_NAME_TABLE_GET,
+ .dumpit = tipc_nl_name_table_dump,
+ .policy = tipc_nl_policy,
}
};
--
1.7.10.4
------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
^ permalink raw reply related
* [PATCH net-next 14/14] tipc: remove old ASCII netlink API
From: richard.alpe @ 2014-09-11 8:29 UTC (permalink / raw)
To: netdev; +Cc: tipc-discussion
In-Reply-To: <1410424167-17427-1-git-send-email-richard.alpe@ericsson.com>
From: Richard Alpe <richard.alpe@ericsson.com>
The API has been deprecated along with its user-space tool
"tipc-config". Users shall use the new kernel netlink API already in
place along with the new user space tool "tipc" that's part of the
tipc-utils package.
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
include/uapi/linux/tipc_config.h | 299 +--------------------------------
net/tipc/Makefile | 2 +-
net/tipc/bcast.c | 41 -----
net/tipc/bcast.h | 1 -
net/tipc/bearer.c | 65 --------
net/tipc/bearer.h | 1 -
net/tipc/config.c | 342 --------------------------------------
net/tipc/config.h | 67 --------
net/tipc/core.c | 3 +-
net/tipc/link.c | 311 ----------------------------------
net/tipc/link.h | 7 -
net/tipc/log.c | 1 -
net/tipc/name_table.c | 185 +--------------------
net/tipc/name_table.h | 1 +
net/tipc/net.c | 1 -
net/tipc/netlink.c | 36 ----
net/tipc/node.c | 113 +------------
net/tipc/node.h | 2 -
net/tipc/socket.c | 77 ---------
net/tipc/socket.h | 1 -
20 files changed, 8 insertions(+), 1548 deletions(-)
delete mode 100644 net/tipc/config.c
delete mode 100644 net/tipc/config.h
diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 3d1a4ab..359c627 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -38,13 +38,6 @@
#define _LINUX_TIPC_CONFIG_H_
#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/tipc.h>
-#include <asm/byteorder.h>
-
-#ifndef __KERNEL__
-#include <arpa/inet.h> /* for ntohs etc. */
-#endif
/* Netlink commands */
enum {
@@ -248,115 +241,6 @@ enum {
};
/*
- * Configuration
- *
- * All configuration management messaging involves sending a request message
- * to the TIPC configuration service on a node, which sends a reply message
- * back. (In the future multi-message replies may be supported.)
- *
- * Both request and reply messages consist of a transport header and payload.
- * The transport header contains info about the desired operation;
- * the payload consists of zero or more type/length/value (TLV) items
- * which specify parameters or results for the operation.
- *
- * For many operations, the request and reply messages have a fixed number
- * of TLVs (usually zero or one); however, some reply messages may return
- * a variable number of TLVs. A failed request is denoted by the presence
- * of an "error string" TLV in the reply message instead of the TLV(s) the
- * reply should contain if the request succeeds.
- */
-
-/*
- * Public commands:
- * May be issued by any process.
- * Accepted by own node, or by remote node only if remote management enabled.
- */
-
-#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */
-#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */
-#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */
-#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */
-#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */
-#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */
-#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */
-#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */
-#define TIPC_CMD_SHOW_STATS 0x000F /* tx unsigned, rx ultra_string */
-
-/*
- * Protected commands:
- * May only be issued by "network administration capable" process.
- * Accepted by own node, or by remote node only if remote management enabled
- * and this node is zone manager.
- */
-
-#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */
-#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */
-#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* obsoleted */
-#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* obsoleted */
-#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* obsoleted */
-#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* obsoleted */
-#define TIPC_CMD_GET_MAX_NODES 0x4009 /* obsoleted */
-#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* obsoleted */
-#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */
-
-#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */
-#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */
-#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */
-#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */
-#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */
-#define TIPC_CMD_SET_LOG_SIZE 0x410A /* obsoleted */
-#define TIPC_CMD_DUMP_LOG 0x410B /* obsoleted */
-#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */
-
-/*
- * Private commands:
- * May only be issued by "network administration capable" process.
- * Accepted by own node only; cannot be used on a remote node.
- */
-
-#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */
-#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */
-#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */
-#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* obsoleted */
-#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* obsoleted */
-#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* obsoleted */
-#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* obsoleted */
-#define TIPC_CMD_SET_MAX_NODES 0x8009 /* obsoleted */
-#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* obsoleted */
-#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */
-
-/*
- * Reserved commands:
- * May not be issued by any process.
- * Used internally by TIPC.
- */
-
-#define TIPC_CMD_NOT_NET_ADMIN 0xC001 /* tx none, rx none */
-
-/*
- * TLV types defined for TIPC
- */
-
-#define TIPC_TLV_NONE 0 /* no TLV present */
-#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/
-#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */
-#define TIPC_TLV_STRING 3 /* char[128] (max) */
-#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */
-#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */
-
-#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */
-#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */
-#define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */
-#define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */
-#define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */
-#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */
-#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */
-#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */
-#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */
-#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */
-#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */
-
-/*
* Link priority limits (min, default, max, media default)
*/
@@ -385,172 +269,17 @@ enum {
#define TIPC_DEF_LINK_WIN 50
#define TIPC_MAX_LINK_WIN 8191
-
-struct tipc_node_info {
- __be32 addr; /* network address of node */
- __be32 up; /* 0=down, 1= up */
-};
-
-struct tipc_link_info {
- __be32 dest; /* network address of peer node */
- __be32 up; /* 0=down, 1=up */
- char str[TIPC_MAX_LINK_NAME]; /* link name */
-};
-
-struct tipc_bearer_config {
- __be32 priority; /* Range [1,31]. Override per link */
- __be32 disc_domain; /* <Z.C.N> describing desired nodes */
- char name[TIPC_MAX_BEARER_NAME];
-};
-
-struct tipc_link_config {
- __be32 value;
- char name[TIPC_MAX_LINK_NAME];
-};
-
-#define TIPC_NTQ_ALLTYPES 0x80000000
-
-struct tipc_name_table_query {
- __be32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
- __be32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
- __be32 lowbound; /* (i.e. displays all entries of name table) */
- __be32 upbound;
-};
-
-/*
- * The error string TLV is a null-terminated string describing the cause
- * of the request failure. To simplify error processing (and to save space)
- * the first character of the string can be a special error code character
- * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason.
- */
-
-#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */
-#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */
-#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */
-#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */
-#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */
-#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */
-
-/*
- * A TLV consists of a descriptor, followed by the TLV value.
- * TLV descriptor fields are stored in network byte order;
- * TLV values must also be stored in network byte order (where applicable).
- * TLV descriptors must be aligned to addresses which are multiple of 4,
- * so up to 3 bytes of padding may exist at the end of the TLV value area.
- * There must not be any padding between the TLV descriptor and its value.
- */
-
-struct tlv_desc {
- __be16 tlv_len; /* TLV length (descriptor + value) */
- __be16 tlv_type; /* TLV identifier */
-};
-
-#define TLV_ALIGNTO 4
-
-#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1))
-#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen))
-#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen)))
-#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0)))
-
-static inline int TLV_OK(const void *tlv, __u16 space)
-{
- /*
- * Would also like to check that "tlv" is a multiple of 4,
- * but don't know how to do this in a portable way.
- * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler
- * won't allow binary "&" with a pointer.
- * - Tried casting "tlv" to integer type, but causes warning about size
- * mismatch when pointer is bigger than chosen type (int, long, ...).
- */
-
- return (space >= TLV_SPACE(0)) &&
- (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space);
-}
-
-static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type)
-{
- return TLV_OK(tlv, space) &&
- (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type);
-}
-
-static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len)
-{
- struct tlv_desc *tlv_ptr;
- int tlv_len;
-
- tlv_len = TLV_LENGTH(len);
- tlv_ptr = (struct tlv_desc *)tlv;
- tlv_ptr->tlv_type = htons(type);
- tlv_ptr->tlv_len = htons(tlv_len);
- if (len && data)
- memcpy(TLV_DATA(tlv_ptr), data, tlv_len);
- return TLV_SPACE(len);
-}
-
-/*
- * A TLV list descriptor simplifies processing of messages
- * containing multiple TLVs.
- */
-
-struct tlv_list_desc {
- struct tlv_desc *tlv_ptr; /* ptr to current TLV */
- __u32 tlv_space; /* # bytes from curr TLV to list end */
-};
-
-static inline void TLV_LIST_INIT(struct tlv_list_desc *list,
- void *data, __u32 space)
-{
- list->tlv_ptr = (struct tlv_desc *)data;
- list->tlv_space = space;
-}
-
-static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
-{
- return (list->tlv_space == 0);
-}
-
-static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type)
-{
- return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type);
-}
-
-static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
-{
- return TLV_DATA(list->tlv_ptr);
-}
-
-static inline void TLV_LIST_STEP(struct tlv_list_desc *list)
-{
- __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len));
-
- list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space);
- list->tlv_space -= tlv_space;
-}
-
/*
* Configuration messages exchanged via NETLINK_GENERIC use the following
* family id, name, version and command.
*/
#define TIPC_GENL_NAME "TIPC"
#define TIPC_GENL_VERSION 0x1
-#define TIPC_GENL_CMD 0x1
-
-/*
- * TIPC specific header used in NETLINK_GENERIC requests.
- */
-struct tipc_genlmsghdr {
- __u32 dest; /* Destination address */
- __u16 cmd; /* Command */
- __u16 reserved; /* Unused */
-};
-
-#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr))
/*
* Configuration messages exchanged via TIPC sockets use the TIPC configuration
- * message header, which is defined below. This structure is analogous
- * to the Netlink message header, but fields are stored in network byte order
- * and no padding is permitted between the header and the message data
+ * message header, which is defined below. Fields are stored in network byte
+ * order and no padding is permitted between the header and the message data
* that follows.
*/
@@ -561,28 +290,4 @@ struct tipc_cfg_msg_hdr {
char tcm_reserved[8]; /* Unused */
};
-#define TCM_F_REQUEST 0x1 /* Flag: Request message */
-#define TCM_F_MORE 0x2 /* Flag: Message to be continued */
-
-#define TCM_ALIGN(datalen) (((datalen)+3) & ~3)
-#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen)
-#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen)))
-#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0)))
-
-static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags,
- void *data, __u16 data_len)
-{
- struct tipc_cfg_msg_hdr *tcm_hdr;
- int msg_len;
-
- msg_len = TCM_LENGTH(data_len);
- tcm_hdr = (struct tipc_cfg_msg_hdr *)msg;
- tcm_hdr->tcm_len = htonl(msg_len);
- tcm_hdr->tcm_type = htons(cmd);
- tcm_hdr->tcm_flags = htons(flags);
- if (data_len && data)
- memcpy(TCM_DATA(msg), data, data_len);
- return TCM_SPACE(data_len);
-}
-
#endif
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
index b8a13ca..c68864f 100644
--- a/net/tipc/Makefile
+++ b/net/tipc/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_TIPC) := tipc.o
-tipc-y += addr.o bcast.o bearer.o config.o \
+tipc-y += addr.o bcast.o bearer.o \
core.o link.o discover.o msg.o \
name_distr.o subscr.o name_table.o net.o \
netlink.o node.o node_subscr.o \
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index e12476b..473f3a1 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -867,47 +867,6 @@ msg_full:
return -EMSGSIZE;
}
-int tipc_bclink_stats(char *buf, const u32 buf_size)
-{
- int ret;
- struct tipc_stats *s;
-
- if (!bcl)
- return 0;
-
- tipc_bclink_lock();
-
- s = &bcl->stats;
-
- ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
- " Window:%u packets\n",
- bcl->name, bcl->queue_limit[0]);
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
- s->recv_info, s->recv_fragments,
- s->recv_fragmented, s->recv_bundles,
- s->recv_bundled);
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
- s->sent_info, s->sent_fragments,
- s->sent_fragmented, s->sent_bundles,
- s->sent_bundled);
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " RX naks:%u defs:%u dups:%u\n",
- s->recv_nacks, s->deferred_recv, s->duplicates);
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " TX naks:%u acks:%u dups:%u\n",
- s->sent_nacks, s->sent_acks, s->retransmitted);
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " Congestion link:%u Send queue max:%u avg:%u\n",
- s->link_congs, s->max_queue_sz,
- s->queue_sz_counts ?
- (s->accu_queue_sz / s->queue_sz_counts) : 0);
-
- tipc_bclink_unlock();
- return ret;
-}
-
int tipc_bclink_reset_stats(void)
{
if (!bcl)
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 3c0263e..2c2443a 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -95,7 +95,6 @@ void tipc_bclink_rcv(struct sk_buff *buf);
u32 tipc_bclink_get_last_sent(void);
u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr);
void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent);
-int tipc_bclink_stats(char *stats_buf, const u32 buf_size);
int tipc_bclink_reset_stats(void);
int tipc_bclink_set_queue_limits(u32 limit);
void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 3e33771..6798219 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -35,7 +35,6 @@
*/
#include "core.h"
-#include "config.h"
#include "bearer.h"
#include "link.h"
#include "discover.h"
@@ -123,26 +122,6 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
}
/**
- * tipc_media_get_names - record names of registered media in buffer
- */
-struct sk_buff *tipc_media_get_names(void)
-{
- struct sk_buff *buf;
- int i;
-
- buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
- if (!buf)
- return NULL;
-
- for (i = 0; media_info_array[i] != NULL; i++) {
- tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
- media_info_array[i]->name,
- strlen(media_info_array[i]->name) + 1);
- }
- return buf;
-}
-
-/**
* bearer_name_validate - validate & (optionally) deconstruct bearer name
* @name: ptr to bearer name string
* @name_parts: ptr to area for bearer name components (or NULL if not needed)
@@ -203,34 +182,6 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
return NULL;
}
-/**
- * tipc_bearer_get_names - record names of bearers in buffer
- */
-struct sk_buff *tipc_bearer_get_names(void)
-{
- struct sk_buff *buf;
- struct tipc_bearer *b;
- int i, j;
-
- buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
- if (!buf)
- return NULL;
-
- for (i = 0; media_info_array[i] != NULL; i++) {
- for (j = 0; j < MAX_BEARERS; j++) {
- b = rtnl_dereference(bearer_list[j]);
- if (!b)
- continue;
- if (b->media == media_info_array[i]) {
- tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
- b->name,
- strlen(b->name) + 1);
- }
- }
- }
- return buf;
-}
-
void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
{
struct tipc_bearer *b_ptr;
@@ -413,22 +364,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
kfree_rcu(b_ptr, rcu);
}
-int tipc_disable_bearer(const char *name)
-{
- struct tipc_bearer *b_ptr;
- int res;
-
- b_ptr = tipc_bearer_find(name);
- if (b_ptr == NULL) {
- pr_warn("Attempt to disable unknown bearer <%s>\n", name);
- res = -EINVAL;
- } else {
- bearer_disable(b_ptr, false);
- res = 0;
- }
- return res;
-}
-
int tipc_enable_l2_media(struct tipc_bearer *b)
{
struct net_device *dev;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index b1d9052..8550ec8 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -167,7 +167,6 @@ extern struct tipc_bearer __rcu *bearer_list[];
void tipc_rcv(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
-int tipc_disable_bearer(const char *name);
/*
* Routines made available to TIPC by supported media types
diff --git a/net/tipc/config.c b/net/tipc/config.c
deleted file mode 100644
index 876f4c6..0000000
--- a/net/tipc/config.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * net/tipc/config.c: TIPC configuration management code
- *
- * Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2007, 2010-2013, Wind River Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "core.h"
-#include "socket.h"
-#include "name_table.h"
-#include "config.h"
-#include "server.h"
-
-#define REPLY_TRUNCATED "<truncated>\n"
-
-static const void *req_tlv_area; /* request message TLV area */
-static int req_tlv_space; /* request message TLV area size */
-static int rep_headroom; /* reply message headroom to use */
-
-struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
-{
- struct sk_buff *buf;
-
- buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
- if (buf)
- skb_reserve(buf, rep_headroom);
- return buf;
-}
-
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
- void *tlv_data, int tlv_data_size)
-{
- struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf);
- int new_tlv_space = TLV_SPACE(tlv_data_size);
-
- if (skb_tailroom(buf) < new_tlv_space)
- return 0;
- skb_put(buf, new_tlv_space);
- tlv->tlv_type = htons(tlv_type);
- tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size));
- if (tlv_data_size && tlv_data)
- memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
- return 1;
-}
-
-static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
-{
- struct sk_buff *buf;
- __be32 value_net;
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
- if (buf) {
- value_net = htonl(value);
- tipc_cfg_append_tlv(buf, tlv_type, &value_net,
- sizeof(value_net));
- }
- return buf;
-}
-
-static struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
-{
- return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
-}
-
-struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
-{
- struct sk_buff *buf;
- int string_len = strlen(string) + 1;
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
- if (buf)
- tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
- return buf;
-}
-
-static struct sk_buff *tipc_show_stats(void)
-{
- struct sk_buff *buf;
- struct tlv_desc *rep_tlv;
- char *pb;
- int pb_len;
- int str_len;
- u32 value;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- value = ntohl(*(u32 *)TLV_DATA(req_tlv_area));
- if (value != 0)
- return tipc_cfg_reply_error_string("unsupported argument");
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
- if (buf == NULL)
- return NULL;
-
- rep_tlv = (struct tlv_desc *)buf->data;
- pb = TLV_DATA(rep_tlv);
- pb_len = ULTRA_STRING_MAX_LEN;
-
- str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n");
- str_len += 1; /* for "\0" */
- skb_put(buf, TLV_SPACE(str_len));
- TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
- return buf;
-}
-
-static struct sk_buff *cfg_enable_bearer(void)
-{
- struct tipc_bearer_config *args;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
- if (tipc_enable_bearer(args->name,
- ntohl(args->disc_domain),
- ntohl(args->priority)))
- return tipc_cfg_reply_error_string("unable to enable bearer");
-
- return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *cfg_disable_bearer(void)
-{
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
- return tipc_cfg_reply_error_string("unable to disable bearer");
-
- return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *cfg_set_own_addr(void)
-{
- u32 addr;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
- if (addr == tipc_own_addr)
- return tipc_cfg_reply_none();
- if (!tipc_addr_node_valid(addr))
- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
- " (node address)");
- if (tipc_own_addr)
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (cannot change node address once assigned)");
- if (!tipc_net_start(addr))
- return tipc_cfg_reply_none();
-
- return tipc_cfg_reply_error_string("cannot change to network mode");
-}
-
-static struct sk_buff *cfg_set_max_ports(void)
-{
- u32 value;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
- if (value == tipc_max_ports)
- return tipc_cfg_reply_none();
- if (value < 127 || value > 65535)
- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
- " (max ports must be 127-65535)");
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (cannot change max ports while TIPC is active)");
-}
-
-static struct sk_buff *cfg_set_netid(void)
-{
- u32 value;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
- value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
- if (value == tipc_net_id)
- return tipc_cfg_reply_none();
- if (value < 1 || value > 9999)
- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
- " (network id must be 1-9999)");
- if (tipc_own_addr)
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (cannot change network id once TIPC has joined a network)");
- tipc_net_id = value;
- return tipc_cfg_reply_none();
-}
-
-struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
- int request_space, int reply_headroom)
-{
- struct sk_buff *rep_tlv_buf;
-
- rtnl_lock();
-
- /* Save request and reply details in a well-known location */
- req_tlv_area = request_area;
- req_tlv_space = request_space;
- rep_headroom = reply_headroom;
-
- /* Check command authorization */
- if (likely(in_own_node(orig_node))) {
- /* command is permitted */
- } else {
- rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (cannot be done remotely)");
- goto exit;
- }
-
- /* Call appropriate processing routine */
- switch (cmd) {
- case TIPC_CMD_NOOP:
- rep_tlv_buf = tipc_cfg_reply_none();
- break;
- case TIPC_CMD_GET_NODES:
- rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space);
- break;
- case TIPC_CMD_GET_LINKS:
- rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space);
- break;
- case TIPC_CMD_SHOW_LINK_STATS:
- rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space);
- break;
- case TIPC_CMD_RESET_LINK_STATS:
- rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space);
- break;
- case TIPC_CMD_SHOW_NAME_TABLE:
- rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space);
- break;
- case TIPC_CMD_GET_BEARER_NAMES:
- rep_tlv_buf = tipc_bearer_get_names();
- break;
- case TIPC_CMD_GET_MEDIA_NAMES:
- rep_tlv_buf = tipc_media_get_names();
- break;
- case TIPC_CMD_SHOW_PORTS:
- rep_tlv_buf = tipc_sk_socks_show();
- break;
- case TIPC_CMD_SHOW_STATS:
- rep_tlv_buf = tipc_show_stats();
- break;
- case TIPC_CMD_SET_LINK_TOL:
- case TIPC_CMD_SET_LINK_PRI:
- case TIPC_CMD_SET_LINK_WINDOW:
- rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd);
- break;
- case TIPC_CMD_ENABLE_BEARER:
- rep_tlv_buf = cfg_enable_bearer();
- break;
- case TIPC_CMD_DISABLE_BEARER:
- rep_tlv_buf = cfg_disable_bearer();
- break;
- case TIPC_CMD_SET_NODE_ADDR:
- rep_tlv_buf = cfg_set_own_addr();
- break;
- case TIPC_CMD_SET_MAX_PORTS:
- rep_tlv_buf = cfg_set_max_ports();
- break;
- case TIPC_CMD_SET_NETID:
- rep_tlv_buf = cfg_set_netid();
- break;
- case TIPC_CMD_GET_MAX_PORTS:
- rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
- break;
- case TIPC_CMD_GET_NETID:
- rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
- break;
- case TIPC_CMD_NOT_NET_ADMIN:
- rep_tlv_buf =
- tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
- break;
- case TIPC_CMD_SET_MAX_ZONES:
- case TIPC_CMD_GET_MAX_ZONES:
- case TIPC_CMD_SET_MAX_SLAVES:
- case TIPC_CMD_GET_MAX_SLAVES:
- case TIPC_CMD_SET_MAX_CLUSTERS:
- case TIPC_CMD_GET_MAX_CLUSTERS:
- case TIPC_CMD_SET_MAX_NODES:
- case TIPC_CMD_GET_MAX_NODES:
- case TIPC_CMD_SET_MAX_SUBSCR:
- case TIPC_CMD_GET_MAX_SUBSCR:
- case TIPC_CMD_SET_MAX_PUBL:
- case TIPC_CMD_GET_MAX_PUBL:
- case TIPC_CMD_SET_LOG_SIZE:
- case TIPC_CMD_SET_REMOTE_MNG:
- case TIPC_CMD_GET_REMOTE_MNG:
- case TIPC_CMD_DUMP_LOG:
- rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (obsolete command)");
- break;
- default:
- rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (unknown command)");
- break;
- }
-
- WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN));
-
- /* Append an error message if we cannot return all requested data */
- if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) {
- if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0')
- sprintf(rep_tlv_buf->data + rep_tlv_buf->len -
- sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);
- }
-
- /* Return reply buffer */
-exit:
- rtnl_unlock();
- return rep_tlv_buf;
-}
diff --git a/net/tipc/config.h b/net/tipc/config.h
deleted file mode 100644
index 47b1bf1..0000000
--- a/net/tipc/config.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * net/tipc/config.h: Include file for TIPC configuration service code
- *
- * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _TIPC_CONFIG_H
-#define _TIPC_CONFIG_H
-
-/* ---------------------------------------------------------------------- */
-
-#include "link.h"
-
-struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
- void *tlv_data, int tlv_data_size);
-struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
-
-static inline struct sk_buff *tipc_cfg_reply_none(void)
-{
- return tipc_cfg_reply_alloc(0);
-}
-
-static inline struct sk_buff *tipc_cfg_reply_error_string(char *string)
-{
- return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
-}
-
-static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string)
-{
- return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
-}
-
-struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
- const void *req_tlv_area, int req_tlv_space,
- int headroom);
-#endif
diff --git a/net/tipc/core.c b/net/tipc/core.c
index a5737b8..b78284b 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -37,8 +37,9 @@
#include "core.h"
#include "name_table.h"
#include "subscr.h"
-#include "config.h"
#include "socket.h"
+#include "net.h"
+#include "bearer.h"
#include <linux/module.h>
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2195197..2e8e184 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -40,7 +40,6 @@
#include "socket.h"
#include "name_distr.h"
#include "discover.h"
-#include "config.h"
#include "netlink.h"
#include <linux/pkt_sched.h>
@@ -2028,148 +2027,6 @@ static struct tipc_node *tipc_link_find_owner(const char *link_name,
}
/**
- * link_value_is_valid -- validate proposed link tolerance/priority/window
- *
- * @cmd: value type (TIPC_CMD_SET_LINK_*)
- * @new_value: the new value
- *
- * Returns 1 if value is within range, 0 if not.
- */
-static int link_value_is_valid(u16 cmd, u32 new_value)
-{
- switch (cmd) {
- case TIPC_CMD_SET_LINK_TOL:
- return (new_value >= TIPC_MIN_LINK_TOL) &&
- (new_value <= TIPC_MAX_LINK_TOL);
- case TIPC_CMD_SET_LINK_PRI:
- return (new_value <= TIPC_MAX_LINK_PRI);
- case TIPC_CMD_SET_LINK_WINDOW:
- return (new_value >= TIPC_MIN_LINK_WIN) &&
- (new_value <= TIPC_MAX_LINK_WIN);
- }
- return 0;
-}
-
-/**
- * link_cmd_set_value - change priority/tolerance/window for link/bearer/media
- * @name: ptr to link, bearer, or media name
- * @new_value: new value of link, bearer, or media setting
- * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*)
- *
- * Caller must hold RTNL lock to ensure link/bearer/media is not deleted.
- *
- * Returns 0 if value updated and negative value on error.
- */
-static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
-{
- struct tipc_node *node;
- struct tipc_link *l_ptr;
- struct tipc_bearer *b_ptr;
- struct tipc_media *m_ptr;
- int bearer_id;
- int res = 0;
-
- node = tipc_link_find_owner(name, &bearer_id);
- if (node) {
- tipc_node_lock(node);
- l_ptr = node->links[bearer_id];
-
- if (l_ptr) {
- switch (cmd) {
- case TIPC_CMD_SET_LINK_TOL:
- link_set_supervision_props(l_ptr, new_value);
- tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
- new_value, 0, 0);
- break;
- case TIPC_CMD_SET_LINK_PRI:
- l_ptr->priority = new_value;
- tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
- 0, new_value, 0);
- break;
- case TIPC_CMD_SET_LINK_WINDOW:
- tipc_link_set_queue_limits(l_ptr, new_value);
- break;
- default:
- res = -EINVAL;
- break;
- }
- }
- tipc_node_unlock(node);
- return res;
- }
-
- b_ptr = tipc_bearer_find(name);
- if (b_ptr) {
- switch (cmd) {
- case TIPC_CMD_SET_LINK_TOL:
- b_ptr->tolerance = new_value;
- break;
- case TIPC_CMD_SET_LINK_PRI:
- b_ptr->priority = new_value;
- break;
- case TIPC_CMD_SET_LINK_WINDOW:
- b_ptr->window = new_value;
- break;
- default:
- res = -EINVAL;
- break;
- }
- return res;
- }
-
- m_ptr = tipc_media_find(name);
- if (!m_ptr)
- return -ENODEV;
- switch (cmd) {
- case TIPC_CMD_SET_LINK_TOL:
- m_ptr->tolerance = new_value;
- break;
- case TIPC_CMD_SET_LINK_PRI:
- m_ptr->priority = new_value;
- break;
- case TIPC_CMD_SET_LINK_WINDOW:
- m_ptr->window = new_value;
- break;
- default:
- res = -EINVAL;
- break;
- }
- return res;
-}
-
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,
- u16 cmd)
-{
- struct tipc_link_config *args;
- u32 new_value;
- int res;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
- new_value = ntohl(args->value);
-
- if (!link_value_is_valid(cmd, new_value))
- return tipc_cfg_reply_error_string(
- "cannot change, value invalid");
-
- if (!strcmp(args->name, tipc_bclink_name)) {
- if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
- (tipc_bclink_set_queue_limits(new_value) == 0))
- return tipc_cfg_reply_none();
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (cannot change setting on broadcast link)");
- }
-
- res = link_cmd_set_value(args->name, new_value, cmd);
- if (res)
- return tipc_cfg_reply_error_string("cannot change link setting");
-
- return tipc_cfg_reply_none();
-}
-
-/**
* link_reset_statistics - reset link statistics
* @l_ptr: pointer to link
*/
@@ -2180,174 +2037,6 @@ static void link_reset_statistics(struct tipc_link *l_ptr)
l_ptr->stats.recv_info = l_ptr->next_in_no;
}
-struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
-{
- char *link_name;
- struct tipc_link *l_ptr;
- struct tipc_node *node;
- unsigned int bearer_id;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- link_name = (char *)TLV_DATA(req_tlv_area);
- if (!strcmp(link_name, tipc_bclink_name)) {
- if (tipc_bclink_reset_stats())
- return tipc_cfg_reply_error_string("link not found");
- return tipc_cfg_reply_none();
- }
- node = tipc_link_find_owner(link_name, &bearer_id);
- if (!node)
- return tipc_cfg_reply_error_string("link not found");
-
- tipc_node_lock(node);
- l_ptr = node->links[bearer_id];
- if (!l_ptr) {
- tipc_node_unlock(node);
- return tipc_cfg_reply_error_string("link not found");
- }
- link_reset_statistics(l_ptr);
- tipc_node_unlock(node);
- return tipc_cfg_reply_none();
-}
-
-/**
- * percent - convert count to a percentage of total (rounding up or down)
- */
-static u32 percent(u32 count, u32 total)
-{
- return (count * 100 + (total / 2)) / total;
-}
-
-/**
- * tipc_link_stats - print link statistics
- * @name: link name
- * @buf: print buffer area
- * @buf_size: size of print buffer area
- *
- * Returns length of print buffer data string (or 0 if error)
- */
-static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
-{
- struct tipc_link *l;
- struct tipc_stats *s;
- struct tipc_node *node;
- char *status;
- u32 profile_total = 0;
- unsigned int bearer_id;
- int ret;
-
- if (!strcmp(name, tipc_bclink_name))
- return tipc_bclink_stats(buf, buf_size);
-
- node = tipc_link_find_owner(name, &bearer_id);
- if (!node)
- return 0;
-
- tipc_node_lock(node);
-
- l = node->links[bearer_id];
- if (!l) {
- tipc_node_unlock(node);
- return 0;
- }
-
- s = &l->stats;
-
- if (tipc_link_is_active(l))
- status = "ACTIVE";
- else if (tipc_link_is_up(l))
- status = "STANDBY";
- else
- status = "DEFUNCT";
-
- ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
- " %s MTU:%u Priority:%u Tolerance:%u ms"
- " Window:%u packets\n",
- l->name, status, l->max_pkt, l->priority,
- l->tolerance, l->queue_limit[0]);
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
- l->next_in_no - s->recv_info, s->recv_fragments,
- s->recv_fragmented, s->recv_bundles,
- s->recv_bundled);
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
- l->next_out_no - s->sent_info, s->sent_fragments,
- s->sent_fragmented, s->sent_bundles,
- s->sent_bundled);
-
- profile_total = s->msg_length_counts;
- if (!profile_total)
- profile_total = 1;
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " TX profile sample:%u packets average:%u octets\n"
- " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
- "-16384:%u%% -32768:%u%% -66000:%u%%\n",
- s->msg_length_counts,
- s->msg_lengths_total / profile_total,
- percent(s->msg_length_profile[0], profile_total),
- percent(s->msg_length_profile[1], profile_total),
- percent(s->msg_length_profile[2], profile_total),
- percent(s->msg_length_profile[3], profile_total),
- percent(s->msg_length_profile[4], profile_total),
- percent(s->msg_length_profile[5], profile_total),
- percent(s->msg_length_profile[6], profile_total));
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " RX states:%u probes:%u naks:%u defs:%u"
- " dups:%u\n", s->recv_states, s->recv_probes,
- s->recv_nacks, s->deferred_recv, s->duplicates);
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " TX states:%u probes:%u naks:%u acks:%u"
- " dups:%u\n", s->sent_states, s->sent_probes,
- s->sent_nacks, s->sent_acks, s->retransmitted);
-
- ret += tipc_snprintf(buf + ret, buf_size - ret,
- " Congestion link:%u Send queue"
- " max:%u avg:%u\n", s->link_congs,
- s->max_queue_sz, s->queue_sz_counts ?
- (s->accu_queue_sz / s->queue_sz_counts) : 0);
-
- tipc_node_unlock(node);
- return ret;
-}
-
-struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
-{
- struct sk_buff *buf;
- struct tlv_desc *rep_tlv;
- int str_len;
- int pb_len;
- char *pb;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
- if (!buf)
- return NULL;
-
- rep_tlv = (struct tlv_desc *)buf->data;
- pb = TLV_DATA(rep_tlv);
- pb_len = ULTRA_STRING_MAX_LEN;
- str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
- pb, pb_len);
- if (!str_len) {
- kfree_skb(buf);
- return tipc_cfg_reply_error_string("link not found");
- }
- str_len += 1; /* for "\0" */
- skb_put(buf, TLV_SPACE(str_len));
- TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
- return buf;
-}
-
/**
* tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
* @dest: network address of destination node
diff --git a/net/tipc/link.h b/net/tipc/link.h
index f463e7b..20e9c93 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -217,13 +217,6 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr);
int tipc_link_is_up(struct tipc_link *l_ptr);
int tipc_link_is_active(struct tipc_link *l_ptr);
void tipc_link_purge_queues(struct tipc_link *l_ptr);
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area,
- int req_tlv_space,
- u16 cmd);
-struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
- int req_tlv_space);
-struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
- int req_tlv_space);
void tipc_link_reset_all(struct tipc_node *node);
void tipc_link_reset(struct tipc_link *l_ptr);
void tipc_link_reset_list(unsigned int bearer_id);
diff --git a/net/tipc/log.c b/net/tipc/log.c
index abef644..b186af0 100644
--- a/net/tipc/log.c
+++ b/net/tipc/log.c
@@ -35,7 +35,6 @@
*/
#include "core.h"
-#include "config.h"
/**
* tipc_snprintf - append formatted output to print buffer
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 7d69229..7b06a9d 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -35,9 +35,9 @@
*/
#include "core.h"
-#include "config.h"
#include "name_table.h"
#include "name_distr.h"
+#include "bcast.h"
#include "subscr.h"
#define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */
@@ -760,189 +760,6 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
write_unlock_bh(&tipc_nametbl_lock);
}
-
-/**
- * subseq_list - print specified sub-sequence contents into the given buffer
- */
-static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
- u32 index)
-{
- char portIdStr[27];
- const char *scope_str[] = {"", " zone", " cluster", " node"};
- struct publication *publ;
- struct name_info *info;
- int ret;
-
- ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper);
-
- if (depth == 2) {
- ret += tipc_snprintf(buf - ret, len + ret, "\n");
- return ret;
- }
-
- info = sseq->info;
-
- list_for_each_entry(publ, &info->zone_list, zone_list) {
- sprintf(portIdStr, "<%u.%u.%u:%u>",
- tipc_zone(publ->node), tipc_cluster(publ->node),
- tipc_node(publ->node), publ->ref);
- ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr);
- if (depth > 3) {
- ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s",
- publ->key, scope_str[publ->scope]);
- }
- if (!list_is_last(&publ->zone_list, &info->zone_list))
- ret += tipc_snprintf(buf + ret, len - ret,
- "\n%33s", " ");
- }
-
- ret += tipc_snprintf(buf + ret, len - ret, "\n");
- return ret;
-}
-
-/**
- * nameseq_list - print specified name sequence contents into the given buffer
- */
-static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
- u32 type, u32 lowbound, u32 upbound, u32 index)
-{
- struct sub_seq *sseq;
- char typearea[11];
- int ret = 0;
-
- if (seq->first_free == 0)
- return 0;
-
- sprintf(typearea, "%-10u", seq->type);
-
- if (depth == 1) {
- ret += tipc_snprintf(buf, len, "%s\n", typearea);
- return ret;
- }
-
- for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
- if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
- ret += tipc_snprintf(buf + ret, len - ret, "%s ",
- typearea);
- spin_lock_bh(&seq->lock);
- ret += subseq_list(sseq, buf + ret, len - ret,
- depth, index);
- spin_unlock_bh(&seq->lock);
- sprintf(typearea, "%10s", " ");
- }
- }
- return ret;
-}
-
-/**
- * nametbl_header - print name table header into the given buffer
- */
-static int nametbl_header(char *buf, int len, u32 depth)
-{
- const char *header[] = {
- "Type ",
- "Lower Upper ",
- "Port Identity ",
- "Publication Scope"
- };
-
- int i;
- int ret = 0;
-
- if (depth > 4)
- depth = 4;
- for (i = 0; i < depth; i++)
- ret += tipc_snprintf(buf + ret, len - ret, header[i]);
- ret += tipc_snprintf(buf + ret, len - ret, "\n");
- return ret;
-}
-
-/**
- * nametbl_list - print specified name table contents into the given buffer
- */
-static int nametbl_list(char *buf, int len, u32 depth_info,
- u32 type, u32 lowbound, u32 upbound)
-{
- struct hlist_head *seq_head;
- struct name_seq *seq;
- int all_types;
- int ret = 0;
- u32 depth;
- u32 i;
-
- all_types = (depth_info & TIPC_NTQ_ALLTYPES);
- depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
-
- if (depth == 0)
- return 0;
-
- if (all_types) {
- /* display all entries in name table to specified depth */
- ret += nametbl_header(buf, len, depth);
- lowbound = 0;
- upbound = ~0;
- for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
- seq_head = &table.types[i];
- hlist_for_each_entry(seq, seq_head, ns_list) {
- ret += nameseq_list(seq, buf + ret, len - ret,
- depth, seq->type,
- lowbound, upbound, i);
- }
- }
- } else {
- /* display only the sequence that matches the specified type */
- if (upbound < lowbound) {
- ret += tipc_snprintf(buf + ret, len - ret,
- "invalid name sequence specified\n");
- return ret;
- }
- ret += nametbl_header(buf + ret, len - ret, depth);
- i = hash(type);
- seq_head = &table.types[i];
- hlist_for_each_entry(seq, seq_head, ns_list) {
- if (seq->type == type) {
- ret += nameseq_list(seq, buf + ret, len - ret,
- depth, type,
- lowbound, upbound, i);
- break;
- }
- }
- }
- return ret;
-}
-
-struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
-{
- struct sk_buff *buf;
- struct tipc_name_table_query *argv;
- struct tlv_desc *rep_tlv;
- char *pb;
- int pb_len;
- int str_len;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
- if (!buf)
- return NULL;
-
- rep_tlv = (struct tlv_desc *)buf->data;
- pb = TLV_DATA(rep_tlv);
- pb_len = ULTRA_STRING_MAX_LEN;
- argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
- read_lock_bh(&tipc_nametbl_lock);
- str_len = nametbl_list(pb, pb_len, ntohl(argv->depth),
- ntohl(argv->type),
- ntohl(argv->lowbound), ntohl(argv->upbound));
- read_unlock_bh(&tipc_nametbl_lock);
- str_len += 1; /* for "\0" */
- skb_put(buf, TLV_SPACE(str_len));
- TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
- return buf;
-}
-
int tipc_nametbl_init(void)
{
table.types = kcalloc(TIPC_NAMETBL_SIZE, sizeof(struct hlist_head),
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index b38ebec..3ed7b64 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -38,6 +38,7 @@
#define _TIPC_NAME_TABLE_H
#include "node_subscr.h"
+#include <net/genetlink.h>
struct tipc_subscription;
struct tipc_port_list;
diff --git a/net/tipc/net.c b/net/tipc/net.c
index fdbbedf..2b7d7f3 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -40,7 +40,6 @@
#include "subscr.h"
#include "socket.h"
#include "node.h"
-#include "config.h"
static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
[TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC },
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 11a2fd8..608a935 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -35,7 +35,6 @@
*/
#include "core.h"
-#include "config.h"
#include "socket.h"
#include "name_table.h"
#include "bearer.h"
@@ -44,36 +43,6 @@
#include "net.h"
#include <net/genetlink.h>
-static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
-{
- struct sk_buff *rep_buf;
- struct nlmsghdr *rep_nlh;
- struct nlmsghdr *req_nlh = info->nlhdr;
- struct tipc_genlmsghdr *req_userhdr = info->userhdr;
- int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN);
- u16 cmd;
-
- if ((req_userhdr->cmd & 0xC000) && (!netlink_capable(skb, CAP_NET_ADMIN)))
- cmd = TIPC_CMD_NOT_NET_ADMIN;
- else
- cmd = req_userhdr->cmd;
-
- rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd,
- nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
- nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
- hdr_space);
-
- if (rep_buf) {
- skb_push(rep_buf, hdr_space);
- rep_nlh = nlmsg_hdr(rep_buf);
- memcpy(rep_nlh, req_nlh, hdr_space);
- rep_nlh->nlmsg_len = rep_buf->len;
- genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).portid);
- }
-
- return 0;
-}
-
static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
[TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, },
[TIPC_NLA_BEARER] = { .type = NLA_NESTED, },
@@ -95,11 +64,6 @@ struct genl_family tipc_genl_family = {
static const struct genl_ops tipc_genl_ops[] = {
{
- /* Legacy ASCII API */
- .cmd = TIPC_GENL_CMD,
- .doit = handle_cmd,
- },
- {
.cmd = TIPC_NL_BEARER_DISABLE,
.doit = tipc_nl_bearer_disable,
.policy = tipc_nl_policy,
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 80ca561..1a5ef71 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -35,8 +35,8 @@
*/
#include "core.h"
-#include "config.h"
#include "node.h"
+#include "link.h"
#include "name_distr.h"
#include "socket.h"
@@ -414,117 +414,6 @@ static void node_lost_contact(struct tipc_node *n_ptr)
TIPC_NOTIFY_NODE_DOWN;
}
-struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
-{
- u32 domain;
- struct sk_buff *buf;
- struct tipc_node *n_ptr;
- struct tipc_node_info node_info;
- u32 payload_size;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
- if (!tipc_addr_domain_valid(domain))
- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
- " (network address)");
-
- spin_lock_bh(&node_list_lock);
- if (!tipc_num_nodes) {
- spin_unlock_bh(&node_list_lock);
- return tipc_cfg_reply_none();
- }
-
- /* For now, get space for all other nodes */
- payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
- if (payload_size > 32768u) {
- spin_unlock_bh(&node_list_lock);
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (too many nodes)");
- }
- spin_unlock_bh(&node_list_lock);
-
- buf = tipc_cfg_reply_alloc(payload_size);
- if (!buf)
- return NULL;
-
- /* Add TLVs for all nodes in scope */
- rcu_read_lock();
- list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) {
- if (!tipc_in_scope(domain, n_ptr->addr))
- continue;
- node_info.addr = htonl(n_ptr->addr);
- node_info.up = htonl(tipc_node_is_up(n_ptr));
- tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
- &node_info, sizeof(node_info));
- }
- rcu_read_unlock();
- return buf;
-}
-
-struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
-{
- u32 domain;
- struct sk_buff *buf;
- struct tipc_node *n_ptr;
- struct tipc_link_info link_info;
- u32 payload_size;
-
- if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
- return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
- domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
- if (!tipc_addr_domain_valid(domain))
- return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
- " (network address)");
-
- if (!tipc_own_addr)
- return tipc_cfg_reply_none();
-
- spin_lock_bh(&node_list_lock);
- /* Get space for all unicast links + broadcast link */
- payload_size = TLV_SPACE((sizeof(link_info)) * (tipc_num_links + 1));
- if (payload_size > 32768u) {
- spin_unlock_bh(&node_list_lock);
- return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
- " (too many links)");
- }
- spin_unlock_bh(&node_list_lock);
-
- buf = tipc_cfg_reply_alloc(payload_size);
- if (!buf)
- return NULL;
-
- /* Add TLV for broadcast link */
- link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
- link_info.up = htonl(1);
- strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
- tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
-
- /* Add TLVs for any other links in scope */
- rcu_read_lock();
- list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) {
- u32 i;
-
- if (!tipc_in_scope(domain, n_ptr->addr))
- continue;
- tipc_node_lock(n_ptr);
- for (i = 0; i < MAX_BEARERS; i++) {
- if (!n_ptr->links[i])
- continue;
- link_info.dest = htonl(n_ptr->addr);
- link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
- strcpy(link_info.str, n_ptr->links[i]->name);
- tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
- &link_info, sizeof(link_info));
- }
- tipc_node_unlock(n_ptr);
- }
- rcu_read_unlock();
- return buf;
-}
-
/**
* tipc_node_get_linkname - get the name of a link
*
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 17c0921..a8849d7 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -132,8 +132,6 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
int tipc_node_active_links(struct tipc_node *n_ptr);
int tipc_node_is_up(struct tipc_node *n_ptr);
-struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len);
void tipc_node_unlock(struct tipc_node *node);
int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index bb58029..4cf2260 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -39,7 +39,6 @@
#include "node.h"
#include "link.h"
#include <linux/export.h>
-#include "config.h"
#include "socket.h"
#define SS_LISTENING -1 /* socket is listening */
@@ -2203,82 +2202,6 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
return rc;
}
-static int tipc_sk_show(struct tipc_sock *tsk, char *buf,
- int len, int full_id)
-{
- struct publication *publ;
- int ret;
-
- if (full_id)
- ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
- tipc_zone(tipc_own_addr),
- tipc_cluster(tipc_own_addr),
- tipc_node(tipc_own_addr), tsk->ref);
- else
- ret = tipc_snprintf(buf, len, "%-10u:", tsk->ref);
-
- if (tsk->connected) {
- u32 dport = tsk_peer_port(tsk);
- u32 destnode = tsk_peer_node(tsk);
-
- ret += tipc_snprintf(buf + ret, len - ret,
- " connected to <%u.%u.%u:%u>",
- tipc_zone(destnode),
- tipc_cluster(destnode),
- tipc_node(destnode), dport);
- if (tsk->conn_type != 0)
- ret += tipc_snprintf(buf + ret, len - ret,
- " via {%u,%u}", tsk->conn_type,
- tsk->conn_instance);
- } else if (tsk->published) {
- ret += tipc_snprintf(buf + ret, len - ret, " bound to");
- list_for_each_entry(publ, &tsk->publications, pport_list) {
- if (publ->lower == publ->upper)
- ret += tipc_snprintf(buf + ret, len - ret,
- " {%u,%u}", publ->type,
- publ->lower);
- else
- ret += tipc_snprintf(buf + ret, len - ret,
- " {%u,%u,%u}", publ->type,
- publ->lower, publ->upper);
- }
- }
- ret += tipc_snprintf(buf + ret, len - ret, "\n");
- return ret;
-}
-
-struct sk_buff *tipc_sk_socks_show(void)
-{
- struct sk_buff *buf;
- struct tlv_desc *rep_tlv;
- char *pb;
- int pb_len;
- struct tipc_sock *tsk;
- int str_len = 0;
- u32 ref = 0;
-
- buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
- if (!buf)
- return NULL;
- rep_tlv = (struct tlv_desc *)buf->data;
- pb = TLV_DATA(rep_tlv);
- pb_len = ULTRA_STRING_MAX_LEN;
-
- tsk = tipc_sk_get_next(&ref);
- for (; tsk; tsk = tipc_sk_get_next(&ref)) {
- lock_sock(&tsk->sk);
- str_len += tipc_sk_show(tsk, pb + str_len,
- pb_len - str_len, 0);
- release_sock(&tsk->sk);
- tipc_sk_put(tsk);
- }
- str_len += 1; /* for "\0" */
- skb_put(buf, TLV_SPACE(str_len));
- TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
- return buf;
-}
-
/* tipc_sk_reinit: set non-zero address in all existing sockets
* when we go from standalone to network mode.
*/
diff --git a/net/tipc/socket.h b/net/tipc/socket.h
index 16dfd62..e7cdb40 100644
--- a/net/tipc/socket.h
+++ b/net/tipc/socket.h
@@ -43,7 +43,6 @@
#define TIPC_CONN_OVERLOAD_LIMIT ((TIPC_FLOWCTRL_WIN * 2 + 1) * \
SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
int tipc_sk_rcv(struct sk_buff *buf);
-struct sk_buff *tipc_sk_socks_show(void);
void tipc_sk_mcast_rcv(struct sk_buff *buf);
void tipc_sk_reinit(void);
int tipc_sk_ref_table_init(u32 requested_size, u32 start);
--
1.7.10.4
------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
^ permalink raw reply related
* Re: [PATCH net-next] ipv6: implement rt_genid_bump_ipv6 with fn_sernum and remove rt6i_genid
From: Hannes Frederic Sowa @ 2014-09-11 8:30 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eric.dumazet, nicolas.dichtel
In-Reply-To: <20140910.130929.247064282043941043.davem@davemloft.net>
On Mi, 2014-09-10 at 13:09 -0700, David Miller wrote:
> From: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Date: Wed, 10 Sep 2014 11:31:28 +0200
>
> > In case we need to force the sockets to relookup the routes we now
> > increase the fn_sernum on all fibnodes in the routing tree. This is a
> > costly operation but should only happen if we have major routing/policy
> > changes in the kernel (e.g. manual route adding/removal, xfrm policy
> > changes).
>
> Core routers can update thousands of route updates per second, and they
> do this via what you refer to as "manual route adding/removal".
Sorry, I was too unspecific here. Route changes because of address
removal/addition on the local stack.
The reason why we do the bump_id here is that we want to flush all the
socket caches in case we have either lost or gained access to a new
source address.
If you think about e.g. BGP routers which update lots of routes, they
aren't affected and the flush won't happen on every route change.
> I don't think we want to put such a scalability problem into the tree.
>
> There has to be a lightweight way to address this.
I am still investigating why this bump_id actually happened. Seems the
reason is only sctp ontop of IPv6 and maybe we can build something much
more lightweight, yes.
Thanks,
Hannes
^ permalink raw reply
* [PATCH v2 0/4] net: stmmac: Enable Intel Quark SoC X1000 Ethernet support
From: Kweh Hock Leong @ 2014-09-11 8:38 UTC (permalink / raw)
To: David S. Miller, Giuseppe Cavallaro, rayagond
Cc: Vince Bridgers, Srinivas Kandagatla, Chen-Yu Tsai, netdev, LKML,
Ong Boon Leong, Kweh Hock Leong
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
Hi,
Intel Quark X1000 SoC has 2 Ethernet controllers integrated on chip and they are
PCI devices. We adopted the stmmac_pci driver and added on code to support Intel
Quark SoC X1000 by creating the patchset below. The patchset has been built and
tested on Galileo board and found to be working as expected.
We believe that the changes are transparent to other non Intel Quark platform.
Please help to review the code change and feedback if there is any concern.
Thank you very much.
---
changelog v2:
[PATCH 1/4]
* fix indentation to align with the 1st column of openning parenthesis
* replace the static variable instance_id by using pci bus & devfn number
[PATCH 2/4]
* replace the static variable instance_id by using pci bus & devfn number
[PATCH 3/4]
* replace the static variable instance_id by using pci bus & devfn number
Kweh, Hock Leong (4):
net: stmmac: enhance to support multiple device instances
net: stmmac: better code manageability with platform data struct
net: stmmac: add support for Intel Quark X1000
net: stmmac: add MSI support for Intel Quark X1000
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 194 +++++++++++++++++++---
1 file changed, 171 insertions(+), 23 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v2 1/4] net: stmmac: enhance to support multiple device instances
From: Kweh Hock Leong @ 2014-09-11 8:38 UTC (permalink / raw)
To: David S. Miller, Giuseppe Cavallaro, rayagond
Cc: Vince Bridgers, Srinivas Kandagatla, Chen-Yu Tsai, netdev, LKML,
Ong Boon Leong, Kweh Hock Leong
In-Reply-To: <cover.1410416223.git.hock.leong.kweh@intel.com>
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
The original stmmac_pci code only supports single ethernet controller
instance. This modification allows the driver to support multiple
stmicro ethernet controller instances by converting the static global
variables plat_dat, mdio_data & dma_cfg to dynamic allocation.
This piece of work is derived from Bryan O'Donoghue's initial work for
Quark X1000 enabling.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Ong, Boon Leong <boon.leong.ong@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 61 ++++++++++++++--------
1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 655a23b..4d9a5c2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -26,27 +26,21 @@
#include <linux/pci.h>
#include "stmmac.h"
-static struct plat_stmmacenet_data plat_dat;
-static struct stmmac_mdio_bus_data mdio_data;
-static struct stmmac_dma_cfg dma_cfg;
-
-static void stmmac_default_data(void)
+static void stmmac_default_data(struct plat_stmmacenet_data *plat_dat,
+ struct pci_dev *pdev)
{
- memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
- plat_dat.bus_id = 1;
- plat_dat.phy_addr = 0;
- plat_dat.interface = PHY_INTERFACE_MODE_GMII;
- plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
- plat_dat.has_gmac = 1;
- plat_dat.force_sf_dma_mode = 1;
-
- mdio_data.phy_reset = NULL;
- mdio_data.phy_mask = 0;
- plat_dat.mdio_bus_data = &mdio_data;
-
- dma_cfg.pbl = 32;
- dma_cfg.burst_len = DMA_AXI_BLEN_256;
- plat_dat.dma_cfg = &dma_cfg;
+ plat_dat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ plat_dat->phy_addr = 0;
+ plat_dat->interface = PHY_INTERFACE_MODE_GMII;
+ plat_dat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+ plat_dat->has_gmac = 1;
+ plat_dat->force_sf_dma_mode = 1;
+
+ plat_dat->mdio_bus_data->phy_reset = NULL;
+ plat_dat->mdio_bus_data->phy_mask = 0;
+
+ plat_dat->dma_cfg->pbl = 32;
+ plat_dat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
}
/**
@@ -67,6 +61,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
int ret = 0;
void __iomem *addr = NULL;
struct stmmac_priv *priv = NULL;
+ struct plat_stmmacenet_data *plat_dat;
int i;
/* Enable pci device */
@@ -97,9 +92,31 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
}
pci_set_master(pdev);
- stmmac_default_data();
+ plat_dat = devm_kzalloc(&pdev->dev, sizeof(*plat_dat), GFP_KERNEL);
+ if (!plat_dat) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ plat_dat->mdio_bus_data = devm_kzalloc(&pdev->dev,
+ sizeof(*plat_dat->mdio_bus_data),
+ GFP_KERNEL);
+ if (!plat_dat->mdio_bus_data) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ plat_dat->dma_cfg = devm_kzalloc(&pdev->dev,
+ sizeof(*plat_dat->dma_cfg),
+ GFP_KERNEL);
+ if (!plat_dat->dma_cfg) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ stmmac_default_data(plat_dat, pdev);
- priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
+ priv = stmmac_dvr_probe(&pdev->dev, plat_dat, addr);
if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
ret = PTR_ERR(priv);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 2/4] net: stmmac: better code manageability with platform data struct
From: Kweh Hock Leong @ 2014-09-11 8:38 UTC (permalink / raw)
To: David S. Miller, Giuseppe Cavallaro, rayagond
Cc: Vince Bridgers, Srinivas Kandagatla, Chen-Yu Tsai, netdev, LKML,
Ong Boon Leong, Kweh Hock Leong
In-Reply-To: <cover.1410416223.git.hock.leong.kweh@intel.com>
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
Introduce additional struct to hold platform info for pci device. It
is used to store features that are supported by specific chip vendor.
This code change helps to expand further to support more platform
vendors and this implementation promotes better code manageability
and keep code base clean. In addition, this patch adds mcast & ucast
filter configuration in pci driver.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Ong, Boon Leong <boon.leong.ong@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 77 +++++++++++++++++-----
1 file changed, 60 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 4d9a5c2..35fc884 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -26,21 +26,63 @@
#include <linux/pci.h>
#include "stmmac.h"
-static void stmmac_default_data(struct plat_stmmacenet_data *plat_dat,
- struct pci_dev *pdev)
+enum chip {
+ CHIP_STMICRO = 0,
+};
+
+/* A struct for platform specific information which will be
+ * used in stmmac_default_data function for initialization
+ */
+struct platform_data {
+ int phy_addr;
+ int interface;
+ int clk_csr;
+ int has_gmac;
+ int force_sf_dma_mode;
+ int multicast_filter_bins;
+ int unicast_filter_entries;
+ int (*phy_reset)(void *priv);
+ unsigned int phy_mask;
+ int pbl;
+ int burst_len;
+};
+
+static struct platform_data platform_info[] = {
+ [CHIP_STMICRO] = {
+ .phy_addr = 0,
+ .interface = PHY_INTERFACE_MODE_GMII,
+ .clk_csr = 2,
+ .has_gmac = 1,
+ .force_sf_dma_mode = 1,
+ .multicast_filter_bins = HASH_TABLE_SIZE,
+ .unicast_filter_entries = 1,
+ .phy_reset = NULL,
+ .phy_mask = 0,
+ .pbl = 32,
+ .burst_len = DMA_AXI_BLEN_256,
+ },
+};
+
+static void stmmac_default_data(struct plat_stmmacenet_data *plat,
+ int chip_id, struct pci_dev *pdev)
{
- plat_dat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
- plat_dat->phy_addr = 0;
- plat_dat->interface = PHY_INTERFACE_MODE_GMII;
- plat_dat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
- plat_dat->has_gmac = 1;
- plat_dat->force_sf_dma_mode = 1;
-
- plat_dat->mdio_bus_data->phy_reset = NULL;
- plat_dat->mdio_bus_data->phy_mask = 0;
-
- plat_dat->dma_cfg->pbl = 32;
- plat_dat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
+ struct platform_data *chip_plat_dat = &platform_info[chip_id];
+
+ plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ plat->phy_addr = chip_plat_dat->phy_addr;
+ plat->interface = chip_plat_dat->interface;
+ /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+ plat->clk_csr = chip_plat_dat->clk_csr;
+ plat->has_gmac = chip_plat_dat->has_gmac;
+ plat->force_sf_dma_mode = chip_plat_dat->force_sf_dma_mode;
+ plat->multicast_filter_bins = chip_plat_dat->multicast_filter_bins;
+ plat->unicast_filter_entries = chip_plat_dat->unicast_filter_entries;
+
+ plat->mdio_bus_data->phy_reset = chip_plat_dat->phy_reset;
+ plat->mdio_bus_data->phy_mask = chip_plat_dat->phy_mask;
+
+ plat->dma_cfg->pbl = chip_plat_dat->pbl;
+ plat->dma_cfg->burst_len = chip_plat_dat->burst_len;
}
/**
@@ -114,7 +156,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
goto err_out;
}
- stmmac_default_data(plat_dat, pdev);
+ stmmac_default_data(plat_dat, id->driver_data, pdev);
priv = stmmac_dvr_probe(&pdev->dev, plat_dat, addr);
if (IS_ERR(priv)) {
@@ -188,8 +230,9 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
#define STMMAC_DEVICE_ID 0x1108
static const struct pci_device_id stmmac_id_table[] = {
- {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+ {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID), PCI_ANY_ID,
+ PCI_ANY_ID, CHIP_STMICRO},
+ {PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC), CHIP_STMICRO},
{}
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 3/4] net: stmmac: add support for Intel Quark X1000
From: Kweh Hock Leong @ 2014-09-11 8:38 UTC (permalink / raw)
To: David S. Miller, Giuseppe Cavallaro, rayagond
Cc: Vince Bridgers, Srinivas Kandagatla, Chen-Yu Tsai, netdev, LKML,
Ong Boon Leong, Kweh Hock Leong
In-Reply-To: <cover.1410416223.git.hock.leong.kweh@intel.com>
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
The Intel Quark SoC X1000 provides two 10/100 Mbps Ethernet MAC
controllers which may or may not be connected to PHY on board.
This MAC controller only supports RMII PHY.
Besides adding Quark PCI ID to this driver, this patch introduces
run-time board detection through DMI and MAC-PHY configuration
function used by stmmac_default_data() during initialization.
It fills up the phy_address to -1 for Galileo and Galileo Gen2
boards to indicate that the 2nd Ethernet MAC controller is not
connected to any PHY.
The implementation takes into consideration for future expansion in
Quark series boards that may have different PHY address that is
linked to its MAC controllers.
This piece of work is derived from Bryan O'Donoghue's initial work for
Quark X1000 enabling.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Ong, Boon Leong <boon.leong.ong@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 87 ++++++++++++++++++++--
1 file changed, 82 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 35fc884..4fae23f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -24,14 +24,18 @@
*******************************************************************************/
#include <linux/pci.h>
+#include <linux/dmi.h>
#include "stmmac.h"
+static void quark_run_time_config(int chip_id, struct pci_dev *pdev);
+
enum chip {
CHIP_STMICRO = 0,
+ CHIP_QUARK_X1000,
};
-/* A struct for platform specific information which will be
- * used in stmmac_default_data function for initialization
+/* A struct for platform specific information which is used
+ * in stmmac_default_data function for initialization
*/
struct platform_data {
int phy_addr;
@@ -44,7 +48,9 @@ struct platform_data {
int (*phy_reset)(void *priv);
unsigned int phy_mask;
int pbl;
+ int fixed_burst;
int burst_len;
+ void (*rt_config)(int chip_id, struct pci_dev *pdev);
};
static struct platform_data platform_info[] = {
@@ -59,15 +65,76 @@ static struct platform_data platform_info[] = {
.phy_reset = NULL,
.phy_mask = 0,
.pbl = 32,
+ .fixed_burst = 0,
.burst_len = DMA_AXI_BLEN_256,
+ .rt_config = NULL,
+ },
+ [CHIP_QUARK_X1000] = {
+ .phy_addr = 1,
+ .interface = PHY_INTERFACE_MODE_RMII,
+ .clk_csr = 2,
+ .has_gmac = 1,
+ .force_sf_dma_mode = 1,
+ .multicast_filter_bins = HASH_TABLE_SIZE,
+ .unicast_filter_entries = 1,
+ .phy_reset = NULL,
+ .phy_mask = 0,
+ .pbl = 16,
+ .fixed_burst = 1,
+ .burst_len = DMA_AXI_BLEN_256,
+ .rt_config = &quark_run_time_config,
+ },
+};
+
+/* This struct is used to associate PCI Function ID of MAC controller
+ * on a board, discovered via DMI, with phy_address. It is also used
+ * to describe if that MAC controller is connected with PHY.
+ */
+struct intel_quark_platform {
+ int pci_func_num;
+ const char *board_name;
+ int phy_address;
+};
+
+static struct intel_quark_platform quark_x1000_phy_info[] = {
+ {
+ .pci_func_num = 7,
+ .board_name = "Galileo",
+ /* Galileo ethernet port 2 does not connect to any PHY */
+ .phy_address = -1,
+ },
+ {
+ .pci_func_num = 7,
+ .board_name = "GalileoGen2",
+ /* Galileo Gen2 ethernet port 2 does not connect to any PHY */
+ .phy_address = -1,
},
};
-static void stmmac_default_data(struct plat_stmmacenet_data *plat,
- int chip_id, struct pci_dev *pdev)
+static void quark_run_time_config(int chip_id, struct pci_dev *pdev)
+{
+ const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ int i;
+ int func_num = PCI_FUNC(pdev->devfn);
+
+ if (!board_name)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(quark_x1000_phy_info); i++) {
+ if ((!strcmp(quark_x1000_phy_info[i].board_name, board_name)) &&
+ quark_x1000_phy_info[i].pci_func_num == func_num)
+ platform_info[chip_id].phy_addr =
+ quark_x1000_phy_info[i].phy_address;
+ }
+}
+
+static int stmmac_default_data(struct plat_stmmacenet_data *plat,
+ int chip_id, struct pci_dev *pdev)
{
struct platform_data *chip_plat_dat = &platform_info[chip_id];
+ if (chip_plat_dat->rt_config)
+ chip_plat_dat->rt_config(chip_id, pdev);
plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
plat->phy_addr = chip_plat_dat->phy_addr;
plat->interface = chip_plat_dat->interface;
@@ -82,7 +149,13 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat,
plat->mdio_bus_data->phy_mask = chip_plat_dat->phy_mask;
plat->dma_cfg->pbl = chip_plat_dat->pbl;
+ plat->dma_cfg->fixed_burst = chip_plat_dat->fixed_burst;
plat->dma_cfg->burst_len = chip_plat_dat->burst_len;
+
+ /* Refuse to load the driver and register net device
+ * if MAC controller does not connect to any PHY interface
+ */
+ return (plat->phy_addr != -1) ? 0 : -ENODEV;
}
/**
@@ -156,7 +229,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
goto err_out;
}
- stmmac_default_data(plat_dat, id->driver_data, pdev);
+ ret = stmmac_default_data(plat_dat, id->driver_data, pdev);
+ if (ret)
+ goto err_out;
priv = stmmac_dvr_probe(&pdev->dev, plat_dat, addr);
if (IS_ERR(priv)) {
@@ -228,11 +303,13 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
#define STMMAC_VENDOR_ID 0x700
#define STMMAC_DEVICE_ID 0x1108
+#define STMMAC_QUARK_X1000_ID 0x0937
static const struct pci_device_id stmmac_id_table[] = {
{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID), PCI_ANY_ID,
PCI_ANY_ID, CHIP_STMICRO},
{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC), CHIP_STMICRO},
+ {PCI_VDEVICE(INTEL, STMMAC_QUARK_X1000_ID), CHIP_QUARK_X1000},
{}
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 4/4] net: stmmac: add MSI support for Intel Quark X1000
From: Kweh Hock Leong @ 2014-09-11 8:38 UTC (permalink / raw)
To: David S. Miller, Giuseppe Cavallaro, rayagond
Cc: Vince Bridgers, Srinivas Kandagatla, Chen-Yu Tsai, netdev, LKML,
Ong Boon Leong, Kweh Hock Leong
In-Reply-To: <cover.1410416223.git.hock.leong.kweh@intel.com>
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
In Intel Quark SoC X1000, both of the Ethernet controllers support
MSI interrupt handling. This patch enables them to use MSI interrupt
servicing in stmmac_pci for Intel Quark X1000.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
Reviewed-by: Ong, Boon Leong <boon.leong.ong@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 4fae23f..02861c3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -51,6 +51,7 @@ struct platform_data {
int fixed_burst;
int burst_len;
void (*rt_config)(int chip_id, struct pci_dev *pdev);
+ int support_msi;
};
static struct platform_data platform_info[] = {
@@ -68,6 +69,7 @@ static struct platform_data platform_info[] = {
.fixed_burst = 0,
.burst_len = DMA_AXI_BLEN_256,
.rt_config = NULL,
+ .support_msi = 0,
},
[CHIP_QUARK_X1000] = {
.phy_addr = 1,
@@ -83,6 +85,7 @@ static struct platform_data platform_info[] = {
.fixed_burst = 1,
.burst_len = DMA_AXI_BLEN_256,
.rt_config = &quark_run_time_config,
+ .support_msi = 1,
},
};
@@ -210,7 +213,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
plat_dat = devm_kzalloc(&pdev->dev, sizeof(*plat_dat), GFP_KERNEL);
if (!plat_dat) {
ret = -ENOMEM;
- goto err_out;
+ goto err_out_alloc_failed;
}
plat_dat->mdio_bus_data = devm_kzalloc(&pdev->dev,
@@ -218,7 +221,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
GFP_KERNEL);
if (!plat_dat->mdio_bus_data) {
ret = -ENOMEM;
- goto err_out;
+ goto err_out_alloc_failed;
}
plat_dat->dma_cfg = devm_kzalloc(&pdev->dev,
@@ -226,12 +229,15 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
GFP_KERNEL);
if (!plat_dat->dma_cfg) {
ret = -ENOMEM;
- goto err_out;
+ goto err_out_alloc_failed;
}
ret = stmmac_default_data(plat_dat, id->driver_data, pdev);
if (ret)
- goto err_out;
+ goto err_out_alloc_failed;
+
+ if (platform_info[id->driver_data].support_msi)
+ pci_enable_msi(pdev);
priv = stmmac_dvr_probe(&pdev->dev, plat_dat, addr);
if (IS_ERR(priv)) {
@@ -249,6 +255,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
return 0;
err_out:
+ if (platform_info[id->driver_data].support_msi)
+ pci_disable_msi(pdev);
+err_out_alloc_failed:
pci_clear_master(pdev);
err_out_map_failed:
pci_release_regions(pdev);
@@ -272,6 +281,8 @@ static void stmmac_pci_remove(struct pci_dev *pdev)
stmmac_dvr_remove(ndev);
+ if (pci_dev_msi_enabled(pdev))
+ pci_disable_msi(pdev);
pci_iounmap(pdev, priv->ioaddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
--
1.7.9.5
^ permalink raw reply related
* Blogpost: Explaining why I do PPS measurement with 64 bytes
From: Jesper Dangaard Brouer @ 2014-09-11 9:18 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: brouer
People generally seem to have a hardtime understanding why I'm using
64byte packets and measuring PPS, when tuning the network stack.
People keep telling me this is artificial benchmarking, which is true,
but there is another reason behind these measurements.
Which I have described in this blogpost:
http://netoptimizer.blogspot.dk/2014/09/packet-per-sec-measurements-for.html
I'm basically leveraging the PPS measurements to deduct the nanosec
improvements I'm making to the code.
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH net-next 2/2] mac80211: Resolve sk_refcnt/sk_wmem_alloc issue in wifi ack path
From: Arend van Spriel @ 2014-09-11 9:38 UTC (permalink / raw)
To: Johannes Berg
Cc: Alexander Duyck, netdev, linux-wireless, davem, eric.dumazet,
linville
In-Reply-To: <1410419198.1825.5.camel@jlt4.sipsolutions.net>
On 09/11/14 09:06, Johannes Berg wrote:
> On Wed, 2014-09-10 at 18:05 -0400, Alexander Duyck wrote:
>> There is a possible issue with the use, or lack thereof of sk_refcnt and
>> sk_wmem_alloc in the wifi ack status functionality.
>>
>> Specifically if a socket were to request acknowledgements, and the socket
>> were to have sk_refcnt drop to 0 resulting in it waiting on sk_wmem_alloc
>> to reach 0 it would be possible to have sock_queue_err_skb orphan the last
>> buffer, resulting in __sk_free being called on the socket. After this the
>> buffer is enqueued on sk_error_queue, however the queue has already been
>> flushed resulting in at least a memory leak, if not a data corruption.
>
> Oh. Thanks :-)
Hi Alexander,
So why is this only an issue in wifi ack path. The sock_queue_err_skb()
does not mention the caller should hold a sock reference. This seems
entirely an issue of the sock_queue_err_skb() function itself so why not
do sk_hold/sk_put within that function. Does it impose too much overhead?
Regards,
Arend
^ permalink raw reply
* Re: [PATCH net-next v3 2/2] bonding: Simplify the xmit function for modes that use xmit_hash
From: Nikolay Aleksandrov @ 2014-09-11 9:39 UTC (permalink / raw)
To: Mahesh Bandewar, Jay Vosburgh, Veaceslav Falico, Andy Gospodarek,
David Miller
Cc: netdev, Eric Dumazet, Maciej Zenczykowski
In-Reply-To: <1410409003-5530-1-git-send-email-maheshb@google.com>
On 11/09/14 06:16, Mahesh Bandewar wrote:
> Earlier change to use usable slave array for TLB mode had an additional
> performance advantage. So extending the same logic to all other modes
> that use xmit-hash for slave selection (viz 802.3AD, and XOR modes).
> Also consolidating this with the earlier TLB change.
>
> The main idea is to build the usable slaves array in the control path
> and use that array for slave selection during xmit operation.
>
> Measured performance in a setup with a bond of 4x1G NICs with 200
> instances of netperf for the modes involved (3ad, xor, tlb)
> cmd: netperf -t TCP_RR -H <TargetHost> -l 60 -s 5
>
> Mode TPS-Before TPS-After
>
> 802.3ad : 468,694 493,101
> TLB (lb=0): 392,583 392,965
> XOR : 475,696 484,517
>
> Signed-off-by: Mahesh Bandewar <maheshb@google.com>
> ---
> v1:
> (a) If bond_update_slave_arr() fails to allocate memory, it will overwrite
> the slave that need to be removed.
> (b) Freeing of array will assign NULL (to handle bond->down to bond->up
> transition gracefully.
> (c) Change from pr_debug() to pr_err() if bond_update_slave_arr() returns
> failure.
> (d) XOR: bond_update_slave_arr() will consider mii-mon, arp-mon cases and
> will populate the array even if these parameters are not used.
> (e) 3AD: Should handle the ad_agg_selection_logic correctly.
> v2:
> (a) Removed rcu_read_{un}lock() calls from array manipulation code.
> (b) Slave link-events now refresh array for all these modes.
> (c) Moved free-array call from bond_close() to bond_uninit().
> v3:
> (a) Fixed null pointer dereference.
> (b) Removed bond->lock lockdep dependency.
>
Hello Mahesh,
You should've given me time to respond, the reason I wrote this:
"First a question, if a bond device in XOR mode is up and we enslave a single
slave how would it start transmitting ? Same question, if we are enslaving a
second device then the array will be rebuild with only the first upon
NETDEV_UP
(of course all this is in the case miimon is 0).
The NETDEV_UP upon enslave happens before the slave is linked in."
was not because I wanted you to remove the slave rebuilding from the
NETDEV_UP/DOWN events, but because I didn't see how would a slave start
transmitting in XOR mode after enslaving, and I just tested it - it doesn't
since the slave array never gets rebuilt. The NETDEV_UP event is carried by the
dev_open() done in bond_enslave() earlier so the bond_set_carrier() in the end
isn't of much importance in most cases, simply do the following and you'll see:
modprobe bonding mode=2
ip set bond0 up
ifenslave bond0 eth0
Try to transmit anything and watch on the other side, you won't be able to see
anything as there's no slave array. My second question was given all this, if
you enslave any subsequent slaves, will it start transmitting ? But I just
tested this scenario and it still doesn't as the array doesn't get built.
A few suggestions below, nothing serious though.
> drivers/net/bonding/bond_3ad.c | 76 +++-----------------
> drivers/net/bonding/bond_alb.c | 51 ++------------
> drivers/net/bonding/bond_alb.h | 8 ---
> drivers/net/bonding/bond_main.c | 152 ++++++++++++++++++++++++++++++++++++----
> drivers/net/bonding/bonding.h | 8 +++
> 5 files changed, 164 insertions(+), 131 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
> index 5d27a6207384..516075f0a740 100644
> --- a/drivers/net/bonding/bond_3ad.c
> +++ b/drivers/net/bonding/bond_3ad.c
> @@ -1579,6 +1579,8 @@ static void ad_agg_selection_logic(struct aggregator *agg)
> __disable_port(port);
> }
> }
> + if (bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for 3ad mode.\n");
> }
>
> /* if the selected aggregator is of join individuals
> @@ -1717,6 +1719,8 @@ static void ad_enable_collecting_distributing(struct port *port)
> port->actor_port_number,
> port->aggregator->aggregator_identifier);
> __enable_port(port);
> + if (bond_update_slave_arr(port->slave->bond, NULL))
> + pr_err("Failed to build slave-array for 3ad mode.\n");
> }
> }
>
> @@ -1733,6 +1737,8 @@ static void ad_disable_collecting_distributing(struct port *port)
> port->actor_port_number,
> port->aggregator->aggregator_identifier);
> __disable_port(port);
> + if (bond_update_slave_arr(port->slave->bond, NULL))
> + pr_err("Failed to build slave-array for 3ad mode.\n");
> }
> }
>
> @@ -2311,6 +2317,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
> */
> port->sm_vars |= AD_PORT_BEGIN;
>
> + if (bond_update_slave_arr(slave->bond, NULL))
> + pr_err("Failed to build slave-array for 3ad mode.\n");
> +
> __release_state_machine_lock(port);
> }
>
> @@ -2406,73 +2415,6 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
> return ret;
> }
>
> -int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
> -{
> - struct bonding *bond = netdev_priv(dev);
> - struct slave *slave, *first_ok_slave;
> - struct aggregator *agg;
> - struct ad_info ad_info;
> - struct list_head *iter;
> - int slaves_in_agg;
> - int slave_agg_no;
> - int agg_id;
> -
> - if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
> - netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n");
> - goto err_free;
> - }
> -
> - slaves_in_agg = ad_info.ports;
> - agg_id = ad_info.aggregator_id;
> -
> - if (slaves_in_agg == 0) {
> - netdev_dbg(dev, "active aggregator is empty\n");
> - goto err_free;
> - }
> -
> - slave_agg_no = bond_xmit_hash(bond, skb) % slaves_in_agg;
> - first_ok_slave = NULL;
> -
> - bond_for_each_slave_rcu(bond, slave, iter) {
> - agg = SLAVE_AD_INFO(slave)->port.aggregator;
> - if (!agg || agg->aggregator_identifier != agg_id)
> - continue;
> -
> - if (slave_agg_no >= 0) {
> - if (!first_ok_slave && bond_slave_can_tx(slave))
> - first_ok_slave = slave;
> - slave_agg_no--;
> - continue;
> - }
> -
> - if (bond_slave_can_tx(slave)) {
> - bond_dev_queue_xmit(bond, skb, slave->dev);
> - goto out;
> - }
> - }
> -
> - if (slave_agg_no >= 0) {
> - netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n",
> - agg_id);
> - goto err_free;
> - }
> -
> - /* we couldn't find any suitable slave after the agg_no, so use the
> - * first suitable found, if found.
> - */
> - if (first_ok_slave)
> - bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
> - else
> - goto err_free;
> -
> -out:
> - return NETDEV_TX_OK;
> -err_free:
> - /* no suitable interface, frame not sent */
> - dev_kfree_skb_any(skb);
> - goto out;
> -}
> -
> int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
> struct slave *slave)
> {
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index 028496205f39..dbac0ceb17f6 100644
> --- a/drivers/net/bonding/bond_alb.c
> +++ b/drivers/net/bonding/bond_alb.c
> @@ -200,7 +200,6 @@ static int tlb_initialize(struct bonding *bond)
> static void tlb_deinitialize(struct bonding *bond)
> {
> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> - struct tlb_up_slave *arr;
>
> _lock_tx_hashtbl_bh(bond);
>
> @@ -208,10 +207,6 @@ static void tlb_deinitialize(struct bonding *bond)
> bond_info->tx_hashtbl = NULL;
>
> _unlock_tx_hashtbl_bh(bond);
> -
> - arr = rtnl_dereference(bond_info->slave_arr);
> - if (arr)
> - kfree_rcu(arr, rcu);
> }
>
> static long long compute_gap(struct slave *slave)
> @@ -1409,39 +1404,9 @@ out:
> return NETDEV_TX_OK;
> }
>
> -static int bond_tlb_update_slave_arr(struct bonding *bond,
> - struct slave *skipslave)
> -{
> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> - struct slave *tx_slave;
> - struct list_head *iter;
> - struct tlb_up_slave *new_arr, *old_arr;
> -
> - new_arr = kzalloc(offsetof(struct tlb_up_slave, arr[bond->slave_cnt]),
> - GFP_ATOMIC);
> - if (!new_arr)
> - return -ENOMEM;
> -
> - bond_for_each_slave(bond, tx_slave, iter) {
> - if (!bond_slave_can_tx(tx_slave))
> - continue;
> - if (skipslave == tx_slave)
> - continue;
> - new_arr->arr[new_arr->count++] = tx_slave;
> - }
> -
> - old_arr = rtnl_dereference(bond_info->slave_arr);
> - rcu_assign_pointer(bond_info->slave_arr, new_arr);
> - if (old_arr)
> - kfree_rcu(old_arr, rcu);
> -
> - return 0;
> -}
> -
> int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
> {
> struct bonding *bond = netdev_priv(bond_dev);
> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> struct ethhdr *eth_data;
> struct slave *tx_slave = NULL;
> u32 hash_index;
> @@ -1462,12 +1427,14 @@ int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
> hash_index & 0xFF,
> skb->len);
> } else {
> - struct tlb_up_slave *slaves;
> + struct bond_up_slave *slaves;
> + unsigned int count;
>
> - slaves = rcu_dereference(bond_info->slave_arr);
> - if (slaves && slaves->count)
> + slaves = rcu_dereference(bond->slave_arr);
> + count = slaves ? slaves->count : 0;
> + if (count)
^^^^^^^^^^^^^^^^^^^^^^^^^^
In both of these cases (slaves & slaves->count) you could use likely() as in the
case we have slaves to transmit, it'd be advantageous and will be hit every
time. The cases that we get here and don't have a slave_arr/count are mostly 2:
1. The slaves got released between the start of xmit and this part
2. They were not eligible so the array got emptied
In both of these cases we don't care about the fallout path since transmission
isn't possible anyway.
Also another minor thing is that usually in the cases where we want to fetch a
variable only once ACCESS_ONCE() is used as a weak compiler barrier to make sure
the compiler doesn't optimize out something. The others can correct me if I'm
wrong, but I think in this case it's a good precaution for slaves->count.
These are merely suggestions, I might be wrong.
> tx_slave = slaves->arr[hash_index %
> - slaves->count];
> + count];
> }
> break;
> }
> @@ -1733,10 +1700,6 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
> rlb_clear_slave(bond, slave);
> }
>
> - if (bond_is_nondyn_tlb(bond))
> - if (bond_tlb_update_slave_arr(bond, slave))
> - pr_err("Failed to build slave-array for TLB mode.\n");
> -
> }
>
> /* Caller must hold bond lock for read */
> @@ -1762,7 +1725,7 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
> }
>
> if (bond_is_nondyn_tlb(bond)) {
> - if (bond_tlb_update_slave_arr(bond, NULL))
> + if (bond_update_slave_arr(bond, NULL))
> pr_err("Failed to build slave-array for TLB mode.\n");
> }
> }
> diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
> index aaeac61d03cf..5fc76c01636c 100644
> --- a/drivers/net/bonding/bond_alb.h
> +++ b/drivers/net/bonding/bond_alb.h
> @@ -139,20 +139,12 @@ struct tlb_slave_info {
> */
> };
>
> -struct tlb_up_slave {
> - unsigned int count;
> - struct rcu_head rcu;
> - struct slave *arr[0];
> -};
> -
> struct alb_bond_info {
> struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
> spinlock_t tx_hashtbl_lock;
> u32 unbalanced_load;
> int tx_rebalance_counter;
> int lp_counter;
> - /* -------- non-dynamic tlb mode only ---------*/
> - struct tlb_up_slave __rcu *slave_arr; /* Up slaves */
> /* -------- rlb parameters -------- */
> int rlb_enabled;
> struct rlb_client_info *rx_hashtbl; /* Receive hash table */
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index b43b2df9e5d1..4412c458939d 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -1700,6 +1700,10 @@ static int __bond_release_one(struct net_device *bond_dev,
> write_unlock_bh(&bond->curr_slave_lock);
> }
>
> + if (bond_mode_uses_xmit_hash(bond) &&
> + bond_update_slave_arr(bond, slave))
> + pr_err("Failed to build slave-array.\n");
> +
> netdev_info(bond_dev, "Releasing %s interface %s\n",
> bond_is_active_slave(slave) ? "active" : "backup",
> slave_dev->name);
> @@ -2015,6 +2019,10 @@ static void bond_miimon_commit(struct bonding *bond)
> bond_alb_handle_link_change(bond, slave,
> BOND_LINK_UP);
>
> + if (BOND_MODE(bond) == BOND_MODE_XOR &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> +
> if (!bond->curr_active_slave || slave == primary)
> goto do_failover;
>
> @@ -2042,6 +2050,10 @@ static void bond_miimon_commit(struct bonding *bond)
> bond_alb_handle_link_change(bond, slave,
> BOND_LINK_DOWN);
>
> + if (BOND_MODE(bond) == BOND_MODE_XOR &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> +
> if (slave == rcu_access_pointer(bond->curr_active_slave))
> goto do_failover;
>
> @@ -2505,6 +2517,9 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
>
> if (slave_state_changed) {
> bond_slave_state_change(bond);
> + if (BOND_MODE(bond) == BOND_MODE_XOR &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> } else if (do_failover) {
> /* the bond_select_active_slave must hold RTNL
> * and curr_slave_lock for write.
> @@ -2899,11 +2914,23 @@ static int bond_slave_netdev_event(unsigned long event,
> if (old_duplex != slave->duplex)
> bond_3ad_adapter_duplex_changed(slave);
> }
> + /* Refresh slave-array if applicable!
> + * If the setuo does not use miimon or arpmon (mode-specific!),
> + * then these event will not cause the slave-array to be
> + * refreshed. This will cause xmit to use a slave that is not
> + * usable. Avoid such situation by refeshing the array at these
> + * events. If these (miimon/arpmon) parameters are configured
> + * then array gets refreshed twice and that should be fine!
> + */
> + if (bond_mode_uses_xmit_hash(bond) &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> break;
> case NETDEV_DOWN:
> - /*
> - * ... Or is it this?
> - */
> + /* Refresh slave-array if applicable! */
> + if (bond_mode_uses_xmit_hash(bond) &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> break;
> case NETDEV_CHANGEMTU:
> /*
> @@ -3147,6 +3174,10 @@ static int bond_open(struct net_device *bond_dev)
> bond_3ad_initiate_agg_selection(bond, 1);
> }
>
> + if (bond_mode_uses_xmit_hash(bond) &&
> + bond_update_slave_arr(bond, NULL))
> + pr_err("Failed to build slave-array for XOR mode.\n");
> +
> return 0;
> }
>
> @@ -3654,15 +3685,106 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
> return NETDEV_TX_OK;
> }
>
> -/* In bond_xmit_xor() , we determine the output device by using a pre-
> - * determined xmit_hash_policy(), If the selected device is not enabled,
> - * find the next active slave.
> +/* Build the usable slaves array in control path for modes that use xmit-hash
> + * to determine the slave interface -
> + * (a) BOND_MODE_8023AD
> + * (b) BOND_MODE_XOR
> + * (c) BOND_MODE_TLB && tlb_dynamic_lb == 0
> */
> -static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
> +int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
> {
> - struct bonding *bond = netdev_priv(bond_dev);
> + struct slave *slave;
> + struct list_head *iter;
> + struct bond_up_slave *new_arr, *old_arr;
> + int slaves_in_agg;
> + int agg_id = 0;
> + int ret = 0;
> +
> + new_arr = kzalloc(offsetof(struct bond_up_slave, arr[bond->slave_cnt]),
> + GFP_ATOMIC);
> + if (!new_arr) {
> + ret = -ENOMEM;
> + goto out;
> + }
> + if (BOND_MODE(bond) == BOND_MODE_8023AD) {
> + struct ad_info ad_info;
> +
> + if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
> + pr_debug("bond_3ad_get_active_agg_info failed\n");
> + kfree_rcu(new_arr, rcu);
> + ret = -EINVAL;
> + goto out;
> + }
> + slaves_in_agg = ad_info.ports;
> + agg_id = ad_info.aggregator_id;
> + }
> + bond_for_each_slave(bond, slave, iter) {
> + if (BOND_MODE(bond) == BOND_MODE_8023AD) {
> + struct aggregator *agg;
>
> - bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb) % bond->slave_cnt);
> + agg = SLAVE_AD_INFO(slave)->port.aggregator;
> + if (!agg || agg->aggregator_identifier != agg_id)
> + continue;
> + }
> + if (!bond_slave_can_tx(slave))
> + continue;
> + if (skipslave == slave)
> + continue;
> + new_arr->arr[new_arr->count++] = slave;
> + }
> +
> + old_arr = rcu_dereference_protected(bond->slave_arr,
> + lockdep_rtnl_is_held() ||
> + lockdep_is_held(&bond->curr_slave_lock));
> + rcu_assign_pointer(bond->slave_arr, new_arr);
> + if (old_arr)
> + kfree_rcu(old_arr, rcu);
> +
> +out:
> + if (ret != 0 && skipslave) {
> + int idx;
> +
> + /* Rare situation where caller has asked to skip a specific
> + * slave but allocation failed (most likely!). BTW this is
> + * only possible when the call is initiated from
> + * __bond_release_one(). In this sitation; overwrite the
> + * skipslave entry in the array with the last entry from the
> + * array to avoid a situation where the xmit path may choose
> + * this to-be-skipped slave to send a packet out.
> + */
> + old_arr = rtnl_dereference(bond->slave_arr);
> + for (idx = 0; idx < old_arr->count; idx++) {
> + if (skipslave == old_arr->arr[idx]) {
> + old_arr->arr[idx] =
> + old_arr->arr[old_arr->count-1];
> + old_arr->count--;
> + break;
> + }
> + }
> + }
> + return ret;
> +}
> +
> +/* Use this Xmit function for 3AD as well as XOR modes. The current
> + * usable slave array is formed in the control path. The xmit function
> + * just calculates hash and sends the packet out.
> + */
> +int bond_3ad_xor_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct bonding *bond = netdev_priv(dev);
> + struct slave *slave;
> + struct bond_up_slave *slaves;
> + unsigned int count;
> +
> + slaves = rcu_dereference(bond->slave_arr);
> + count = slaves ? slaves->count : 0;
> + if (count) {
^^^^^^^^^^^^^^
The same comment as above applies here, too.
> + slave = slaves->arr[bond_xmit_hash(bond, skb) % count];
> + bond_dev_queue_xmit(bond, skb, slave->dev);
> + } else {
> + dev_kfree_skb_any(skb);
> + atomic_long_inc(&dev->tx_dropped);
> + }
>
> return NETDEV_TX_OK;
> }
> @@ -3764,12 +3886,11 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
> return bond_xmit_roundrobin(skb, dev);
> case BOND_MODE_ACTIVEBACKUP:
> return bond_xmit_activebackup(skb, dev);
> + case BOND_MODE_8023AD:
> case BOND_MODE_XOR:
> - return bond_xmit_xor(skb, dev);
> + return bond_3ad_xor_xmit(skb, dev);
> case BOND_MODE_BROADCAST:
> return bond_xmit_broadcast(skb, dev);
> - case BOND_MODE_8023AD:
> - return bond_3ad_xmit_xor(skb, dev);
> case BOND_MODE_ALB:
> return bond_alb_xmit(skb, dev);
> case BOND_MODE_TLB:
> @@ -3947,6 +4068,7 @@ static void bond_uninit(struct net_device *bond_dev)
> struct bonding *bond = netdev_priv(bond_dev);
> struct list_head *iter;
> struct slave *slave;
> + struct bond_up_slave *arr;
>
> bond_netpoll_cleanup(bond_dev);
>
> @@ -3955,6 +4077,12 @@ static void bond_uninit(struct net_device *bond_dev)
> __bond_release_one(bond_dev, slave->dev, true);
> netdev_info(bond_dev, "Released all slaves\n");
>
> + arr = rtnl_dereference(bond->slave_arr);
> + if (arr) {
> + kfree_rcu(arr, rcu);
> + RCU_INIT_POINTER(bond->slave_arr, NULL);
> + }
> +
> list_del(&bond->bond_list);
>
> bond_debug_unregister(bond);
> diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
> index 8375133dd347..78d6d3b7a780 100644
> --- a/drivers/net/bonding/bonding.h
> +++ b/drivers/net/bonding/bonding.h
> @@ -177,6 +177,12 @@ struct slave {
> struct kobject kobj;
> };
>
> +struct bond_up_slave {
> + unsigned int count;
> + struct rcu_head rcu;
> + struct slave *arr[0];
> +};
> +
> /*
> * Link pseudo-state only used internally by monitors
> */
> @@ -193,6 +199,7 @@ struct bonding {
> struct slave __rcu *curr_active_slave;
> struct slave __rcu *current_arp_slave;
> struct slave __rcu *primary_slave;
> + struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
> bool force_primary;
> s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
> int (*recv_probe)(const struct sk_buff *, struct bonding *,
> @@ -530,6 +537,7 @@ const char *bond_slave_link_status(s8 link);
> struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
> struct net_device *end_dev,
> int level);
> +int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
>
> #ifdef CONFIG_PROC_FS
> void bond_create_proc_entry(struct bonding *bond);
>
^ permalink raw reply
* Re: PTP_PEROUT_REQUEST and clock stepping
From: Daniel Glöckner @ 2014-09-11 9:52 UTC (permalink / raw)
To: Richard Cochran; +Cc: netdev
In-Reply-To: <20140910172619.GB5944@localhost.localdomain>
On Wed, Sep 10, 2014 at 07:26:20PM +0200, Richard Cochran wrote:
> On Wed, Sep 10, 2014 at 06:16:37PM +0200, Daniel Glöckner wrote:
> > I was wondering how periodic output is supposed to behave if the clock
> > is stepped from a time after ptp_perout_request.start to a time before
> > ptp_perout_request.start.
>
> I would say the result is undefined.
>
> User space should first stop the periodic output, then reprogram the
> clock, then restart the periodic output. Anything else makes no sense
> at all.
But then the PTP demon has to be responsible for configuring the periodic
outputs as well.
IMHO there is no use for a .start value > .period. It is good for defining
the phase of the periodic output but is just annoying if you want to have
the periodic output running all the time. Only a small fraction of people
using periodic outputs will want to schedule the start of the signal at
a specific time in the future and only a fraction of those will use a
.period value that is so small that they can't use a timer to configure
the periodic output within .period/2 before the desired start time.
Best regards,
Daniel
--
Dipl.-Math. Daniel Glöckner, emlix GmbH, http://www.emlix.com
Fon +49 551 30664-0, Fax +49 551 30664-11,
Bertha-von-Suttner-Straße 9, 37085 Göttingen, Germany
Sitz der Gesellschaft: Göttingen, Amtsgericht Göttingen HR B 3160
Geschäftsführung: Dr. Uwe Kracke, Ust-IdNr.: DE 205 198 055
emlix - your embedded linux partner
^ permalink raw reply
* [PATCH] net: axienet: remove unnecessary ether_setup after alloc_etherdev
From: Subbaraya Sundeep Bhatta @ 2014-09-11 9:23 UTC (permalink / raw)
To: davem, jeffrey.t.kirsher, jesse.brandeburg, netdev, linux-kernel
Cc: michals, svemula, anirudh, Subbaraya Sundeep Bhatta
calling ether_setup is redundant since alloc_etherdev calls
it.
Signed-off-by: Subbaraya Sundeep Bhatta <sbhatta@xilinx.com>
---
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index c8fd941..4ea2d4e 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1485,7 +1485,6 @@ static int axienet_of_probe(struct platform_device *op)
if (!ndev)
return -ENOMEM;
- ether_setup(ndev);
platform_set_drvdata(op, ndev);
SET_NETDEV_DEV(ndev, &op->dev);
--
1.7.4
^ permalink raw reply related
* [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
From: Sanjeev Sharma @ 2014-09-11 10:09 UTC (permalink / raw)
To: dsd
Cc: kune, linux-wireless, linux-kernel, netdev, Sanjeev Sharma,
Sanjeev Sharma
In-Reply-To: <1410418407.1825.0.camel@jlt4.sipsolutions.net>
on some architecture spin_is_locked() always return false in
uniprocessor configuration and therefore it would be advise
to replace with lockdep_assert_held().
Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
---
Changes in v2:
- corrected the typo
drivers/net/wireless/zd1211rw/zd_mac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index e7af261..adce2ee 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac)
{
flush_workqueue(zd_workqueue);
zd_chip_clear(&mac->chip);
- ZD_ASSERT(!spin_is_locked(&mac->lock));
+ lockdep_assert_held(&mac->lock);
ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
}
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
From: Johannes Berg @ 2014-09-11 10:12 UTC (permalink / raw)
To: Sanjeev Sharma; +Cc: dsd, kune, linux-wireless, linux-kernel, netdev
In-Reply-To: <1410430179-19944-1-git-send-email-sanjeev_sharma@mentor.com>
On Thu, 2014-09-11 at 15:39 +0530, Sanjeev Sharma wrote:
> on some architecture spin_is_locked() always return false in
> uniprocessor configuration and therefore it would be advise
> to replace with lockdep_assert_held().
>
> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
> ---
> Changes in v2:
> - corrected the typo
Now it compiles, but you got the logic wrong.
> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
> @@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac)
> {
> flush_workqueue(zd_workqueue);
> zd_chip_clear(&mac->chip);
> - ZD_ASSERT(!spin_is_locked(&mac->lock));
> + lockdep_assert_held(&mac->lock);
> ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
> }
Look closely at this again.
johannes
^ permalink raw reply
* RE: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
From: Sharma, Sanjeev @ 2014-09-11 10:36 UTC (permalink / raw)
To: Johannes Berg
Cc: dsd@gentoo.org, kune@deine-taler.de,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <1410430345.22863.0.camel@jlt4.sipsolutions.net>
-----Original Message-----
From: Johannes Berg [mailto:johannes@sipsolutions.net]
Sent: Thursday, September 11, 2014 3:42 PM
To: Sharma, Sanjeev
Cc: dsd@gentoo.org; kune@deine-taler.de; linux-wireless@vger.kernel.org; linux-kernel@vger.kernel.org; netdev@vger.kernel.org
Subject: Re: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
On Thu, 2014-09-11 at 15:39 +0530, Sanjeev Sharma wrote:
> on some architecture spin_is_locked() always return false in
> uniprocessor configuration and therefore it would be advise to replace
> with lockdep_assert_held().
>
> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
> ---
> Changes in v2:
> - corrected the typo
> Now it compiles, but you got the logic wrong.
> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
> @@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac) {
> flush_workqueue(zd_workqueue);
> zd_chip_clear(&mac->chip);
> - ZD_ASSERT(!spin_is_locked(&mac->lock));
> + lockdep_assert_held(&mac->lock);
> ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); }
>Look closely at this again.
I didn't understand where I put wrong logic ?
Regards
Sanjeev Sharma
^ permalink raw reply
* Re: [PATCH v2] zd1211rw: replace ZD_ASSERT with lockdep_assert_held()
From: Johannes Berg @ 2014-09-11 10:42 UTC (permalink / raw)
To: Sharma, Sanjeev
Cc: dsd@gentoo.org, kune@deine-taler.de,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <FDC088D3B5555644AE135ED28A7ABDE94DF5256D@EU-MBX-02.mgc.mentorg.com>
On Thu, 2014-09-11 at 10:36 +0000, Sharma, Sanjeev wrote:
> > - ZD_ASSERT(!spin_is_locked(&mac->lock));
> > + lockdep_assert_held(&mac->lock);
> >Look closely at this again.
>
> I didn't understand where I put wrong logic ?
Ok, that's fine. But please send a new patch only when you've understood
the logic.
johannes
^ permalink raw reply
* [PATCH net-next 0/7] bonding: get rid of curr_slave_lock
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
Hi all,
This is the second patch-set dealing with bond locking and the purpose here
is to convert curr_slave_lock into a spinlock called "mode_lock" which can
be used in the various modes for their specific needs. The first three
patches cleanup the use of curr_slave_lock and prepare it for the
conversion which is done in patch 4 and then the modes that were using
their own locks are converted to use the new "mode_lock" giving us the
opportunity to remove their locks.
This patch-set has been tested in each mode by running enslave/release of
slaves in parallel with traffic transmission and miimon=1 i.e. running
all the time. In fact this lead to the discovery of a subtle bug related to
RCU which will be fixed in -net.
Also did an allmodconfig test just in case :-)
Best regards,
Nikolay Aleksandrov
Nikolay Aleksandrov (7):
bonding: 3ad: clean up curr_slave_lock usage
bonding: alb: remove curr_slave_lock
bonding: clean curr_slave_lock use
bonding: convert curr_slave_lock to a spinlock and rename it
bonding: alb: convert to bond->mode_lock
bonding: 3ad: convert to bond->mode_lock
bonding: adjust locking comments
drivers/net/bonding/bond_3ad.c | 76 ++++++------------
drivers/net/bonding/bond_3ad.h | 1 -
drivers/net/bonding/bond_alb.c | 159 +++++++++----------------------------
drivers/net/bonding/bond_alb.h | 2 -
drivers/net/bonding/bond_debugfs.c | 4 +-
drivers/net/bonding/bond_main.c | 89 ++++-----------------
drivers/net/bonding/bond_options.c | 10 +--
drivers/net/bonding/bonding.h | 16 ++--
8 files changed, 89 insertions(+), 268 deletions(-)
--
1.9.3
^ permalink raw reply
* [PATCH net-next 1/7] bonding: 3ad: clean up curr_slave_lock usage
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
Remove the read_lock in bond_3ad_lacpdu_recv() since when the slave is
being released its rx_handler is removed before 3ad unbind, so even if
packets arrive, they won't see the slave in an inconsistent state.
In bond_3ad_state_machine_handler() move the use of curr_slave_lock
around the only place that needs it: ad_agg_selection_logic. Since it
can traverse the lag_ports instead of the slave list, it could reach the
detached slave.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 5d27a6207384..6512c1cee666 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2057,7 +2057,6 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
struct port *port;
bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
- read_lock(&bond->curr_slave_lock);
rcu_read_lock();
/* check if there are any slaves */
@@ -2078,8 +2077,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
goto re_arm;
}
+ read_lock(&bond->curr_slave_lock);
aggregator = __get_first_agg(port);
ad_agg_selection_logic(aggregator);
+ read_unlock(&bond->curr_slave_lock);
}
bond_3ad_set_carrier(bond);
}
@@ -2120,7 +2121,6 @@ re_arm:
}
}
rcu_read_unlock();
- read_unlock(&bond->curr_slave_lock);
if (should_notify_rtnl && rtnl_trylock()) {
bond_slave_state_notify(bond);
@@ -2476,20 +2476,16 @@ err_free:
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
- int ret = RX_HANDLER_ANOTHER;
struct lacpdu *lacpdu, _lacpdu;
if (skb->protocol != PKT_TYPE_LACPDU)
- return ret;
+ return RX_HANDLER_ANOTHER;
lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu);
if (!lacpdu)
- return ret;
+ return RX_HANDLER_ANOTHER;
- read_lock(&bond->curr_slave_lock);
- ret = bond_3ad_rx_indication(lacpdu, slave, skb->len);
- read_unlock(&bond->curr_slave_lock);
- return ret;
+ return bond_3ad_rx_indication(lacpdu, slave, skb->len);
}
/**
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 2/7] bonding: alb: remove curr_slave_lock
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
First in rlb_teach_disabled_mac_on_primary() it's okay to remove
curr_slave_lock as all callers except bond_alb_monitor() already hold
RTNL, and in case bond_alb_monitor() is executing we can at most have a
period with bad throughput (very unlikely though).
In bond_alb_monitor() it's okay to remove the read_lock as the slave
list is walked with RCU and the worst that could happen is another
transmitter at the same time and thus for a period which currently is 10
seconds (bond_alb.h: BOND_ALB_LP_TICKS).
And bond_alb_handle_active_change() is okay because it's always called
with RTNL. Removed the ASSERT_RTNL() because it'll be inserted in the
parent function in a following patch.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_alb.c | 39 +++------------------------------------
1 file changed, 3 insertions(+), 36 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 028496205f39..cf4ede8594ff 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -447,7 +447,7 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond)
/* teach the switch the mac of a disabled slave
* on the primary for fault tolerance
*
- * Caller must hold bond->curr_slave_lock for write or bond lock for write
+ * Caller must hold RTNL
*/
static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
{
@@ -512,12 +512,8 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_unlock_rx_hashtbl_bh(bond);
- write_lock_bh(&bond->curr_slave_lock);
-
if (slave != bond_deref_active_protected(bond))
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
-
- write_unlock_bh(&bond->curr_slave_lock);
}
static void rlb_update_client(struct rlb_client_info *client_info)
@@ -1595,13 +1591,6 @@ void bond_alb_monitor(struct work_struct *work)
if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) {
bool strict_match;
- /* change of curr_active_slave involves swapping of mac addresses.
- * in order to avoid this swapping from happening while
- * sending the learning packets, the curr_slave_lock must be held for
- * read.
- */
- read_lock(&bond->curr_slave_lock);
-
bond_for_each_slave_rcu(bond, slave, iter) {
/* If updating current_active, use all currently
* user mac addreses (!strict_match). Otherwise, only
@@ -1613,17 +1602,11 @@ void bond_alb_monitor(struct work_struct *work)
alb_send_learning_packets(slave, slave->dev->dev_addr,
strict_match);
}
-
- read_unlock(&bond->curr_slave_lock);
-
bond_info->lp_counter = 0;
}
/* rebalance tx traffic */
if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) {
-
- read_lock(&bond->curr_slave_lock);
-
bond_for_each_slave_rcu(bond, slave, iter) {
tlb_clear_slave(bond, slave, 1);
if (slave == rcu_access_pointer(bond->curr_active_slave)) {
@@ -1633,9 +1616,6 @@ void bond_alb_monitor(struct work_struct *work)
bond_info->unbalanced_load = 0;
}
}
-
- read_unlock(&bond->curr_slave_lock);
-
bond_info->tx_rebalance_counter = 0;
}
@@ -1775,21 +1755,14 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
* Set the bond->curr_active_slave to @new_slave and handle
* mac address swapping and promiscuity changes as needed.
*
- * If new_slave is NULL, caller must hold curr_slave_lock for write
- *
- * If new_slave is not NULL, caller must hold RTNL, curr_slave_lock
- * for write. Processing here may sleep, so no other locks may be held.
+ * Caller must hold RTNL
*/
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
- __releases(&bond->curr_slave_lock)
- __acquires(&bond->curr_slave_lock)
{
struct slave *swap_slave;
struct slave *curr_active;
- curr_active = rcu_dereference_protected(bond->curr_active_slave,
- !new_slave ||
- lockdep_is_held(&bond->curr_slave_lock));
+ curr_active = rtnl_dereference(bond->curr_active_slave);
if (curr_active == new_slave)
return;
@@ -1820,10 +1793,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
tlb_clear_slave(bond, swap_slave, 1);
tlb_clear_slave(bond, new_slave, 1);
- write_unlock_bh(&bond->curr_slave_lock);
-
- ASSERT_RTNL();
-
/* in TLB mode, the slave might flip down/up with the old dev_addr,
* and thus filter bond->dev_addr's packets, so force bond's mac
*/
@@ -1852,8 +1821,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
alb_send_learning_packets(new_slave, bond->dev->dev_addr,
false);
}
-
- write_lock_bh(&bond->curr_slave_lock);
}
/* Called with RTNL */
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 3/7] bonding: clean curr_slave_lock use
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
Mostly all users of curr_slave_lock already have RTNL as we've discussed
previously so there's no point in using it, the one case where the lock
must stay is the 3ad code, in fact it's the only one.
It's okay to remove it from bond_do_fail_over_mac() as it's called with
RTNL and drops the curr_slave_lock anyway.
bond_change_active_slave() is one of the main places where
curr_slave_lock was used, it's okay to remove it as all callers use RTNL
these days before calling it, that's why we move the ASSERT_RTNL() in
the beginning to catch any potential offenders to this rule.
The RTNL argument actually applies to all of the places where
curr_slave_lock has been removed from in this patch.
Also remove the unnecessary bond_deref_active_protected() macro and use
rtnl_dereference() instead.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_alb.c | 4 +--
drivers/net/bonding/bond_main.c | 62 ++++++--------------------------------
drivers/net/bonding/bond_options.c | 10 +-----
drivers/net/bonding/bonding.h | 8 +----
4 files changed, 14 insertions(+), 70 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index cf4ede8594ff..b755659ddfdc 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -451,7 +451,7 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond)
*/
static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
{
- struct slave *curr_active = bond_deref_active_protected(bond);
+ struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
if (!curr_active)
return;
@@ -512,7 +512,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_unlock_rx_hashtbl_bh(bond);
- if (slave != bond_deref_active_protected(bond))
+ if (slave != rtnl_dereference(bond->curr_active_slave))
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b43b2df9e5d1..3b06685260b8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -637,13 +637,11 @@ static void bond_set_dev_addr(struct net_device *bond_dev,
*
* Perform special MAC address swapping for fail_over_mac settings
*
- * Called with RTNL, curr_slave_lock for write_bh.
+ * Called with RTNL
*/
static void bond_do_fail_over_mac(struct bonding *bond,
struct slave *new_active,
struct slave *old_active)
- __releases(&bond->curr_slave_lock)
- __acquires(&bond->curr_slave_lock)
{
u8 tmp_mac[ETH_ALEN];
struct sockaddr saddr;
@@ -651,11 +649,8 @@ static void bond_do_fail_over_mac(struct bonding *bond,
switch (bond->params.fail_over_mac) {
case BOND_FOM_ACTIVE:
- if (new_active) {
- write_unlock_bh(&bond->curr_slave_lock);
+ if (new_active)
bond_set_dev_addr(bond->dev, new_active->dev);
- write_lock_bh(&bond->curr_slave_lock);
- }
break;
case BOND_FOM_FOLLOW:
/*
@@ -666,8 +661,6 @@ static void bond_do_fail_over_mac(struct bonding *bond,
if (!new_active)
return;
- write_unlock_bh(&bond->curr_slave_lock);
-
if (old_active) {
ether_addr_copy(tmp_mac, new_active->dev->dev_addr);
ether_addr_copy(saddr.sa_data,
@@ -696,7 +689,6 @@ static void bond_do_fail_over_mac(struct bonding *bond,
netdev_err(bond->dev, "Error %d setting MAC of slave %s\n",
-rv, new_active->dev->name);
out:
- write_lock_bh(&bond->curr_slave_lock);
break;
default:
netdev_err(bond->dev, "bond_do_fail_over_mac impossible: bad policy %d\n",
@@ -709,7 +701,7 @@ out:
static bool bond_should_change_active(struct bonding *bond)
{
struct slave *prim = rtnl_dereference(bond->primary_slave);
- struct slave *curr = bond_deref_active_protected(bond);
+ struct slave *curr = rtnl_dereference(bond->curr_active_slave);
if (!prim || !curr || curr->link != BOND_LINK_UP)
return true;
@@ -785,15 +777,15 @@ static bool bond_should_notify_peers(struct bonding *bond)
* because it is apparently the best available slave we have, even though its
* updelay hasn't timed out yet.
*
- * If new_active is not NULL, caller must hold curr_slave_lock for write_bh.
+ * Caller must hold RTNL.
*/
void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
{
struct slave *old_active;
- old_active = rcu_dereference_protected(bond->curr_active_slave,
- !new_active ||
- lockdep_is_held(&bond->curr_slave_lock));
+ ASSERT_RTNL();
+
+ old_active = rtnl_dereference(bond->curr_active_slave);
if (old_active == new_active)
return;
@@ -861,14 +853,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
bond_should_notify_peers(bond);
}
- write_unlock_bh(&bond->curr_slave_lock);
-
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
if (should_notify_peers)
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
bond->dev);
-
- write_lock_bh(&bond->curr_slave_lock);
}
}
@@ -893,7 +881,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
* - The primary_slave has got its link back.
* - A slave has got its link back and there's no old curr_active_slave.
*
- * Caller must hold curr_slave_lock for write_bh.
+ * Caller must hold RTNL.
*/
void bond_select_active_slave(struct bonding *bond)
{
@@ -901,7 +889,7 @@ void bond_select_active_slave(struct bonding *bond)
int rv;
best_slave = bond_find_best_slave(bond);
- if (best_slave != bond_deref_active_protected(bond)) {
+ if (best_slave != rtnl_dereference(bond->curr_active_slave)) {
bond_change_active_slave(bond, best_slave);
rv = bond_set_carrier(bond);
if (!rv)
@@ -1571,9 +1559,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (bond_uses_primary(bond)) {
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
}
@@ -1601,10 +1587,8 @@ err_detach:
RCU_INIT_POINTER(bond->primary_slave, NULL);
if (rcu_access_pointer(bond->curr_active_slave) == new_slave) {
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, NULL);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
}
/* either primary_slave or curr_active_slave might've changed */
@@ -1720,11 +1704,8 @@ static int __bond_release_one(struct net_device *bond_dev,
if (rtnl_dereference(bond->primary_slave) == slave)
RCU_INIT_POINTER(bond->primary_slave, NULL);
- if (oldcurrent == slave) {
- write_lock_bh(&bond->curr_slave_lock);
+ if (oldcurrent == slave)
bond_change_active_slave(bond, NULL);
- write_unlock_bh(&bond->curr_slave_lock);
- }
if (bond_is_lb(bond)) {
/* Must be called only after the slave has been
@@ -1743,11 +1724,7 @@ static int __bond_release_one(struct net_device *bond_dev,
* is no concern that another slave add/remove event
* will interfere.
*/
- write_lock_bh(&bond->curr_slave_lock);
-
bond_select_active_slave(bond);
-
- write_unlock_bh(&bond->curr_slave_lock);
}
if (!bond_has_slaves(bond)) {
@@ -2058,9 +2035,7 @@ static void bond_miimon_commit(struct bonding *bond)
do_failover:
ASSERT_RTNL();
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
}
@@ -2506,15 +2481,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
if (slave_state_changed) {
bond_slave_state_change(bond);
} else if (do_failover) {
- /* the bond_select_active_slave must hold RTNL
- * and curr_slave_lock for write.
- */
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
-
bond_select_active_slave(bond);
-
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
}
rtnl_unlock();
@@ -2670,9 +2638,7 @@ static void bond_ab_arp_commit(struct bonding *bond)
do_failover:
ASSERT_RTNL();
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
}
@@ -2939,9 +2905,7 @@ static int bond_slave_netdev_event(unsigned long event,
primary ? slave_dev->name : "none");
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
break;
case NETDEV_FEAT_CHANGE:
@@ -3106,7 +3070,6 @@ static int bond_open(struct net_device *bond_dev)
/* reset slave->backup and slave->inactive */
if (bond_has_slaves(bond)) {
- read_lock(&bond->curr_slave_lock);
bond_for_each_slave(bond, slave, iter) {
if (bond_uses_primary(bond) &&
slave != rcu_access_pointer(bond->curr_active_slave)) {
@@ -3117,7 +3080,6 @@ static int bond_open(struct net_device *bond_dev)
BOND_SLAVE_NOTIFY_NOW);
}
}
- read_unlock(&bond->curr_slave_lock);
}
bond_work_init_all(bond);
@@ -3239,14 +3201,10 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
if (!mii)
return -EINVAL;
-
if (mii->reg_num == 1) {
mii->val_out = 0;
- read_lock(&bond->curr_slave_lock);
if (netif_carrier_ok(bond->dev))
mii->val_out = BMSR_LSTATUS;
-
- read_unlock(&bond->curr_slave_lock);
}
return 0;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 534c0600484e..b62697f4a3de 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -734,15 +734,13 @@ static int bond_option_active_slave_set(struct bonding *bond,
}
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
-
/* check to see if we are clearing active */
if (!slave_dev) {
netdev_info(bond->dev, "Clearing current active slave\n");
RCU_INIT_POINTER(bond->curr_active_slave, NULL);
bond_select_active_slave(bond);
} else {
- struct slave *old_active = bond_deref_active_protected(bond);
+ struct slave *old_active = rtnl_dereference(bond->curr_active_slave);
struct slave *new_active = bond_slave_get_rtnl(slave_dev);
BUG_ON(!new_active);
@@ -765,8 +763,6 @@ static int bond_option_active_slave_set(struct bonding *bond,
}
}
}
-
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
return ret;
@@ -1066,7 +1062,6 @@ static int bond_option_primary_set(struct bonding *bond,
struct slave *slave;
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
p = strchr(primary, '\n');
if (p)
@@ -1103,7 +1098,6 @@ static int bond_option_primary_set(struct bonding *bond,
primary, bond->dev->name);
out:
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
return 0;
@@ -1117,9 +1111,7 @@ static int bond_option_primary_reselect_set(struct bonding *bond,
bond->params.primary_reselect = newval->value;
block_netpoll_tx();
- write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
return 0;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 78c461abaa09..02afdeb08765 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -184,9 +184,7 @@ struct slave {
/*
* Here are the locking policies for the two bonding locks:
- *
- * 1) Get rcu_read_lock when reading or RTNL when writing slave list.
- * 2) Get bond->curr_slave_lock when reading/writing bond->curr_active_slave.
+ * Get rcu_read_lock when reading or RTNL when writing slave list.
*/
struct bonding {
struct net_device *dev; /* first - useful for panic debug */
@@ -227,10 +225,6 @@ struct bonding {
#define bond_slave_get_rtnl(dev) \
((struct slave *) rtnl_dereference(dev->rx_handler_data))
-#define bond_deref_active_protected(bond) \
- rcu_dereference_protected(bond->curr_active_slave, \
- lockdep_is_held(&bond->curr_slave_lock))
-
struct bond_vlan_tag {
__be16 vlan_proto;
unsigned short vlan_id;
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 4/7] bonding: convert curr_slave_lock to a spinlock and rename it
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
curr_slave_lock is now a misleading name, a much better name is
mode_lock as it'll be used for each mode's purposes and it's no longer
necessary to use a rwlock, a simple spinlock is enough.
Suggested-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 4 ++--
drivers/net/bonding/bond_main.c | 7 +++----
drivers/net/bonding/bonding.h | 2 +-
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6512c1cee666..1b19f35689a4 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2077,10 +2077,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
goto re_arm;
}
- read_lock(&bond->curr_slave_lock);
+ spin_lock_bh(&bond->mode_lock);
aggregator = __get_first_agg(port);
ad_agg_selection_logic(aggregator);
- read_unlock(&bond->curr_slave_lock);
+ spin_unlock_bh(&bond->mode_lock);
}
bond_3ad_set_carrier(bond);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3b06685260b8..99d21c2fd44f 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1679,9 +1679,9 @@ static int __bond_release_one(struct net_device *bond_dev,
/* Sync against bond_3ad_rx_indication and
* bond_3ad_state_machine_handler
*/
- write_lock_bh(&bond->curr_slave_lock);
+ spin_lock_bh(&bond->mode_lock);
bond_3ad_unbind_slave(slave);
- write_unlock_bh(&bond->curr_slave_lock);
+ spin_unlock_bh(&bond->mode_lock);
}
netdev_info(bond_dev, "Releasing %s interface %s\n",
@@ -3850,8 +3850,7 @@ void bond_setup(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- /* initialize rwlocks */
- rwlock_init(&bond->curr_slave_lock);
+ spin_lock_init(&bond->mode_lock);
bond->params = bonding_defaults;
/* Initialize pointers */
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 02afdeb08765..0cda34b827f8 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -195,7 +195,7 @@ struct bonding {
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
struct slave *);
- rwlock_t curr_slave_lock;
+ spinlock_t mode_lock;
u8 send_peer_notif;
u8 igmp_retrans;
#ifdef CONFIG_PROC_FS
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 5/7] bonding: alb: convert to bond->mode_lock
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
The ALB/TLB specific spinlocks are no longer necessary as we now have
bond->mode_lock for this purpose, so convert them and remove them from
struct alb_bond_info.
Also remove the unneeded lock/unlock functions and use spin_lock/unlock
directly.
Suggested-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_alb.c | 108 ++++++++++++-------------------------
drivers/net/bonding/bond_alb.h | 2 -
drivers/net/bonding/bond_debugfs.c | 4 +-
drivers/net/bonding/bond_main.c | 10 ----
4 files changed, 35 insertions(+), 89 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index b755659ddfdc..876b97fb55e9 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -100,27 +100,6 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
/*********************** tlb specific functions ***************************/
-static inline void _lock_tx_hashtbl_bh(struct bonding *bond)
-{
- spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
-}
-
-static inline void _unlock_tx_hashtbl_bh(struct bonding *bond)
-{
- spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
-}
-
-static inline void _lock_tx_hashtbl(struct bonding *bond)
-{
- spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
-}
-
-static inline void _unlock_tx_hashtbl(struct bonding *bond)
-{
- spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
-}
-
-/* Caller must hold tx_hashtbl lock */
static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
{
if (save_load) {
@@ -167,9 +146,9 @@ static void __tlb_clear_slave(struct bonding *bond, struct slave *slave,
static void tlb_clear_slave(struct bonding *bond, struct slave *slave,
int save_load)
{
- _lock_tx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
__tlb_clear_slave(bond, slave, save_load);
- _unlock_tx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
/* Must be called before starting the monitor timer */
@@ -184,14 +163,14 @@ static int tlb_initialize(struct bonding *bond)
if (!new_hashtbl)
return -1;
- _lock_tx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
bond_info->tx_hashtbl = new_hashtbl;
for (i = 0; i < TLB_HASH_TABLE_SIZE; i++)
tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
- _unlock_tx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
return 0;
}
@@ -202,12 +181,12 @@ static void tlb_deinitialize(struct bonding *bond)
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct tlb_up_slave *arr;
- _lock_tx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
kfree(bond_info->tx_hashtbl);
bond_info->tx_hashtbl = NULL;
- _unlock_tx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
arr = rtnl_dereference(bond_info->slave_arr);
if (arr)
@@ -281,7 +260,6 @@ static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index,
return assigned_slave;
}
-/* Caller must hold bond lock for read */
static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index,
u32 skb_len)
{
@@ -291,32 +269,13 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index,
* tlb_choose_channel() is only called by bond_alb_xmit()
* which already has softirq disabled.
*/
- _lock_tx_hashtbl(bond);
+ spin_lock(&bond->mode_lock);
tx_slave = __tlb_choose_channel(bond, hash_index, skb_len);
- _unlock_tx_hashtbl(bond);
+ spin_unlock(&bond->mode_lock);
return tx_slave;
}
/*********************** rlb specific functions ***************************/
-static inline void _lock_rx_hashtbl_bh(struct bonding *bond)
-{
- spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
-}
-
-static inline void _unlock_rx_hashtbl_bh(struct bonding *bond)
-{
- spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
-}
-
-static inline void _lock_rx_hashtbl(struct bonding *bond)
-{
- spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
-}
-
-static inline void _unlock_rx_hashtbl(struct bonding *bond)
-{
- spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
-}
/* when an ARP REPLY is received from a client update its info
* in the rx_hashtbl
@@ -327,7 +286,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
struct rlb_client_info *client_info;
u32 hash_index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
hash_index = _simple_hash((u8 *)&(arp->ip_src), sizeof(arp->ip_src));
client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -342,7 +301,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
bond_info->rx_ntt = 1;
}
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
@@ -479,7 +438,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
u32 index, next_index;
/* clear slave from rx_hashtbl */
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
rx_hash_table = bond_info->rx_hashtbl;
index = bond_info->rx_hashtbl_used_head;
@@ -510,7 +469,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
}
}
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
if (slave != rtnl_dereference(bond->curr_active_slave))
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
@@ -561,7 +520,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
struct rlb_client_info *client_info;
u32 hash_index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
@@ -579,7 +538,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
*/
bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY;
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
/* The slave was assigned a new mac address - update the clients */
@@ -590,7 +549,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
int ntt = 0;
u32 hash_index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
@@ -611,7 +570,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
}
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
/* mark all clients using src_ip to be updated */
@@ -621,7 +580,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
struct rlb_client_info *client_info;
u32 hash_index;
- _lock_rx_hashtbl(bond);
+ spin_lock(&bond->mode_lock);
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
@@ -645,10 +604,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
}
}
- _unlock_rx_hashtbl(bond);
+ spin_unlock(&bond->mode_lock);
}
-/* Caller must hold both bond and ptr locks for read */
static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
@@ -657,7 +615,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
struct rlb_client_info *client_info;
u32 hash_index = 0;
- _lock_rx_hashtbl(bond);
+ spin_lock(&bond->mode_lock);
curr_active_slave = rcu_dereference(bond->curr_active_slave);
@@ -676,7 +634,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
assigned_slave = client_info->slave;
if (assigned_slave) {
- _unlock_rx_hashtbl(bond);
+ spin_unlock(&bond->mode_lock);
return assigned_slave;
}
} else {
@@ -738,7 +696,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
}
}
- _unlock_rx_hashtbl(bond);
+ spin_unlock(&bond->mode_lock);
return assigned_slave;
}
@@ -800,7 +758,7 @@ static void rlb_rebalance(struct bonding *bond)
int ntt;
u32 hash_index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
ntt = 0;
hash_index = bond_info->rx_hashtbl_used_head;
@@ -818,7 +776,7 @@ static void rlb_rebalance(struct bonding *bond)
/* update the team's flag only after the whole iteration */
if (ntt)
bond_info->rx_ntt = 1;
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
/* Caller must hold rx_hashtbl lock */
@@ -917,7 +875,7 @@ static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
u32 ip_src_hash = _simple_hash((u8 *)&(arp->ip_src), sizeof(arp->ip_src));
u32 index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
index = bond_info->rx_hashtbl[ip_src_hash].src_first;
while (index != RLB_NULL_INDEX) {
@@ -928,7 +886,7 @@ static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
rlb_delete_table_entry(bond, index);
index = next_index;
}
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
static int rlb_initialize(struct bonding *bond)
@@ -942,7 +900,7 @@ static int rlb_initialize(struct bonding *bond)
if (!new_hashtbl)
return -1;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
bond_info->rx_hashtbl = new_hashtbl;
@@ -951,7 +909,7 @@ static int rlb_initialize(struct bonding *bond)
for (i = 0; i < RLB_HASH_TABLE_SIZE; i++)
rlb_init_table_entry(bond_info->rx_hashtbl + i);
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
/* register to receive ARPs */
bond->recv_probe = rlb_arp_recv;
@@ -963,13 +921,13 @@ static void rlb_deinitialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
kfree(bond_info->rx_hashtbl);
bond_info->rx_hashtbl = NULL;
bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
@@ -977,7 +935,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 curr_index;
- _lock_rx_hashtbl_bh(bond);
+ spin_lock_bh(&bond->mode_lock);
curr_index = bond_info->rx_hashtbl_used_head;
while (curr_index != RLB_NULL_INDEX) {
@@ -990,7 +948,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
curr_index = next_index;
}
- _unlock_rx_hashtbl_bh(bond);
+ spin_unlock_bh(&bond->mode_lock);
}
/*********************** tlb/rlb shared functions *********************/
@@ -1394,9 +1352,9 @@ static int bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
}
if (tx_slave && bond->params.tlb_dynamic_lb) {
- _lock_tx_hashtbl(bond);
+ spin_lock(&bond->mode_lock);
__tlb_clear_slave(bond, tx_slave, 0);
- _unlock_tx_hashtbl(bond);
+ spin_unlock(&bond->mode_lock);
}
/* no suitable interface, frame not sent */
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index aaeac61d03cf..3c6a7ff974d7 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -147,7 +147,6 @@ struct tlb_up_slave {
struct alb_bond_info {
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
- spinlock_t tx_hashtbl_lock;
u32 unbalanced_load;
int tx_rebalance_counter;
int lp_counter;
@@ -156,7 +155,6 @@ struct alb_bond_info {
/* -------- rlb parameters -------- */
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
- spinlock_t rx_hashtbl_lock;
u32 rx_hashtbl_used_head;
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 280971b227ea..652f6c5d1bf7 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -29,7 +29,7 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
seq_printf(m, "SourceIP DestinationIP "
"Destination MAC DEV\n");
- spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_lock_bh(&bond->mode_lock);
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
@@ -42,7 +42,7 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
client_info->slave->dev->name);
}
- spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_unlock_bh(&bond->mode_lock);
return 0;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 99d21c2fd44f..e06251417a7d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4297,19 +4297,9 @@ static int bond_init(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
- struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
netdev_dbg(bond_dev, "Begin bond_init\n");
- /*
- * Initialize locks that may be required during
- * en/deslave operations. All of the bond_open work
- * (of which this is part) should really be moved to
- * a phase prior to dev_open
- */
- spin_lock_init(&(bond_info->tx_hashtbl_lock));
- spin_lock_init(&(bond_info->rx_hashtbl_lock));
-
bond->wq = create_singlethread_workqueue(bond_dev->name);
if (!bond->wq)
return -ENOMEM;
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 6/7] bonding: 3ad: convert to bond->mode_lock
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
Now that we have bond->mode_lock, we can remove the state_machine_lock
and use it in its place. There're no fast paths requiring the per-port
spinlocks so it should be okay to consolidate them into mode_lock.
Also move it inside the unbinding function as we don't want to expose
mode_lock outside of the specific modes.
Suggested-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 62 +++++++++++++----------------------------
drivers/net/bonding/bond_3ad.h | 1 -
drivers/net/bonding/bond_main.c | 8 +-----
3 files changed, 20 insertions(+), 51 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 1b19f35689a4..38fa749bf83b 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -234,24 +234,6 @@ static inline int __check_agg_selection_timer(struct port *port)
}
/**
- * __get_state_machine_lock - lock the port's state machines
- * @port: the port we're looking at
- */
-static inline void __get_state_machine_lock(struct port *port)
-{
- spin_lock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock));
-}
-
-/**
- * __release_state_machine_lock - unlock the port's state machines
- * @port: the port we're looking at
- */
-static inline void __release_state_machine_lock(struct port *port)
-{
- spin_unlock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock));
-}
-
-/**
* __get_link_speed - get a port's speed
* @port: the port we're looking at
*
@@ -341,16 +323,6 @@ static u8 __get_duplex(struct port *port)
return retval;
}
-/**
- * __initialize_port_locks - initialize a port's STATE machine spinlock
- * @port: the slave of the port we're looking at
- */
-static inline void __initialize_port_locks(struct slave *slave)
-{
- /* make sure it isn't called twice */
- spin_lock_init(&(SLAVE_AD_INFO(slave)->state_machine_lock));
-}
-
/* Conversions */
/**
@@ -1843,7 +1815,6 @@ void bond_3ad_bind_slave(struct slave *slave)
ad_initialize_port(port, bond->params.lacp_fast);
- __initialize_port_locks(slave);
port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave)->id;
/* key is determined according to the link speed, duplex and user key(which
@@ -1899,6 +1870,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
struct slave *slave_iter;
struct list_head *iter;
+ /* Sync against bond_3ad_state_machine_handler() */
+ spin_lock_bh(&bond->mode_lock);
aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
port = &(SLAVE_AD_INFO(slave)->port);
@@ -1906,7 +1879,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
if (!port->slave) {
netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n",
slave->dev->name);
- return;
+ goto out;
}
netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n",
@@ -2032,6 +2005,9 @@ void bond_3ad_unbind_slave(struct slave *slave)
}
}
port->slave = NULL;
+
+out:
+ spin_unlock_bh(&bond->mode_lock);
}
/**
@@ -2098,7 +2074,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
* by all (e.g., port->sm_vars). ad_rx_machine may run
* concurrently due to incoming LACPDU.
*/
- __get_state_machine_lock(port);
+ spin_lock_bh(&bond->mode_lock);
ad_rx_machine(NULL, port);
ad_periodic_machine(port);
@@ -2110,7 +2086,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
if (port->sm_vars & AD_PORT_BEGIN)
port->sm_vars &= ~AD_PORT_BEGIN;
- __release_state_machine_lock(port);
+ spin_unlock_bh(&bond->mode_lock);
}
re_arm:
@@ -2161,9 +2137,9 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n",
port->actor_port_number);
/* Protect against concurrent state machines */
- __get_state_machine_lock(port);
+ spin_lock(&slave->bond->mode_lock);
ad_rx_machine(lacpdu, port);
- __release_state_machine_lock(port);
+ spin_unlock(&slave->bond->mode_lock);
break;
case AD_TYPE_MARKER:
@@ -2213,7 +2189,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
return;
}
- __get_state_machine_lock(port);
+ spin_lock_bh(&slave->bond->mode_lock);
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
@@ -2224,7 +2200,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
*/
port->sm_vars |= AD_PORT_BEGIN;
- __release_state_machine_lock(port);
+ spin_unlock_bh(&slave->bond->mode_lock);
}
/**
@@ -2246,7 +2222,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
return;
}
- __get_state_machine_lock(port);
+ spin_lock_bh(&slave->bond->mode_lock);
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
@@ -2257,7 +2233,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
*/
port->sm_vars |= AD_PORT_BEGIN;
- __release_state_machine_lock(port);
+ spin_unlock_bh(&slave->bond->mode_lock);
}
/**
@@ -2280,7 +2256,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
return;
}
- __get_state_machine_lock(port);
+ spin_lock_bh(&slave->bond->mode_lock);
/* on link down we are zeroing duplex and speed since
* some of the adaptors(ce1000.lan) report full duplex/speed
* instead of N/A(duplex) / 0(speed).
@@ -2311,7 +2287,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
*/
port->sm_vars |= AD_PORT_BEGIN;
- __release_state_machine_lock(port);
+ spin_unlock_bh(&slave->bond->mode_lock);
}
/**
@@ -2495,7 +2471,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
* When modify lacp_rate parameter via sysfs,
* update actor_oper_port_state of each port.
*
- * Hold slave->state_machine_lock,
+ * Hold bond->mode_lock,
* so we can modify port->actor_oper_port_state,
* no matter bond is up or down.
*/
@@ -2509,11 +2485,11 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
lacp_fast = bond->params.lacp_fast;
bond_for_each_slave(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave)->port);
- __get_state_machine_lock(port);
+ spin_lock_bh(&bond->mode_lock);
if (lacp_fast)
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
else
port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
- __release_state_machine_lock(port);
+ spin_unlock_bh(&bond->mode_lock);
}
}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index bb03b1df2f3e..c5f14ac63f3e 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -259,7 +259,6 @@ struct ad_bond_info {
struct ad_slave_info {
struct aggregator aggregator; /* 802.3ad aggregator structure */
struct port port; /* 802.3ad port structure */
- spinlock_t state_machine_lock; /* mutex state machines vs. incoming LACPDU */
u16 id;
};
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e06251417a7d..116cf6965bc5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1675,14 +1675,8 @@ static int __bond_release_one(struct net_device *bond_dev,
*/
netdev_rx_handler_unregister(slave_dev);
- if (BOND_MODE(bond) == BOND_MODE_8023AD) {
- /* Sync against bond_3ad_rx_indication and
- * bond_3ad_state_machine_handler
- */
- spin_lock_bh(&bond->mode_lock);
+ if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_unbind_slave(slave);
- spin_unlock_bh(&bond->mode_lock);
- }
netdev_info(bond_dev, "Releasing %s interface %s\n",
bond_is_active_slave(slave) ? "active" : "backup",
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 7/7] bonding: adjust locking comments
From: Nikolay Aleksandrov @ 2014-09-11 11:38 UTC (permalink / raw)
To: netdev; +Cc: vfalico, j.vosburgh, andy, davem, Nikolay Aleksandrov
In-Reply-To: <1410435523-7520-1-git-send-email-nikolay@redhat.com>
Now that locks have been removed, remove some unnecessary comments and
adjust others to reflect reality. Also add a comment to "mode_lock" to
describe its current users and give a brief summary why they need it.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_alb.c | 8 +-------
drivers/net/bonding/bond_main.c | 6 +++---
drivers/net/bonding/bonding.h | 6 ++++++
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 876b97fb55e9..85af961f1317 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -119,7 +119,6 @@ static inline void tlb_init_slave(struct slave *slave)
SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX;
}
-/* Caller must hold bond lock for read, BH disabled */
static void __tlb_clear_slave(struct bonding *bond, struct slave *slave,
int save_load)
{
@@ -142,7 +141,6 @@ static void __tlb_clear_slave(struct bonding *bond, struct slave *slave,
tlb_init_slave(slave);
}
-/* Caller must hold bond lock for read */
static void tlb_clear_slave(struct bonding *bond, struct slave *slave,
int save_load)
{
@@ -199,7 +197,6 @@ static long long compute_gap(struct slave *slave)
(s64) (SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
}
-/* Caller must hold bond lock for read */
static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
{
struct slave *slave, *least_loaded;
@@ -337,7 +334,6 @@ out:
return RX_HANDLER_ANOTHER;
}
-/* Caller must hold bond lock for read */
static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
@@ -370,7 +366,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
return rx_slave;
}
-/* Caller must hold rcu_read_lock() for read */
+/* Caller must hold rcu_read_lock() */
static struct slave *__rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
@@ -749,7 +745,6 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
return tx_slave;
}
-/* Caller must hold bond lock for read */
static void rlb_rebalance(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
@@ -1677,7 +1672,6 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
}
-/* Caller must hold bond lock for read */
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 116cf6965bc5..2d90a8b7f62e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1629,7 +1629,7 @@ err_undo_flags:
/*
* Try to release the slave device <slave> from the bond device <master>
* It is legal to access curr_active_slave without a lock because all the function
- * is write-locked. If "all" is true it means that the function is being called
+ * is RTNL-locked. If "all" is true it means that the function is being called
* while destroying a bond interface and all slaves are being released.
*
* The rules for slave state should be:
@@ -2494,7 +2494,7 @@ re_arm:
* place for the slave. Returns 0 if no changes are found, >0 if changes
* to link states must be committed.
*
- * Called with rcu_read_lock hold.
+ * Called with rcu_read_lock held.
*/
static int bond_ab_arp_inspect(struct bonding *bond)
{
@@ -2642,7 +2642,7 @@ do_failover:
/*
* Send ARP probes for active-backup mode ARP monitor.
*
- * Called with rcu_read_lock hold.
+ * Called with rcu_read_lock held.
*/
static bool bond_ab_arp_probe(struct bonding *bond)
{
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 0cda34b827f8..3aff1a815e89 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -195,6 +195,12 @@ struct bonding {
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
struct slave *);
+ /* mode_lock is used for mode-specific locking needs, currently used by:
+ * 3ad mode (4) - protect against running bond_3ad_unbind_slave() and
+ * bond_3ad_state_machine_handler() concurrently.
+ * TLB mode (5) - to sync the use and modifications of its hash table
+ * ALB mode (6) - to sync the use and modifications of its hash table
+ */
spinlock_t mode_lock;
u8 send_peer_notif;
u8 igmp_retrans;
--
1.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox