Netdev List
 help / color / mirror / Atom feed
* [PATCH 05/18] batman-adv: Directly print to seq_file in vis
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1340876067-28333-1-git-send-email-ordex@autistici.org>

From: Sven Eckelmann <sven@narfation.org>

The vis output doesn't need to be buffered in an character buffer before it can
be send to the userspace program that reads from the vis debug file.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/vis.c |  226 ++++++++++++++++++--------------------------------
 1 file changed, 82 insertions(+), 144 deletions(-)

diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 6b7a1c0..3095c41 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -140,72 +140,117 @@ static void batadv_vis_data_insert_interface(const uint8_t *interface,
 	hlist_add_head(&entry->list, if_list);
 }
 
-static ssize_t batadv_vis_prim_sec(char *buff, const struct hlist_head *if_list)
+static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
+					  const struct hlist_head *if_list)
 {
 	struct if_list_entry *entry;
 	struct hlist_node *pos;
-	size_t len = 0;
 
 	hlist_for_each_entry(entry, pos, if_list, list) {
 		if (entry->primary)
-			len += sprintf(buff + len, "PRIMARY, ");
+			seq_printf(seq, "PRIMARY, ");
 		else
-			len += sprintf(buff + len,  "SEC %pM, ", entry->addr);
+			seq_printf(seq,  "SEC %pM, ", entry->addr);
 	}
-
-	return len;
-}
-
-static size_t batadv_vis_cnt_prim_sec(struct hlist_head *if_list)
-{
-	struct if_list_entry *entry;
-	struct hlist_node *pos;
-	size_t count = 0;
-
-	hlist_for_each_entry(entry, pos, if_list, list) {
-		if (entry->primary)
-			count += 9;
-		else
-			count += 23;
-	}
-
-	return count;
 }
 
 /* read an entry  */
-static ssize_t batadv_vis_data_read_entry(char *buff,
+static ssize_t batadv_vis_data_read_entry(struct seq_file *seq,
 					  const struct vis_info_entry *entry,
 					  const uint8_t *src, bool primary)
 {
-	/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
 	if (primary && entry->quality == 0)
-		return sprintf(buff, "TT %pM, ", entry->dest);
+		return seq_printf(seq, "TT %pM, ", entry->dest);
 	else if (batadv_compare_eth(entry->src, src))
-		return sprintf(buff, "TQ %pM %d, ", entry->dest,
-			       entry->quality);
+		return seq_printf(seq, "TQ %pM %d, ", entry->dest,
+				  entry->quality);
 
 	return 0;
 }
 
-int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
+static void batadv_vis_data_insert_interfaces(struct hlist_head *list,
+					      struct vis_packet *packet,
+					      struct vis_info_entry *entries)
+{
+	int i;
+
+	for (i = 0; i < packet->entries; i++) {
+		if (entries[i].quality == 0)
+			continue;
+
+		if (batadv_compare_eth(entries[i].src, packet->vis_orig))
+			continue;
+
+		batadv_vis_data_insert_interface(entries[i].src, list, false);
+	}
+}
+
+static void batadv_vis_data_read_entries(struct seq_file *seq,
+					 struct hlist_head *list,
+					 struct vis_packet *packet,
+					 struct vis_info_entry *entries)
+{
+	int i;
+	struct if_list_entry *entry;
+	struct hlist_node *pos;
+
+	hlist_for_each_entry(entry, pos, list, list) {
+		seq_printf(seq, "%pM,", entry->addr);
+
+		for (i = 0; i < packet->entries; i++)
+			batadv_vis_data_read_entry(seq, &entries[i],
+						   entry->addr, entry->primary);
+
+		/* add primary/secondary records */
+		if (batadv_compare_eth(entry->addr, packet->vis_orig))
+			batadv_vis_data_read_prim_sec(seq, list);
+
+		seq_printf(seq, "\n");
+	}
+}
+
+static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
+					     const struct hlist_head *head)
 {
-	struct hard_iface *primary_if;
 	struct hlist_node *node;
-	struct hlist_head *head;
 	struct vis_info *info;
 	struct vis_packet *packet;
+	uint8_t *entries_pos;
 	struct vis_info_entry *entries;
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
+
+	HLIST_HEAD(vis_if_list);
+
+	hlist_for_each_entry_rcu(info, node, head, hash_entry) {
+		packet = (struct vis_packet *)info->skb_packet->data;
+		entries_pos = (uint8_t *)packet + sizeof(*packet);
+		entries = (struct vis_info_entry *)entries_pos;
+
+		batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list,
+						 true);
+		batadv_vis_data_insert_interfaces(&vis_if_list, packet,
+						  entries);
+		batadv_vis_data_read_entries(seq, &vis_if_list, packet,
+					     entries);
+
+		hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
+			hlist_del(&entry->list);
+			kfree(entry);
+		}
+	}
+}
+
+int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
+{
+	struct hard_iface *primary_if;
+	struct hlist_head *head;
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct hashtable_t *hash = bat_priv->vis_hash;
-	HLIST_HEAD(vis_if_list);
-	struct if_list_entry *entry;
-	struct hlist_node *pos, *n;
 	uint32_t i;
-	int j, ret = 0;
+	int ret = 0;
 	int vis_server = atomic_read(&bat_priv->vis_mode);
-	size_t buff_pos, buf_size;
-	char *buff;
 
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (!primary_if)
@@ -214,120 +259,13 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 	if (vis_server == VIS_TYPE_CLIENT_UPDATE)
 		goto out;
 
-	buf_size = 1;
-	/* Estimate length */
 	spin_lock_bh(&bat_priv->vis_hash_lock);
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
-
-		rcu_read_lock();
-		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
-			packet = (struct vis_packet *)info->skb_packet->data;
-			entries = (struct vis_info_entry *)
-				((char *)packet + sizeof(*packet));
-
-			batadv_vis_data_insert_interface(packet->vis_orig,
-							 &vis_if_list, true);
-
-			for (j = 0; j < packet->entries; j++) {
-				if (entries[j].quality == 0)
-					continue;
-				if (batadv_compare_eth(entries[j].src,
-						       packet->vis_orig))
-					continue;
-				batadv_vis_data_insert_interface(entries[j].src,
-								 &vis_if_list,
-								 false);
-			}
-
-			hlist_for_each_entry(entry, pos, &vis_if_list, list) {
-				buf_size += 18 + 26 * packet->entries;
-
-				/* add primary/secondary records */
-				if (batadv_compare_eth(entry->addr,
-						       packet->vis_orig))
-					buf_size +=
-					  batadv_vis_cnt_prim_sec(&vis_if_list);
-
-				buf_size += 1;
-			}
-
-			hlist_for_each_entry_safe(entry, pos, n, &vis_if_list,
-						  list) {
-				hlist_del(&entry->list);
-				kfree(entry);
-			}
-		}
-		rcu_read_unlock();
+		batadv_vis_seq_print_text_bucket(seq, head);
 	}
-
-	buff = kmalloc(buf_size, GFP_ATOMIC);
-	if (!buff) {
-		spin_unlock_bh(&bat_priv->vis_hash_lock);
-		ret = -ENOMEM;
-		goto out;
-	}
-	buff[0] = '\0';
-	buff_pos = 0;
-
-	for (i = 0; i < hash->size; i++) {
-		head = &hash->table[i];
-
-		rcu_read_lock();
-		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
-			packet = (struct vis_packet *)info->skb_packet->data;
-			entries = (struct vis_info_entry *)
-				((char *)packet + sizeof(*packet));
-
-			batadv_vis_data_insert_interface(packet->vis_orig,
-							 &vis_if_list, true);
-
-			for (j = 0; j < packet->entries; j++) {
-				if (entries[j].quality == 0)
-					continue;
-				if (batadv_compare_eth(entries[j].src,
-						       packet->vis_orig))
-					continue;
-				batadv_vis_data_insert_interface(entries[j].src,
-								 &vis_if_list,
-								 false);
-			}
-
-			hlist_for_each_entry(entry, pos, &vis_if_list, list) {
-				buff_pos += sprintf(buff + buff_pos, "%pM,",
-						entry->addr);
-
-				for (j = 0; j < packet->entries; j++)
-					buff_pos += batadv_vis_data_read_entry(
-							buff + buff_pos,
-							&entries[j],
-							entry->addr,
-							entry->primary);
-
-				/* add primary/secondary records */
-				if (batadv_compare_eth(entry->addr,
-						       packet->vis_orig))
-					buff_pos +=
-					 batadv_vis_prim_sec(buff + buff_pos,
-							     &vis_if_list);
-
-				buff_pos += sprintf(buff + buff_pos, "\n");
-			}
-
-			hlist_for_each_entry_safe(entry, pos, n, &vis_if_list,
-						  list) {
-				hlist_del(&entry->list);
-				kfree(entry);
-			}
-		}
-		rcu_read_unlock();
-	}
-
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
 
-	seq_printf(seq, "%s", buff);
-	kfree(buff);
-
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 03/18] batman-adv: Prefix main local static functions with batadv_
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1340876067-28333-1-git-send-email-ordex@autistici.org>

From: Sven Eckelmann <sven@narfation.org>

All non-static symbols of batman-adv were prefixed with batadv_ to avoid
collisions with other symbols of the kernel. Other symbols of batman-adv
should use the same prefix to keep the naming scheme consistent.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/main.c |   76 +++++++++++++++++++++++++------------------------
 1 file changed, 39 insertions(+), 37 deletions(-)

diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index e456430..9cf0b38 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -38,22 +38,23 @@
  * list traversals just rcu-locked
  */
 struct list_head batadv_hardif_list;
-static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *);
+static int (*batadv_rx_handler[256])(struct sk_buff *,
+				     struct hard_iface *);
 char batadv_routing_algo[20] = "BATMAN_IV";
-static struct hlist_head bat_algo_list;
+static struct hlist_head batadv_algo_list;
 
 unsigned char batadv_broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 struct workqueue_struct *batadv_event_workqueue;
 
-static void recv_handler_init(void);
+static void batadv_recv_handler_init(void);
 
-static int __init batman_init(void)
+static int __init batadv_init(void)
 {
 	INIT_LIST_HEAD(&batadv_hardif_list);
-	INIT_HLIST_HEAD(&bat_algo_list);
+	INIT_HLIST_HEAD(&batadv_algo_list);
 
-	recv_handler_init();
+	batadv_recv_handler_init();
 
 	batadv_iv_init();
 
@@ -76,7 +77,7 @@ static int __init batman_init(void)
 	return 0;
 }
 
-static void __exit batman_exit(void)
+static void __exit batadv_exit(void)
 {
 	batadv_debugfs_destroy();
 	unregister_netdevice_notifier(&batadv_hard_if_notifier);
@@ -189,8 +190,8 @@ int batadv_is_my_mac(const uint8_t *addr)
 	return 0;
 }
 
-static int recv_unhandled_packet(struct sk_buff *skb,
-				 struct hard_iface *recv_if)
+static int batadv_recv_unhandled_packet(struct sk_buff *skb,
+					struct hard_iface *recv_if)
 {
 	return NET_RX_DROP;
 }
@@ -248,7 +249,7 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 	 * the supplied skb. if not, we have to free the skb.
 	 */
 	idx = batman_ogm_packet->header.packet_type;
-	ret = (*recv_packet_handler[idx])(skb, hard_iface);
+	ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
 	if (ret == NET_RX_DROP)
 		kfree_skb(skb);
@@ -265,51 +266,51 @@ err_out:
 	return NET_RX_DROP;
 }
 
-static void recv_handler_init(void)
+static void batadv_recv_handler_init(void)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
-		recv_packet_handler[i] = recv_unhandled_packet;
+	for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++)
+		batadv_rx_handler[i] = batadv_recv_unhandled_packet;
 
 	/* batman icmp packet */
-	recv_packet_handler[BAT_ICMP] = batadv_recv_icmp_packet;
+	batadv_rx_handler[BAT_ICMP] = batadv_recv_icmp_packet;
 	/* unicast packet */
-	recv_packet_handler[BAT_UNICAST] = batadv_recv_unicast_packet;
+	batadv_rx_handler[BAT_UNICAST] = batadv_recv_unicast_packet;
 	/* fragmented unicast packet */
-	recv_packet_handler[BAT_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
+	batadv_rx_handler[BAT_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
 	/* broadcast packet */
-	recv_packet_handler[BAT_BCAST] = batadv_recv_bcast_packet;
+	batadv_rx_handler[BAT_BCAST] = batadv_recv_bcast_packet;
 	/* vis packet */
-	recv_packet_handler[BAT_VIS] = batadv_recv_vis_packet;
+	batadv_rx_handler[BAT_VIS] = batadv_recv_vis_packet;
 	/* Translation table query (request or response) */
-	recv_packet_handler[BAT_TT_QUERY] = batadv_recv_tt_query;
+	batadv_rx_handler[BAT_TT_QUERY] = batadv_recv_tt_query;
 	/* Roaming advertisement */
-	recv_packet_handler[BAT_ROAM_ADV] = batadv_recv_roam_adv;
+	batadv_rx_handler[BAT_ROAM_ADV] = batadv_recv_roam_adv;
 }
 
 int batadv_recv_handler_register(uint8_t packet_type,
 				 int (*recv_handler)(struct sk_buff *,
 						     struct hard_iface *))
 {
-	if (recv_packet_handler[packet_type] != &recv_unhandled_packet)
+	if (batadv_rx_handler[packet_type] != &batadv_recv_unhandled_packet)
 		return -EBUSY;
 
-	recv_packet_handler[packet_type] = recv_handler;
+	batadv_rx_handler[packet_type] = recv_handler;
 	return 0;
 }
 
 void batadv_recv_handler_unregister(uint8_t packet_type)
 {
-	recv_packet_handler[packet_type] = recv_unhandled_packet;
+	batadv_rx_handler[packet_type] = batadv_recv_unhandled_packet;
 }
 
-static struct bat_algo_ops *bat_algo_get(char *name)
+static struct bat_algo_ops *batadv_algo_get(char *name)
 {
 	struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
 	struct hlist_node *node;
 
-	hlist_for_each_entry(bat_algo_ops_tmp, node, &bat_algo_list, list) {
+	hlist_for_each_entry(bat_algo_ops_tmp, node, &batadv_algo_list, list) {
 		if (strcmp(bat_algo_ops_tmp->name, name) != 0)
 			continue;
 
@@ -325,7 +326,7 @@ int batadv_algo_register(struct bat_algo_ops *bat_algo_ops)
 	struct bat_algo_ops *bat_algo_ops_tmp;
 	int ret;
 
-	bat_algo_ops_tmp = bat_algo_get(bat_algo_ops->name);
+	bat_algo_ops_tmp = batadv_algo_get(bat_algo_ops->name);
 	if (bat_algo_ops_tmp) {
 		pr_info("Trying to register already registered routing algorithm: %s\n",
 			bat_algo_ops->name);
@@ -347,7 +348,7 @@ int batadv_algo_register(struct bat_algo_ops *bat_algo_ops)
 	}
 
 	INIT_HLIST_NODE(&bat_algo_ops->list);
-	hlist_add_head(&bat_algo_ops->list, &bat_algo_list);
+	hlist_add_head(&bat_algo_ops->list, &batadv_algo_list);
 	ret = 0;
 
 out:
@@ -359,7 +360,7 @@ int batadv_algo_select(struct bat_priv *bat_priv, char *name)
 	struct bat_algo_ops *bat_algo_ops;
 	int ret = -EINVAL;
 
-	bat_algo_ops = bat_algo_get(name);
+	bat_algo_ops = batadv_algo_get(name);
 	if (!bat_algo_ops)
 		goto out;
 
@@ -377,14 +378,14 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
 
 	seq_printf(seq, "Available routing algorithms:\n");
 
-	hlist_for_each_entry(bat_algo_ops, node, &bat_algo_list, list) {
+	hlist_for_each_entry(bat_algo_ops, node, &batadv_algo_list, list) {
 		seq_printf(seq, "%s\n", bat_algo_ops->name);
 	}
 
 	return 0;
 }
 
-static int param_set_ra(const char *val, const struct kernel_param *kp)
+static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
 	struct bat_algo_ops *bat_algo_ops;
 	char *algo_name = (char *)val;
@@ -393,7 +394,7 @@ static int param_set_ra(const char *val, const struct kernel_param *kp)
 	if (algo_name[name_len - 1] == '\n')
 		algo_name[name_len - 1] = '\0';
 
-	bat_algo_ops = bat_algo_get(algo_name);
+	bat_algo_ops = batadv_algo_get(algo_name);
 	if (!bat_algo_ops) {
 		pr_err("Routing algorithm '%s' is not supported\n", algo_name);
 		return -EINVAL;
@@ -402,19 +403,20 @@ static int param_set_ra(const char *val, const struct kernel_param *kp)
 	return param_set_copystring(algo_name, kp);
 }
 
-static const struct kernel_param_ops param_ops_ra = {
-	.set = param_set_ra,
+static const struct kernel_param_ops batadv_param_ops_ra = {
+	.set = batadv_param_set_ra,
 	.get = param_get_string,
 };
 
-static struct kparam_string __param_string_ra = {
+static struct kparam_string batadv_param_string_ra = {
 	.maxlen = sizeof(batadv_routing_algo),
 	.string = batadv_routing_algo,
 };
 
-module_param_cb(routing_algo, &param_ops_ra, &__param_string_ra, 0644);
-module_init(batman_init);
-module_exit(batman_exit);
+module_param_cb(routing_algo, &batadv_param_ops_ra, &batadv_param_string_ra,
+		0644);
+module_init(batadv_init);
+module_exit(batadv_exit);
 
 MODULE_LICENSE("GPL");
 
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 01/18] batman-adv: Prefix unicast local static functions with batadv_
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1340876067-28333-1-git-send-email-ordex@autistici.org>

From: Sven Eckelmann <sven@narfation.org>

All non-static symbols of batman-adv were prefixed with batadv_ to avoid
collisions with other symbols of the kernel. Other symbols of batman-adv
should use the same prefix to keep the naming scheme consistent.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/unicast.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index d021055..472436a 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -29,9 +29,10 @@
 #include "hard-interface.h"
 
 
-static struct sk_buff *frag_merge_packet(struct list_head *head,
-					 struct frag_packet_list_entry *tfp,
-					 struct sk_buff *skb)
+static struct sk_buff *
+batadv_frag_merge_packet(struct list_head *head,
+			 struct frag_packet_list_entry *tfp,
+			 struct sk_buff *skb)
 {
 	struct unicast_frag_packet *up =
 		(struct unicast_frag_packet *)skb->data;
@@ -75,7 +76,8 @@ err:
 	return NULL;
 }
 
-static void frag_create_entry(struct list_head *head, struct sk_buff *skb)
+static void batadv_frag_create_entry(struct list_head *head,
+				     struct sk_buff *skb)
 {
 	struct frag_packet_list_entry *tfp;
 	struct unicast_frag_packet *up =
@@ -91,7 +93,7 @@ static void frag_create_entry(struct list_head *head, struct sk_buff *skb)
 	return;
 }
 
-static int frag_create_buffer(struct list_head *head)
+static int batadv_frag_create_buffer(struct list_head *head)
 {
 	int i;
 	struct frag_packet_list_entry *tfp;
@@ -111,8 +113,9 @@ static int frag_create_buffer(struct list_head *head)
 	return 0;
 }
 
-static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
-					   const struct unicast_frag_packet *up)
+static struct frag_packet_list_entry *
+batadv_frag_search_packet(struct list_head *head,
+			  const struct unicast_frag_packet *up)
 {
 	struct frag_packet_list_entry *tfp;
 	struct unicast_frag_packet *tmp_up = NULL;
@@ -188,22 +191,22 @@ int batadv_frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 	orig_node->last_frag_packet = jiffies;
 
 	if (list_empty(&orig_node->frag_list) &&
-	    frag_create_buffer(&orig_node->frag_list)) {
+	    batadv_frag_create_buffer(&orig_node->frag_list)) {
 		pr_debug("couldn't create frag buffer\n");
 		goto out;
 	}
 
-	tmp_frag_entry = frag_search_packet(&orig_node->frag_list,
-					    unicast_packet);
+	tmp_frag_entry = batadv_frag_search_packet(&orig_node->frag_list,
+						   unicast_packet);
 
 	if (!tmp_frag_entry) {
-		frag_create_entry(&orig_node->frag_list, skb);
+		batadv_frag_create_entry(&orig_node->frag_list, skb);
 		ret = NET_RX_SUCCESS;
 		goto out;
 	}
 
-	*new_skb = frag_merge_packet(&orig_node->frag_list, tmp_frag_entry,
-				     skb);
+	*new_skb = batadv_frag_merge_packet(&orig_node->frag_list,
+					    tmp_frag_entry, skb);
 	/* if not, merge failed */
 	if (*new_skb)
 		ret = NET_RX_SUCCESS;
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 04/18] batman-adv: Prefix remaining function like macros with batadv_
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1340876067-28333-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

From: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
Signed-off-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
---
 net/batman-adv/bat_debugfs.c       |    4 +-
 net/batman-adv/bat_iv_ogm.c        |    2 +-
 net/batman-adv/bat_sysfs.c         |   81 ++++++++++++++++++++----------------
 net/batman-adv/gateway_client.c    |    2 +-
 net/batman-adv/gateway_common.c    |   26 ++++++------
 net/batman-adv/hard-interface.c    |   38 ++++++++---------
 net/batman-adv/main.h              |   20 ++++-----
 net/batman-adv/routing.c           |    4 +-
 net/batman-adv/send.c              |    2 +-
 net/batman-adv/translation-table.c |    4 +-
 net/batman-adv/vis.c               |    4 +-
 11 files changed, 98 insertions(+), 89 deletions(-)

diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index 03f09f0..ca6aee4 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -360,8 +360,8 @@ int batadv_debugfs_add_meshif(struct net_device *dev)
 					  bat_priv->debug_dir,
 					  dev, &(*bat_debug)->fops);
 		if (!file) {
-			bat_err(dev, "Can't add debugfs file: %s/%s\n",
-				dev->name, ((*bat_debug)->attr).name);
+			batadv_err(dev, "Can't add debugfs file: %s/%s\n",
+				   dev->name, ((*bat_debug)->attr).name);
 			goto rem_attr;
 		}
 	}
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index ca64665..ffe9d1d 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -373,7 +373,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 
 	/* own packet should always be scheduled */
 	if (!own_packet) {
-		if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
+		if (!batadv_atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
 			batadv_dbg(DBG_BATMAN, bat_priv,
 				   "batman packet queue full\n");
 			goto out;
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 03b76a4..54429a2 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -191,18 +191,17 @@ static int batadv_store_bool_attr(char *buff, size_t count,
 		enabled = 0;
 
 	if (enabled < 0) {
-		bat_info(net_dev,
-			 "%s: Invalid parameter received: %s\n",
-			 attr_name, buff);
+		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
+			    attr_name, buff);
 		return -EINVAL;
 	}
 
 	if (atomic_read(attr) == enabled)
 		return count;
 
-	bat_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
-		 atomic_read(attr) == 1 ? "enabled" : "disabled",
-		 enabled == 1 ? "enabled" : "disabled");
+	batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
+		    atomic_read(attr) == 1 ? "enabled" : "disabled",
+		    enabled == 1 ? "enabled" : "disabled");
 
 	atomic_set(attr, (unsigned int)enabled);
 	return count;
@@ -235,29 +234,28 @@ static int batadv_store_uint_attr(const char *buff, size_t count,
 
 	ret = kstrtoul(buff, 10, &uint_val);
 	if (ret) {
-		bat_info(net_dev,
-			 "%s: Invalid parameter received: %s\n",
-			 attr_name, buff);
+		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
+			    attr_name, buff);
 		return -EINVAL;
 	}
 
 	if (uint_val < min) {
-		bat_info(net_dev, "%s: Value is too small: %lu min: %u\n",
-			 attr_name, uint_val, min);
+		batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
+			    attr_name, uint_val, min);
 		return -EINVAL;
 	}
 
 	if (uint_val > max) {
-		bat_info(net_dev, "%s: Value is too big: %lu max: %u\n",
-			 attr_name, uint_val, max);
+		batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
+			    attr_name, uint_val, max);
 		return -EINVAL;
 	}
 
 	if (atomic_read(attr) == uint_val)
 		return count;
 
-	bat_info(net_dev, "%s: Changing from: %i to: %lu\n",
-		 attr_name, atomic_read(attr), uint_val);
+	batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
+		    attr_name, atomic_read(attr), uint_val);
 
 	atomic_set(attr, uint_val);
 	return count;
@@ -299,6 +297,7 @@ static ssize_t batadv_store_vis_mode(struct kobject *kobj,
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	unsigned long val;
 	int ret, vis_mode_tmp = -1;
+	const char *old_mode, *new_mode;
 
 	ret = kstrtoul(buff, 10, &val);
 
@@ -315,19 +314,27 @@ static ssize_t batadv_store_vis_mode(struct kobject *kobj,
 		if (buff[count - 1] == '\n')
 			buff[count - 1] = '\0';
 
-		bat_info(net_dev,
-			 "Invalid parameter for 'vis mode' setting received: %s\n",
-			 buff);
+		batadv_info(net_dev,
+			    "Invalid parameter for 'vis mode' setting received: %s\n",
+			    buff);
 		return -EINVAL;
 	}
 
 	if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
 		return count;
 
-	bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
-		 atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
-		 "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
-		 "client" : "server");
+	if (atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE)
+		old_mode =  "client";
+	else
+		old_mode = "server";
+
+	if (vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE)
+		new_mode =  "client";
+	else
+		new_mode = "server";
+
+	batadv_info(net_dev, "Changing vis mode from: %s to: %s\n", old_mode,
+		    new_mode);
 
 	atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp);
 	return count;
@@ -391,9 +398,9 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
 		gw_mode_tmp = GW_MODE_SERVER;
 
 	if (gw_mode_tmp < 0) {
-		bat_info(net_dev,
-			 "Invalid parameter for 'gw mode' setting received: %s\n",
-			 buff);
+		batadv_info(net_dev,
+			    "Invalid parameter for 'gw mode' setting received: %s\n",
+			    buff);
 		return -EINVAL;
 	}
 
@@ -412,8 +419,8 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
 		break;
 	}
 
-	bat_info(net_dev, "Changing gw mode from: %s to: %s\n",
-		 curr_gw_mode_str, buff);
+	batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
+		    curr_gw_mode_str, buff);
 
 	batadv_gw_deselect(bat_priv);
 	atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
@@ -500,8 +507,8 @@ int batadv_sysfs_add_meshif(struct net_device *dev)
 	bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
 						    batif_kobject);
 	if (!bat_priv->mesh_obj) {
-		bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
-			SYSFS_IF_MESH_SUBDIR);
+		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
+			   SYSFS_IF_MESH_SUBDIR);
 		goto out;
 	}
 
@@ -509,9 +516,9 @@ int batadv_sysfs_add_meshif(struct net_device *dev)
 		err = sysfs_create_file(bat_priv->mesh_obj,
 					&((*bat_attr)->attr));
 		if (err) {
-			bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
-				dev->name, SYSFS_IF_MESH_SUBDIR,
-				((*bat_attr)->attr).name);
+			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
+				   dev->name, SYSFS_IF_MESH_SUBDIR,
+				   ((*bat_attr)->attr).name);
 			goto rem_attr;
 		}
 	}
@@ -669,17 +676,17 @@ int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
 						    hardif_kobject);
 
 	if (!*hardif_obj) {
-		bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
-			SYSFS_IF_BAT_SUBDIR);
+		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
+			   SYSFS_IF_BAT_SUBDIR);
 		goto out;
 	}
 
 	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
 		err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
 		if (err) {
-			bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
-				dev->name, SYSFS_IF_BAT_SUBDIR,
-				((*bat_attr)->attr).name);
+			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
+				   dev->name, SYSFS_IF_BAT_SUBDIR,
+				   ((*bat_attr)->attr).name);
 			goto rem_attr;
 		}
 	}
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index efe7519..f43eb57 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -197,7 +197,7 @@ void batadv_gw_election(struct bat_priv *bat_priv)
 	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
 		goto out;
 
-	if (!atomic_dec_not_zero(&bat_priv->gw_reselect))
+	if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect))
 		goto out;
 
 	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 6edf37f..f5c3980 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -97,9 +97,9 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 
 	ret = kstrtol(buff, 10, &ldown);
 	if (ret) {
-		bat_err(net_dev,
-			"Download speed of gateway mode invalid: %s\n",
-			buff);
+		batadv_err(net_dev,
+			   "Download speed of gateway mode invalid: %s\n",
+			   buff);
 		return false;
 	}
 
@@ -122,9 +122,9 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 
 		ret = kstrtol(slash_ptr + 1, 10, &lup);
 		if (ret) {
-			bat_err(net_dev,
-				"Upload speed of gateway mode invalid: %s\n",
-				slash_ptr + 1);
+			batadv_err(net_dev,
+				   "Upload speed of gateway mode invalid: %s\n",
+				   slash_ptr + 1);
 			return false;
 		}
 
@@ -164,13 +164,13 @@ ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
 		return count;
 
 	batadv_gw_deselect(bat_priv);
-	bat_info(net_dev,
-		 "Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n",
-		 atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp,
-		 (down > 2048 ? down / 1024 : down),
-		 (down > 2048 ? "MBit" : "KBit"),
-		 (up > 2048 ? up / 1024 : up),
-		 (up > 2048 ? "MBit" : "KBit"));
+	batadv_info(net_dev,
+		    "Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n",
+		    atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp,
+		    (down > 2048 ? down / 1024 : down),
+		    (down > 2048 ? "MBit" : "KBit"),
+		    (up > 2048 ? up / 1024 : up),
+		    (up > 2048 ? "MBit" : "KBit"));
 
 	atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp);
 
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index c22c145..c1ba6e2 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -234,8 +234,8 @@ static void batadv_hardif_activate_interface(struct hard_iface *hard_iface)
 	if (!primary_if)
 		batadv_primary_if_select(bat_priv, hard_iface);
 
-	bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
-		 hard_iface->net_dev->name);
+	batadv_info(hard_iface->soft_iface, "Interface activated: %s\n",
+		    hard_iface->net_dev->name);
 
 	batadv_update_min_mtu(hard_iface->soft_iface);
 
@@ -252,8 +252,8 @@ static void batadv_hardif_deactivate_interface(struct hard_iface *hard_iface)
 
 	hard_iface->if_status = IF_INACTIVE;
 
-	bat_info(hard_iface->soft_iface, "Interface deactivated: %s\n",
-		 hard_iface->net_dev->name);
+	batadv_info(hard_iface->soft_iface, "Interface deactivated: %s\n",
+		    hard_iface->net_dev->name);
 
 	batadv_update_min_mtu(hard_iface->soft_iface);
 }
@@ -315,29 +315,29 @@ int batadv_hardif_enable_interface(struct hard_iface *hard_iface,
 	dev_add_pack(&hard_iface->batman_adv_ptype);
 
 	atomic_set(&hard_iface->frag_seqno, 1);
-	bat_info(hard_iface->soft_iface, "Adding interface: %s\n",
-		 hard_iface->net_dev->name);
+	batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",
+		    hard_iface->net_dev->name);
 
 	if (atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu <
 		ETH_DATA_LEN + BAT_HEADER_LEN)
-		bat_info(hard_iface->soft_iface,
-			 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n",
-			 hard_iface->net_dev->name, hard_iface->net_dev->mtu,
-			 ETH_DATA_LEN + BAT_HEADER_LEN);
+		batadv_info(hard_iface->soft_iface,
+			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n",
+			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
+			    ETH_DATA_LEN + BAT_HEADER_LEN);
 
 	if (!atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu <
 		ETH_DATA_LEN + BAT_HEADER_LEN)
-		bat_info(hard_iface->soft_iface,
-			 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n",
-			 hard_iface->net_dev->name, hard_iface->net_dev->mtu,
-			 ETH_DATA_LEN + BAT_HEADER_LEN);
+		batadv_info(hard_iface->soft_iface,
+			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n",
+			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
+			    ETH_DATA_LEN + BAT_HEADER_LEN);
 
 	if (batadv_hardif_is_iface_up(hard_iface))
 		batadv_hardif_activate_interface(hard_iface);
 	else
-		bat_err(hard_iface->soft_iface,
-			"Not using interface %s (retrying later): interface not active\n",
-			hard_iface->net_dev->name);
+		batadv_err(hard_iface->soft_iface,
+			   "Not using interface %s (retrying later): interface not active\n",
+			   hard_iface->net_dev->name);
 
 	/* begin scheduling originator messages on that interface */
 	batadv_schedule_bat_ogm(hard_iface);
@@ -363,8 +363,8 @@ void batadv_hardif_disable_interface(struct hard_iface *hard_iface)
 	if (hard_iface->if_status != IF_INACTIVE)
 		goto out;
 
-	bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
-		 hard_iface->net_dev->name);
+	batadv_info(hard_iface->soft_iface, "Removing interface: %s\n",
+		    hard_iface->net_dev->name);
 	dev_remove_pack(&hard_iface->batman_adv_ptype);
 
 	bat_priv->num_ifaces--;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 2824264..b7b9817 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -190,14 +190,14 @@ static inline void batadv_dbg(int type __always_unused,
 }
 #endif
 
-#define bat_info(net_dev, fmt, arg...)					\
+#define batadv_info(net_dev, fmt, arg...)				\
 	do {								\
 		struct net_device *_netdev = (net_dev);                 \
 		struct bat_priv *_batpriv = netdev_priv(_netdev);       \
 		batadv_dbg(DBG_ALL, _batpriv, fmt, ## arg);		\
 		pr_info("%s: " fmt, _netdev->name, ## arg);		\
 	} while (0)
-#define bat_err(net_dev, fmt, arg...)					\
+#define batadv_err(net_dev, fmt, arg...)				\
 	do {								\
 		struct net_device *_netdev = (net_dev);                 \
 		struct bat_priv *_batpriv = netdev_priv(_netdev);       \
@@ -226,10 +226,10 @@ static inline bool batadv_has_timed_out(unsigned long timestamp,
 	return time_is_before_jiffies(timestamp + msecs_to_jiffies(timeout));
 }
 
-#define atomic_dec_not_zero(v)	atomic_add_unless((v), -1, 0)
+#define batadv_atomic_dec_not_zero(v)	atomic_add_unless((v), -1, 0)
 
 /* Returns the smallest signed integer in two's complement with the sizeof x */
-#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
+#define batadv_smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
 
 /* Checks if a sequence number x is a predecessor/successor of y.
  * they handle overflows/underflows and can correctly check for a
@@ -241,12 +241,12 @@ static inline bool batadv_has_timed_out(unsigned long timestamp,
  *  - when adding 128 - it is neither a predecessor nor a successor,
  *  - after adding more than 127 to the starting value - it is a successor
  */
-#define seq_before(x, y) ({typeof(x) _d1 = (x); \
-			  typeof(y) _d2 = (y); \
-			  typeof(x) _dummy = (_d1 - _d2); \
-			  (void) (&_d1 == &_d2); \
-			  _dummy > smallest_signed_int(_dummy); })
-#define seq_after(x, y) seq_before(y, x)
+#define batadv_seq_before(x, y) ({typeof(x) _d1 = (x); \
+				 typeof(y) _d2 = (y); \
+				 typeof(x) _dummy = (_d1 - _d2); \
+				 (void) (&_d1 == &_d2); \
+				 _dummy > batadv_smallest_signed_int(_dummy); })
+#define batadv_seq_after(x, y) batadv_seq_before(y, x)
 
 /* Stop preemption on local cpu while incrementing the counter */
 static inline void batadv_add_counter(struct bat_priv *bat_priv, size_t idx,
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index e7ee40d..1b8f677 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -922,6 +922,7 @@ static int batadv_check_unicast_ttvn(struct bat_priv *bat_priv,
 	struct hard_iface *primary_if;
 	struct unicast_packet *unicast_packet;
 	bool tt_poss_change;
+	int is_old_ttvn;
 
 	/* I could need to modify it */
 	if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
@@ -945,7 +946,8 @@ static int batadv_check_unicast_ttvn(struct bat_priv *bat_priv,
 	}
 
 	/* Check whether I have to reroute the packet */
-	if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
+	is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
+	if (is_old_ttvn || tt_poss_change) {
 		/* check if there is enough data before accessing it */
 		if (pskb_may_pull(skb, sizeof(struct unicast_packet) +
 				  ETH_HLEN) < 0)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 1842cbc..3d725e0 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -141,7 +141,7 @@ int batadv_add_bcast_packet_to_list(struct bat_priv *bat_priv,
 	struct bcast_packet *bcast_packet;
 	struct sk_buff *newskb;
 
-	if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
+	if (!batadv_atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
 		batadv_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
 		goto out;
 	}
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index c673b58..074936f 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1930,7 +1930,7 @@ static bool batadv_tt_check_roam_count(struct bat_priv *bat_priv,
 					 ROAMING_MAX_TIME))
 			continue;
 
-		if (!atomic_dec_not_zero(&tt_roam_node->counter))
+		if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
 			/* Sorry, you roamed too many times! */
 			goto unlock;
 		ret = true;
@@ -2162,7 +2162,7 @@ int batadv_tt_append_diff(struct bat_priv *bat_priv,
 
 	/* if the changes have been sent often enough */
 	if ((tt_num_changes < 0) &&
-	    (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
+	    (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
 		batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 					      packet_min_len, packet_min_len);
 		tt_num_changes = 0;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 607b101..6b7a1c0 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -424,8 +424,8 @@ static struct vis_info *batadv_add_packet(struct bat_priv *bat_priv,
 
 	if (old_info) {
 		old_packet = (struct vis_packet *)old_info->skb_packet->data;
-		if (!seq_after(ntohl(vis_packet->seqno),
-			       ntohl(old_packet->seqno))) {
+		if (!batadv_seq_after(ntohl(vis_packet->seqno),
+				      ntohl(old_packet->seqno))) {
 			if (old_packet->seqno == vis_packet->seqno) {
 				batadv_recv_list_add(bat_priv,
 						     &old_info->recv_list,
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 02/18] batman-adv: Prefix vis local static functions with batadv_
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1340876067-28333-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

From: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

All non-static symbols of batman-adv were prefixed with batadv_ to avoid
collisions with other symbols of the kernel. Other symbols of batman-adv
should use the same prefix to keep the naming scheme consistent.

Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
Signed-off-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
---
 net/batman-adv/vis.c |  201 ++++++++++++++++++++++++++------------------------
 1 file changed, 103 insertions(+), 98 deletions(-)

diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index d45989e..607b101 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -28,10 +28,10 @@
 
 #define MAX_VIS_PACKET_SIZE 1000
 
-static void start_vis_timer(struct bat_priv *bat_priv);
+static void batadv_start_vis_timer(struct bat_priv *bat_priv);
 
 /* free the info */
-static void free_info(struct kref *ref)
+static void batadv_free_info(struct kref *ref)
 {
 	struct vis_info *info = container_of(ref, struct vis_info, refcount);
 	struct bat_priv *bat_priv = info->bat_priv;
@@ -50,7 +50,7 @@ static void free_info(struct kref *ref)
 }
 
 /* Compare two vis packets, used by the hashing algorithm */
-static int vis_info_cmp(const struct hlist_node *node, const void *data2)
+static int batadv_vis_info_cmp(const struct hlist_node *node, const void *data2)
 {
 	const struct vis_info *d1, *d2;
 	const struct vis_packet *p1, *p2;
@@ -65,7 +65,7 @@ static int vis_info_cmp(const struct hlist_node *node, const void *data2)
 /* hash function to choose an entry in a hash table of given size
  * hash algorithm from http://en.wikipedia.org/wiki/Hash_table
  */
-static uint32_t vis_info_choose(const void *data, uint32_t size)
+static uint32_t batadv_vis_info_choose(const void *data, uint32_t size)
 {
 	const struct vis_info *vis_info = data;
 	const struct vis_packet *packet;
@@ -88,8 +88,8 @@ static uint32_t vis_info_choose(const void *data, uint32_t size)
 	return hash % size;
 }
 
-static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
-				      const void *data)
+static struct vis_info *batadv_vis_hash_find(struct bat_priv *bat_priv,
+					     const void *data)
 {
 	struct hashtable_t *hash = bat_priv->vis_hash;
 	struct hlist_head *head;
@@ -100,12 +100,12 @@ static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
 	if (!hash)
 		return NULL;
 
-	index = vis_info_choose(data, hash->size);
+	index = batadv_vis_info_choose(data, hash->size);
 	head = &hash->table[index];
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
-		if (!vis_info_cmp(node, data))
+		if (!batadv_vis_info_cmp(node, data))
 			continue;
 
 		vis_info_tmp = vis_info;
@@ -119,9 +119,9 @@ static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
 /* insert interface to the list of interfaces of one originator, if it
  * does not already exist in the list
  */
-static void vis_data_insert_interface(const uint8_t *interface,
-				      struct hlist_head *if_list,
-				      bool primary)
+static void batadv_vis_data_insert_interface(const uint8_t *interface,
+					     struct hlist_head *if_list,
+					     bool primary)
 {
 	struct if_list_entry *entry;
 	struct hlist_node *pos;
@@ -140,8 +140,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
 	hlist_add_head(&entry->list, if_list);
 }
 
-static ssize_t vis_data_read_prim_sec(char *buff,
-				      const struct hlist_head *if_list)
+static ssize_t batadv_vis_prim_sec(char *buff, const struct hlist_head *if_list)
 {
 	struct if_list_entry *entry;
 	struct hlist_node *pos;
@@ -157,7 +156,7 @@ static ssize_t vis_data_read_prim_sec(char *buff,
 	return len;
 }
 
-static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
+static size_t batadv_vis_cnt_prim_sec(struct hlist_head *if_list)
 {
 	struct if_list_entry *entry;
 	struct hlist_node *pos;
@@ -174,9 +173,9 @@ static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
 }
 
 /* read an entry  */
-static ssize_t vis_data_read_entry(char *buff,
-				   const struct vis_info_entry *entry,
-				   const uint8_t *src, bool primary)
+static ssize_t batadv_vis_data_read_entry(char *buff,
+					  const struct vis_info_entry *entry,
+					  const uint8_t *src, bool primary)
 {
 	/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
 	if (primary && entry->quality == 0)
@@ -227,8 +226,8 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 			entries = (struct vis_info_entry *)
 				((char *)packet + sizeof(*packet));
 
-			vis_data_insert_interface(packet->vis_orig,
-						  &vis_if_list, true);
+			batadv_vis_data_insert_interface(packet->vis_orig,
+							 &vis_if_list, true);
 
 			for (j = 0; j < packet->entries; j++) {
 				if (entries[j].quality == 0)
@@ -236,9 +235,9 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (batadv_compare_eth(entries[j].src,
 						       packet->vis_orig))
 					continue;
-				vis_data_insert_interface(entries[j].src,
-							  &vis_if_list,
-							  false);
+				batadv_vis_data_insert_interface(entries[j].src,
+								 &vis_if_list,
+								 false);
 			}
 
 			hlist_for_each_entry(entry, pos, &vis_if_list, list) {
@@ -248,7 +247,7 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (batadv_compare_eth(entry->addr,
 						       packet->vis_orig))
 					buf_size +=
-					  vis_data_count_prim_sec(&vis_if_list);
+					  batadv_vis_cnt_prim_sec(&vis_if_list);
 
 				buf_size += 1;
 			}
@@ -280,8 +279,8 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 			entries = (struct vis_info_entry *)
 				((char *)packet + sizeof(*packet));
 
-			vis_data_insert_interface(packet->vis_orig,
-						  &vis_if_list, true);
+			batadv_vis_data_insert_interface(packet->vis_orig,
+							 &vis_if_list, true);
 
 			for (j = 0; j < packet->entries; j++) {
 				if (entries[j].quality == 0)
@@ -289,9 +288,9 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (batadv_compare_eth(entries[j].src,
 						       packet->vis_orig))
 					continue;
-				vis_data_insert_interface(entries[j].src,
-							  &vis_if_list,
-							  false);
+				batadv_vis_data_insert_interface(entries[j].src,
+								 &vis_if_list,
+								 false);
 			}
 
 			hlist_for_each_entry(entry, pos, &vis_if_list, list) {
@@ -299,7 +298,7 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 						entry->addr);
 
 				for (j = 0; j < packet->entries; j++)
-					buff_pos += vis_data_read_entry(
+					buff_pos += batadv_vis_data_read_entry(
 							buff + buff_pos,
 							&entries[j],
 							entry->addr,
@@ -309,8 +308,8 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (batadv_compare_eth(entry->addr,
 						       packet->vis_orig))
 					buff_pos +=
-					 vis_data_read_prim_sec(buff + buff_pos,
-								&vis_if_list);
+					 batadv_vis_prim_sec(buff + buff_pos,
+							     &vis_if_list);
 
 				buff_pos += sprintf(buff + buff_pos, "\n");
 			}
@@ -338,7 +337,8 @@ out:
 /* add the info packet to the send list, if it was not
  * already linked in.
  */
-static void send_list_add(struct bat_priv *bat_priv, struct vis_info *info)
+static void batadv_send_list_add(struct bat_priv *bat_priv,
+				 struct vis_info *info)
 {
 	if (list_empty(&info->send_list)) {
 		kref_get(&info->refcount);
@@ -349,17 +349,17 @@ static void send_list_add(struct bat_priv *bat_priv, struct vis_info *info)
 /* delete the info packet from the send list, if it was
  * linked in.
  */
-static void send_list_del(struct vis_info *info)
+static void batadv_send_list_del(struct vis_info *info)
 {
 	if (!list_empty(&info->send_list)) {
 		list_del_init(&info->send_list);
-		kref_put(&info->refcount, free_info);
+		kref_put(&info->refcount, batadv_free_info);
 	}
 }
 
 /* tries to add one entry to the receive list. */
-static void recv_list_add(struct bat_priv *bat_priv,
-			  struct list_head *recv_list, const char *mac)
+static void batadv_recv_list_add(struct bat_priv *bat_priv,
+				 struct list_head *recv_list, const char *mac)
 {
 	struct recvlist_node *entry;
 
@@ -374,8 +374,9 @@ static void recv_list_add(struct bat_priv *bat_priv,
 }
 
 /* returns 1 if this mac is in the recv_list */
-static int recv_list_is_in(struct bat_priv *bat_priv,
-			   const struct list_head *recv_list, const char *mac)
+static int batadv_recv_list_is_in(struct bat_priv *bat_priv,
+				  const struct list_head *recv_list,
+				  const char *mac)
 {
 	const struct recvlist_node *entry;
 
@@ -394,10 +395,10 @@ static int recv_list_is_in(struct bat_priv *bat_priv,
  * broken.. ).	vis hash must be locked outside.  is_new is set when the packet
  * is newer than old entries in the hash.
  */
-static struct vis_info *add_packet(struct bat_priv *bat_priv,
-				   struct vis_packet *vis_packet,
-				   int vis_info_len, int *is_new,
-				   int make_broadcast)
+static struct vis_info *batadv_add_packet(struct bat_priv *bat_priv,
+					  struct vis_packet *vis_packet,
+					  int vis_info_len, int *is_new,
+					  int make_broadcast)
 {
 	struct vis_info *info, *old_info;
 	struct vis_packet *search_packet, *old_packet;
@@ -418,7 +419,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 						     sizeof(*search_packet));
 
 	memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
-	old_info = vis_hash_find(bat_priv, &search_elem);
+	old_info = batadv_vis_hash_find(bat_priv, &search_elem);
 	kfree_skb(search_elem.skb_packet);
 
 	if (old_info) {
@@ -426,8 +427,9 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 		if (!seq_after(ntohl(vis_packet->seqno),
 			       ntohl(old_packet->seqno))) {
 			if (old_packet->seqno == vis_packet->seqno) {
-				recv_list_add(bat_priv, &old_info->recv_list,
-					      vis_packet->sender_orig);
+				batadv_recv_list_add(bat_priv,
+						     &old_info->recv_list,
+						     vis_packet->sender_orig);
 				return old_info;
 			} else {
 				/* newer packet is already in hash. */
@@ -435,10 +437,10 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 			}
 		}
 		/* remove old entry */
-		batadv_hash_remove(bat_priv->vis_hash, vis_info_cmp,
-				   vis_info_choose, old_info);
-		send_list_del(old_info);
-		kref_put(&old_info->refcount, free_info);
+		batadv_hash_remove(bat_priv->vis_hash, batadv_vis_info_cmp,
+				   batadv_vis_info_choose, old_info);
+		batadv_send_list_del(old_info);
+		kref_put(&old_info->refcount, batadv_free_info);
 	}
 
 	info = kmalloc(sizeof(*info), GFP_ATOMIC);
@@ -473,14 +475,15 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 	if (packet->entries * sizeof(struct vis_info_entry) > vis_info_len)
 		packet->entries = vis_info_len / sizeof(struct vis_info_entry);
 
-	recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
+	batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
 
 	/* try to add it */
-	hash_added = batadv_hash_add(bat_priv->vis_hash, vis_info_cmp,
-				     vis_info_choose, info, &info->hash_entry);
+	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
+				     batadv_vis_info_choose, info,
+				     &info->hash_entry);
 	if (hash_added != 0) {
 		/* did not work (for some reason) */
-		kref_put(&info->refcount, free_info);
+		kref_put(&info->refcount, batadv_free_info);
 		info = NULL;
 	}
 
@@ -499,8 +502,8 @@ void batadv_receive_server_sync_packet(struct bat_priv *bat_priv,
 	make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC);
 
 	spin_lock_bh(&bat_priv->vis_hash_lock);
-	info = add_packet(bat_priv, vis_packet, vis_info_len,
-			  &is_new, make_broadcast);
+	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
+				 &is_new, make_broadcast);
 	if (!info)
 		goto end;
 
@@ -508,7 +511,7 @@ void batadv_receive_server_sync_packet(struct bat_priv *bat_priv,
 	 * hash.
 	 */
 	if (vis_server == VIS_TYPE_SERVER_SYNC && is_new)
-		send_list_add(bat_priv, info);
+		batadv_send_list_add(bat_priv, info);
 end:
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
 }
@@ -534,8 +537,8 @@ void batadv_receive_client_update_packet(struct bat_priv *bat_priv,
 		are_target = 1;
 
 	spin_lock_bh(&bat_priv->vis_hash_lock);
-	info = add_packet(bat_priv, vis_packet, vis_info_len,
-			  &is_new, are_target);
+	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
+				 &is_new, are_target);
 
 	if (!info)
 		goto end;
@@ -546,11 +549,11 @@ void batadv_receive_client_update_packet(struct bat_priv *bat_priv,
 	/* send only if we're the target server or ... */
 	if (are_target && is_new) {
 		packet->vis_type = VIS_TYPE_SERVER_SYNC;	/* upgrade! */
-		send_list_add(bat_priv, info);
+		batadv_send_list_add(bat_priv, info);
 
 		/* ... we're not the recipient (and thus need to forward). */
 	} else if (!batadv_is_my_mac(packet->target_orig)) {
-		send_list_add(bat_priv, info);
+		batadv_send_list_add(bat_priv, info);
 	}
 
 end:
@@ -562,8 +565,8 @@ end:
  *
  * Must be called with the originator hash locked
  */
-static int find_best_vis_server(struct bat_priv *bat_priv,
-				struct vis_info *info)
+static int batadv_find_best_vis_server(struct bat_priv *bat_priv,
+				       struct vis_info *info)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
 	struct neigh_node *router;
@@ -600,7 +603,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 }
 
 /* Return true if the vis packet is full. */
-static bool vis_packet_full(const struct vis_info *info)
+static bool batadv_vis_packet_full(const struct vis_info *info)
 {
 	const struct vis_packet *packet;
 	packet = (struct vis_packet *)info->skb_packet->data;
@@ -614,7 +617,7 @@ static bool vis_packet_full(const struct vis_info *info)
 /* generates a packet of own vis data,
  * returns 0 on success, -1 if no packet could be generated
  */
-static int generate_vis_packet(struct bat_priv *bat_priv)
+static int batadv_generate_vis_packet(struct bat_priv *bat_priv)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
 	struct hlist_node *node;
@@ -638,7 +641,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	skb_trim(info->skb_packet, sizeof(*packet));
 
 	if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
-		best_tq = find_best_vis_server(bat_priv, info);
+		best_tq = batadv_find_best_vis_server(bat_priv, info);
 
 		if (best_tq < 0)
 			return best_tq;
@@ -675,7 +678,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 next:
 			batadv_neigh_node_free_ref(router);
 
-			if (vis_packet_full(info))
+			if (batadv_vis_packet_full(info))
 				goto unlock;
 		}
 		rcu_read_unlock();
@@ -697,7 +700,7 @@ next:
 			entry->quality = 0; /* 0 means TT */
 			packet->entries++;
 
-			if (vis_packet_full(info))
+			if (batadv_vis_packet_full(info))
 				goto unlock;
 		}
 		rcu_read_unlock();
@@ -713,7 +716,7 @@ unlock:
 /* free old vis packets. Must be called with this vis_hash_lock
  * held
  */
-static void purge_vis_packets(struct bat_priv *bat_priv)
+static void batadv_purge_vis_packets(struct bat_priv *bat_priv)
 {
 	uint32_t i;
 	struct hashtable_t *hash = bat_priv->vis_hash;
@@ -733,15 +736,15 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
 			if (batadv_has_timed_out(info->first_seen,
 						 VIS_TIMEOUT)) {
 				hlist_del(node);
-				send_list_del(info);
-				kref_put(&info->refcount, free_info);
+				batadv_send_list_del(info);
+				kref_put(&info->refcount, batadv_free_info);
 			}
 		}
 	}
 }
 
-static void broadcast_vis_packet(struct bat_priv *bat_priv,
-				 struct vis_info *info)
+static void batadv_broadcast_vis_packet(struct bat_priv *bat_priv,
+					struct vis_info *info)
 {
 	struct neigh_node *router;
 	struct hashtable_t *hash = bat_priv->orig_hash;
@@ -774,8 +777,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
 			/* don't send it if we already received the packet from
 			 * this node.
 			 */
-			if (recv_list_is_in(bat_priv, &info->recv_list,
-					    orig_node->orig)) {
+			if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
+						   orig_node->orig)) {
 				batadv_neigh_node_free_ref(router);
 				continue;
 			}
@@ -796,8 +799,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
 	}
 }
 
-static void unicast_vis_packet(struct bat_priv *bat_priv,
-			       struct vis_info *info)
+static void batadv_unicast_vis_packet(struct bat_priv *bat_priv,
+				      struct vis_info *info)
 {
 	struct orig_node *orig_node;
 	struct neigh_node *router = NULL;
@@ -825,8 +828,9 @@ out:
 		batadv_orig_node_free_ref(orig_node);
 }
 
-/* only send one vis packet. called from send_vis_packets() */
-static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
+/* only send one vis packet. called from batadv_send_vis_packets() */
+static void batadv_send_vis_packet(struct bat_priv *bat_priv,
+				   struct vis_info *info)
 {
 	struct hard_iface *primary_if;
 	struct vis_packet *packet;
@@ -845,9 +849,9 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
 	packet->header.ttl--;
 
 	if (is_broadcast_ether_addr(packet->target_orig))
-		broadcast_vis_packet(bat_priv, info);
+		batadv_broadcast_vis_packet(bat_priv, info);
 	else
-		unicast_vis_packet(bat_priv, info);
+		batadv_unicast_vis_packet(bat_priv, info);
 	packet->header.ttl++; /* restore TTL */
 
 out:
@@ -856,7 +860,7 @@ out:
 }
 
 /* called from timer; send (and maybe generate) vis packet. */
-static void send_vis_packets(struct work_struct *work)
+static void batadv_send_vis_packets(struct work_struct *work)
 {
 	struct delayed_work *delayed_work =
 		container_of(work, struct delayed_work, work);
@@ -865,11 +869,11 @@ static void send_vis_packets(struct work_struct *work)
 	struct vis_info *info;
 
 	spin_lock_bh(&bat_priv->vis_hash_lock);
-	purge_vis_packets(bat_priv);
+	batadv_purge_vis_packets(bat_priv);
 
-	if (generate_vis_packet(bat_priv) == 0) {
+	if (batadv_generate_vis_packet(bat_priv) == 0) {
 		/* schedule if generation was successful */
-		send_list_add(bat_priv, bat_priv->my_vis_info);
+		batadv_send_list_add(bat_priv, bat_priv->my_vis_info);
 	}
 
 	while (!list_empty(&bat_priv->vis_send_list)) {
@@ -879,14 +883,14 @@ static void send_vis_packets(struct work_struct *work)
 		kref_get(&info->refcount);
 		spin_unlock_bh(&bat_priv->vis_hash_lock);
 
-		send_vis_packet(bat_priv, info);
+		batadv_send_vis_packet(bat_priv, info);
 
 		spin_lock_bh(&bat_priv->vis_hash_lock);
-		send_list_del(info);
-		kref_put(&info->refcount, free_info);
+		batadv_send_list_del(info);
+		kref_put(&info->refcount, batadv_free_info);
 	}
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
-	start_vis_timer(bat_priv);
+	batadv_start_vis_timer(bat_priv);
 }
 
 /* init the vis server. this may only be called when if_list is already
@@ -937,18 +941,19 @@ int batadv_vis_init(struct bat_priv *bat_priv)
 
 	INIT_LIST_HEAD(&bat_priv->vis_send_list);
 
-	hash_added = batadv_hash_add(bat_priv->vis_hash, vis_info_cmp,
-				     vis_info_choose, bat_priv->my_vis_info,
+	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
+				     batadv_vis_info_choose,
+				     bat_priv->my_vis_info,
 				     &bat_priv->my_vis_info->hash_entry);
 	if (hash_added != 0) {
 		pr_err("Can't add own vis packet into hash\n");
 		/* not in hash, need to remove it manually. */
-		kref_put(&bat_priv->my_vis_info->refcount, free_info);
+		kref_put(&bat_priv->my_vis_info->refcount, batadv_free_info);
 		goto err;
 	}
 
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
-	start_vis_timer(bat_priv);
+	batadv_start_vis_timer(bat_priv);
 	return 0;
 
 free_info:
@@ -961,13 +966,13 @@ err:
 }
 
 /* Decrease the reference count on a hash item info */
-static void free_info_ref(struct hlist_node *node, void *arg)
+static void batadv_free_info_ref(struct hlist_node *node, void *arg)
 {
 	struct vis_info *info;
 
 	info = container_of(node, struct vis_info, hash_entry);
-	send_list_del(info);
-	kref_put(&info->refcount, free_info);
+	batadv_send_list_del(info);
+	kref_put(&info->refcount, batadv_free_info);
 }
 
 /* shutdown vis-server */
@@ -980,16 +985,16 @@ void batadv_vis_quit(struct bat_priv *bat_priv)
 
 	spin_lock_bh(&bat_priv->vis_hash_lock);
 	/* properly remove, kill timers ... */
-	batadv_hash_delete(bat_priv->vis_hash, free_info_ref, NULL);
+	batadv_hash_delete(bat_priv->vis_hash, batadv_free_info_ref, NULL);
 	bat_priv->vis_hash = NULL;
 	bat_priv->my_vis_info = NULL;
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
 }
 
 /* schedule packets for (re)transmission */
-static void start_vis_timer(struct bat_priv *bat_priv)
+static void batadv_start_vis_timer(struct bat_priv *bat_priv)
 {
-	INIT_DELAYED_WORK(&bat_priv->vis_work, send_vis_packets);
+	INIT_DELAYED_WORK(&bat_priv->vis_work, batadv_send_vis_packets);
 	queue_delayed_work(batadv_event_workqueue, &bat_priv->vis_work,
 			   msecs_to_jiffies(VIS_INTERVAL));
 }
-- 
1.7.9.4

^ permalink raw reply related

* pull request: batman-adv 2012-06-28
From: Antonio Quartulli @ 2012-06-28  9:34 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r

this is another set of patches I'd like to see included in net-next/linux-3.6.
Here you have some more patches aimed to clean our namespace, a minor cleanup
for the vis code that eliminates a useless intermediate buffer used to
provide the output and two other minor cleanups for the TranslationTable code.


Tell me if there is any problem!

Thank you,
	Antonio



The following changes since commit 160eb5a6b14ca2eab5c598bdbbb24c24624bad34:

  ipv4: Kill early demux method return value. (2012-06-27 22:01:22 -0700)

are available in the git repository at:

  git://git.open-mesh.org/linux-merge.git tags/batman-adv-for-davem

for you to fetch changes up to 42d0b044b7c9e5821f1bf3e2b4ea7861417c11c2:

  batman-adv: Prefix main defines with BATADV_ (2012-06-28 08:45:05 +0200)

----------------------------------------------------------------
Included changes:
- another batch of patches meant to clean batman-adv namespace
- deletion of an obsolete intermediate buffer used in the visualization code to
  print the output
- TT code cleanups

----------------------------------------------------------------
Antonio Quartulli (2):
      batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval
      batman-adv: beautify tt_global_add() argument list

Sven Eckelmann (16):
      batman-adv: Prefix unicast local static functions with batadv_
      batman-adv: Prefix vis local static functions with batadv_
      batman-adv: Prefix main local static functions with batadv_
      batman-adv: Prefix remaining function like macros with batadv_
      batman-adv: Directly print to seq_file in vis
      batman-adv: Prefix local defines with BATADV_
      batman-adv: Prefix debugfs defines with BATADV_
      batman-adv: Prefix sysfs defines with BATADV_
      batman-adv: Prefix bridge_loop_avoidance defines with BATADV_
      batman-adv: Prefix gateway defines with BATADV_
      batman-adv: Prefix icmp_socket defines with BATADV_
      batman-adv: Prefix packet defines with BATADV_
      batman-adv: Prefix types defines with BATADV_
      batman-adv: Prefix unicast defines with BATADV_
      batman-adv: Prefix vis defines with BATADV_
      batman-adv: Prefix main defines with BATADV_

 net/batman-adv/bat_debugfs.c           |   34 +--
 net/batman-adv/bat_debugfs.h           |    2 +-
 net/batman-adv/bat_iv_ogm.c            |  125 ++++++----
 net/batman-adv/bat_sysfs.c             |  228 +++++++++--------
 net/batman-adv/bat_sysfs.h             |    4 +-
 net/batman-adv/bitarray.c              |   20 +-
 net/batman-adv/bitarray.h              |    4 +-
 net/batman-adv/bridge_loop_avoidance.c |   24 +-
 net/batman-adv/bridge_loop_avoidance.h |    2 +-
 net/batman-adv/gateway_client.c        |   32 +--
 net/batman-adv/gateway_common.c        |   26 +-
 net/batman-adv/gateway_common.h        |    6 +-
 net/batman-adv/hard-interface.c        |   50 ++--
 net/batman-adv/icmp_socket.c           |    6 +-
 net/batman-adv/icmp_socket.h           |    2 +-
 net/batman-adv/main.c                  |   91 +++----
 net/batman-adv/main.h                  |  101 ++++----
 net/batman-adv/originator.c            |   34 +--
 net/batman-adv/packet.h                |   12 +-
 net/batman-adv/ring_buffer.c           |    4 +-
 net/batman-adv/routing.c               |   32 +--
 net/batman-adv/send.c                  |    6 +-
 net/batman-adv/soft-interface.c        |   24 +-
 net/batman-adv/translation-table.c     |  163 +++++++-----
 net/batman-adv/translation-table.h     |    4 +-
 net/batman-adv/types.h                 |   19 +-
 net/batman-adv/unicast.c               |   37 +--
 net/batman-adv/unicast.h               |    4 +-
 net/batman-adv/vis.c                   |  422 ++++++++++++++------------------
 net/batman-adv/vis.h                   |    2 +-
 30 files changed, 780 insertions(+), 740 deletions(-)

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
From: Ming Lei @ 2012-06-28  9:11 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Bjørn Mork, netdev, linux-usb, Marius Bjørnstad Kotsbak
In-Reply-To: <201206281035.19964.oneukum@suse.de>

On Thu, Jun 28, 2012 at 4:35 PM, Oliver Neukum <oneukum@suse.de> wrote:
> Am Dienstag, 26. Juni 2012, 09:23:19 schrieb Ming Lei:

>> IMO, probe is serialized strictly with driver unbind since both the parent
>> lock and its own device lock have been held, so the probe may only be
>> started after driver unbinding is completed.
>
> Yes, but if you have a driver which claims multiple interfaces and uses
> a subdriver, then you will have cases of intfdate being NULL before

We have no such case now.

> disconnect() finishes.

Suppose cdc-ether will support subdriver, ->unbind will set NULL to
the 2nd interface and release the 2nd interface, then subdriver->disconnect()
will be called, looks still no any problem.


Thanks,
-- 
Ming Lei

^ permalink raw reply

* Re: LOCKDEP complaints in l2tp_xmit_skb()
From: Eric Dumazet @ 2012-06-28  8:57 UTC (permalink / raw)
  To: Tom Parkin, David Miller; +Cc: netdev
In-Reply-To: <1340866572.26242.312.camel@edumazet-glaptop>

On Thu, 2012-06-28 at 08:56 +0200, Eric Dumazet wrote:

> [PATCH] net: Qdisc busylock gets its own lockdep class
> 
> Tom Parkin reported following LOCKDEP splat :
..
> 
> Instruct lockdep that each Qdisc busylock is independant, or else
> bonding or various tunnels can trigger a splat.
> 
> Reported-by: Tom Parkin <tparkin@katalix.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---

I reproduced the bug using a bond0 device, adding a qdisc on it,
(one Qdisc on bond0, and a Qdisc on the slave too)

Problem with this patch is I have following message :

BUG: key ffff88..... not in .data!

No more LOCKDEP splat, but patch not good as is.

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
From: Bjørn Mork @ 2012-06-28  8:55 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Ming Lei, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Marius Bjørnstad Kotsbak
In-Reply-To: <201206281035.19964.oneukum-l3A5Bk7waGM@public.gmane.org>

Oliver Neukum <oneukum-l3A5Bk7waGM@public.gmane.org> writes:

> Am Dienstag, 26. Juni 2012, 09:23:19 schrieb Ming Lei:
>> On Mon, Jun 25, 2012 at 8:10 PM, Oliver Neukum <oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org> wrote:
>
>> > At this point a minidriver must not follow the intfdata pointer,
>> > because the interface may again be probed. So if here a minidriver
>> 
>> IMO, probe is serialized strictly with driver unbind since both the parent
>> lock and its own device lock have been held, so the probe may only be
>> started after driver unbinding is completed.
>
> Yes, but if you have a driver which claims multiple interfaces and uses
> a subdriver, then you will have cases of intfdate being NULL before
> disconnect() finishes.

This is true regardless of subdriver, isn't it?  The subdriver issue is
special because it makes this a potentional problem even with a single
interface.

>> > still uses intfdata, locking will be needed. We want to catch those
>> > casees.
>> 
>> Suppose infdata is used here somewhere, it is surely a bug because
>> the usbnet instance pointed by intfdata will be freed soon.
>
> Of course. That is the point.
>
>> So looks putting the set to NULL after driver_info->unbind is good,
>> doesn't it?
>
> Again, of course. We could drop it (but not the check for NULL in usbnet).
> It is a debugging aid. 
>
>> >        usb_kill_urb(dev->interrupt);
>> >        usb_free_urb(dev->interrupt);
>> >
>> >        free_netdev(net);
>> >        usb_put_dev (xdev);
>> > }
>> >
>> >> > Sure, it is a debugging aid. It has the drawback that minidrivers have
>> >> > to be able to deal with intfdata being NULL. That is not hard to do.
>> >>
>> >> The check isn't needed if the set to NULL is put after  driver_info->unbind
>> >> in usbnet_disconnect.
>> >
>> > True, but we don't catch bugs.
>> 
>> If the check is added, the bugs may be hided, and no stack will be
>> dumped, :-)
>
> That is also true.
>
> Bjørn,
>
> do you use subdrivers with cdc-ether?

No, and I don't think it should ever be added there.  It would add
complexity to the driver, and IMHO we really don't want that for the
generic cdc-ether. Better adding a new minidriver if the need to export
some other CDC embedded protocol to userspace shows up.

But given that all other embedded protocol examples I've seen are so
simple that they've been implemented inside their repective minidrivers
(sierra_net, hso, rndis_host), I don't think it's likely that any new
need for the cdc-wdm subdriver will show up soon.  I could of course be
completely wrong, as usual.


Bjørn
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH v2] l2tp: use per-cpu variables for u64_stats updates
From: David Laight @ 2012-06-28  8:46 UTC (permalink / raw)
  To: Eric Dumazet, Rick Jones
  Cc: Ben Greear, Stephen Hemminger, Tom Parkin, netdev, James Chapman
In-Reply-To: <1340859654.26242.201.camel@edumazet-glaptop>

 
> [1] : LLTX drivers case 
>    since ndo_start_xmit() can be run concurrently by many cpus, safely
> updating an "unsigned long" requires additional hassle :
> 
>    1) Use of a spinlock to protect the update.
>    2) Use atomic_long_t instead of "unsigned long"
>    3) Use percpu data

4) These are statistics so it shouldn't really matter if
   they are out by a small number.  So the errors
   introduced by unlocked updates can probably be ignored.
   So just use 'unsigned long'.

   Might be worth putting in gcc barriers so that the
   load and store instructions aren't separated too far.

	David

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
From: Oliver Neukum @ 2012-06-28  8:40 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: David Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Ming Lei,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Marius Bjørnstad Kotsbak
In-Reply-To: <87lij7de8u.fsf-lbf33ChDnrE/G1V5fR+Y7Q@public.gmane.org>

Am Donnerstag, 28. Juni 2012, 10:36:49 schrieb Bjørn Mork:
> Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org> writes:
> 
> [..]
> > Fixes this Oops where a cdc-wdm device was closed while the
> > USB device was disconnecting, causing wdm_release to call
> > qmi_wwan_cdc_wdm_manage_power after intfdata was set to
> > NULL by usbnet_disconnect:
> >
> > [41819.087460] BUG: unable to handle kernel NULL pointer dereference at 00000080
> > [41819.087815] IP: [<f8640458>] qmi_wwan_manage_power+0x68/0x90 [qmi_wwan]
> > [41819.088028] *pdpt = 000000000314f001 *pde = 0000000000000000
> > [41819.088028] Oops: 0002 [#1] SMP
> 
> [..]
> 
> > diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> > index 3767a12..b01960f 100644
> > --- a/drivers/net/usb/qmi_wwan.c
> > +++ b/drivers/net/usb/qmi_wwan.c
> > @@ -197,6 +197,10 @@ err:
> >  static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
> >  {
> >  	struct usbnet *dev = usb_get_intfdata(intf);
> > +
> > +	/* can be called while disconnecting */
> > +	if (!dev)
> > +		return 0;
> >  	return qmi_wwan_manage_power(dev, on);
> >  }
> 
> Hello,
> 
> I'd like this patch applied to qmi_wwan regardless of the outcome of the
> (now stalled?) generic usbnet_disconnect discussion.
> 
> The patch fixes a real Oops in 3.4 and 3.5, and I believe it should be
> left in qmi_wwan even if the usbnet code is fixed to avoid this specific
> bug.  The additional NULL test won't harm, and it makes the code more
> robust should someone decide to rearrange usbnet_disconnect again at
> some later point in time.
> 
> I really want this fixed in the next 3.4 stable release, if possible.
> Should I resubmit the patch, or will you pick it up from
> http://patchwork.ozlabs.org/patch/166542/ ?

Yes.

David, can you please apply this? It needs to also go into stable.
We might remove this in later releases, but for now it is needed.

	Regards
		Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
From: Bjørn Mork @ 2012-06-28  8:36 UTC (permalink / raw)
  To: David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Oliver Neukum, Ming Lei,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Marius Bjørnstad Kotsbak
In-Reply-To: <1340356279-3124-1-git-send-email-bjorn-yOkvZcmFvRU@public.gmane.org>

Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org> writes:

[..]
> Fixes this Oops where a cdc-wdm device was closed while the
> USB device was disconnecting, causing wdm_release to call
> qmi_wwan_cdc_wdm_manage_power after intfdata was set to
> NULL by usbnet_disconnect:
>
> [41819.087460] BUG: unable to handle kernel NULL pointer dereference at 00000080
> [41819.087815] IP: [<f8640458>] qmi_wwan_manage_power+0x68/0x90 [qmi_wwan]
> [41819.088028] *pdpt = 000000000314f001 *pde = 0000000000000000
> [41819.088028] Oops: 0002 [#1] SMP

[..]

> diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> index 3767a12..b01960f 100644
> --- a/drivers/net/usb/qmi_wwan.c
> +++ b/drivers/net/usb/qmi_wwan.c
> @@ -197,6 +197,10 @@ err:
>  static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
>  {
>  	struct usbnet *dev = usb_get_intfdata(intf);
> +
> +	/* can be called while disconnecting */
> +	if (!dev)
> +		return 0;
>  	return qmi_wwan_manage_power(dev, on);
>  }

Hello,

I'd like this patch applied to qmi_wwan regardless of the outcome of the
(now stalled?) generic usbnet_disconnect discussion.

The patch fixes a real Oops in 3.4 and 3.5, and I believe it should be
left in qmi_wwan even if the usbnet code is fixed to avoid this specific
bug.  The additional NULL test won't harm, and it makes the code more
robust should someone decide to rearrange usbnet_disconnect again at
some later point in time.

I really want this fixed in the next 3.4 stable release, if possible.
Should I resubmit the patch, or will you pick it up from
http://patchwork.ozlabs.org/patch/166542/ ?


Thanks,
Bjørn
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: fix Oops while disconnecting
From: Oliver Neukum @ 2012-06-28  8:35 UTC (permalink / raw)
  To: Ming Lei
  Cc: Bjørn Mork, netdev, linux-usb, Marius Bjørnstad Kotsbak
In-Reply-To: <CACVXFVO5x9pePZekJPnywr7czXG_3_xCRj-rXEgf2KSQXnmPbA@mail.gmail.com>

Am Dienstag, 26. Juni 2012, 09:23:19 schrieb Ming Lei:
> On Mon, Jun 25, 2012 at 8:10 PM, Oliver Neukum <oliver@neukum.org> wrote:

> > At this point a minidriver must not follow the intfdata pointer,
> > because the interface may again be probed. So if here a minidriver
> 
> IMO, probe is serialized strictly with driver unbind since both the parent
> lock and its own device lock have been held, so the probe may only be
> started after driver unbinding is completed.

Yes, but if you have a driver which claims multiple interfaces and uses
a subdriver, then you will have cases of intfdate being NULL before
disconnect() finishes.

> > still uses intfdata, locking will be needed. We want to catch those
> > casees.
> 
> Suppose infdata is used here somewhere, it is surely a bug because
> the usbnet instance pointed by intfdata will be freed soon.

Of course. That is the point.

> So looks putting the set to NULL after driver_info->unbind is good,
> doesn't it?

Again, of course. We could drop it (but not the check for NULL in usbnet).
It is a debugging aid. 

> >        usb_kill_urb(dev->interrupt);
> >        usb_free_urb(dev->interrupt);
> >
> >        free_netdev(net);
> >        usb_put_dev (xdev);
> > }
> >
> >> > Sure, it is a debugging aid. It has the drawback that minidrivers have
> >> > to be able to deal with intfdata being NULL. That is not hard to do.
> >>
> >> The check isn't needed if the set to NULL is put after  driver_info->unbind
> >> in usbnet_disconnect.
> >
> > True, but we don't catch bugs.
> 
> If the check is added, the bugs may be hided, and no stack will be
> dumped, :-)

That is also true.

Bjørn,

do you use subdrivers with cdc-ether?

	Regards
		Oliver

-- 
- - - 
SUSE LINUX Products GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB 16746 (AG Nürnberg) 
Maxfeldstraße 5                         
90409 Nürnberg 
Germany 
- - - 

^ permalink raw reply

* Re: [patch net-next] virtio_net: allow to change mac when iface is running
From: David Miller @ 2012-06-28  8:30 UTC (permalink / raw)
  To: jpirko; +Cc: netdev, virtualization, brouer, mst
In-Reply-To: <20120628063525.GA1520@minipsycho.orion>

From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 28 Jun 2012 08:35:25 +0200

> Thu, Jun 28, 2012 at 06:30:46AM CEST, davem@davemloft.net wrote:
>>It therefore probably makes sense to add a boolean arg which when true
>>elides the netif_running() check then fixup and audit every caller.
> 
> I was thinking about this. Maybe probably __eth_mac_addr() which does
> not have netif_running() check and eth_mac_addr() calling
> netif_running() check and __eth_mac_addr() after that.
> 
> What do you think?

Yes, sounds good.

^ permalink raw reply

* Re: [PATCH v2] l2tp: use per-cpu variables for u64_stats updates
From: Tom Parkin @ 2012-06-28  8:24 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Rick Jones, Ben Greear, Stephen Hemminger, netdev, David.Laight,
	James Chapman
In-Reply-To: <1340859654.26242.201.camel@edumazet-glaptop>

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

On Thu, Jun 28, 2012 at 07:00:54AM +0200, Eric Dumazet wrote:
> [1] : LLTX drivers case 
>    since ndo_start_xmit() can be run concurrently by many cpus, safely
> updating an "unsigned long" requires additional hassle :
> 
>    1) Use of a spinlock to protect the update.
>    2) Use atomic_long_t instead of "unsigned long"
>    3) Use percpu data
> 
> 3) is overkill for devices with light traffic, because it consumes lot
> of RAM on machines with 2048 possible cpus, _and_ the reader must fold
> the data of all possible values.

Thanks Eric.

So am I right in thinking that a v3 patch which uses atomic_long_t for
the statistics would be the correct way forwards?

-- 
Tom Parkin
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: [net-next PATCH 02/02] net/ipv4: VTI support new module for ip_vti.
From: Steffen Klassert @ 2012-06-28  8:04 UTC (permalink / raw)
  To: Saurabh; +Cc: netdev
In-Reply-To: <20120628010218.GA4056@debian-saurabh-64.vyatta.com>

On Wed, Jun 27, 2012 at 06:02:18PM -0700, Saurabh wrote:
> 
> +config NET_IPVTI
> +	tristate "Virtual (secure) IP: tunneling"
> +	select INET_TUNNEL
> +	depends on INET_XFRM_MODE_TUNNEL
> +	---help---
> +	Tunneling means encapsulating data of one protocol type within
> +	another protocol and sending it over a channel that understands the
> +	Pencapsulating protocol. This particular tunneling driver implements
> +	encapsulation of IP within IP-ESP. This can be used with xfrm to give

This is not ESP specific anymore.

> +	the notion of a secure tunnel and then use routing protocol on top.
> +
> +	Saying Y to this option will produce one module ( = code which can
> +	be inserted in and removed from the running kernel whenever you
> +	want). Most people won't need this and can say N.
> +

Saying Y does not build a module, saying M builds a module. Also,
even if build as a module, you can't remove it whenever you want.
You can remove it as long as it is unused.

...

> +static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct ip_tunnel *tunnel = netdev_priv(dev);
> +	struct pcpu_tstats *tstats;
> +	struct net_device_stats *stats = &tunnel->dev->stats;
> +	struct iphdr  *tiph = &tunnel->parms.iph;
> +	u8     tos = tunnel->parms.iph.tos;
> +	struct rtable *rt;		/* Route to the other host */
> +	struct net_device *tdev;	/* Device to other host */
> +	struct iphdr  *old_iph = ip_hdr(skb);
> +	__be32 dst = tiph->daddr;
> +	struct flowi4 fl4;
> +
> +	if (skb->protocol != htons(ETH_P_IP))
> +		goto tx_error;
> +
> +	if (tos&1)
> +		tos = old_iph->tos;
> +
> +	if (!dst) {
> +		/* NBMA tunnel */
> +		rt = skb_rtable(skb);
> +		if (rt == NULL) {
> +			stats->tx_fifo_errors++;
> +			goto tx_error;
> +		}
> +		dst = rt->rt_gateway;
> +		if (dst == 0)
> +			goto tx_error_icmp;
> +	}
> +
> +	memset(&fl4, 0, sizeof(fl4));
> +	flowi4_init_output(&fl4, tunnel->parms.link,
> +		htonl(tunnel->parms.i_key), RT_TOS(tos), RT_SCOPE_UNIVERSE,
> +		IPPROTO_IPIP, 0,
> +		dst, tiph->saddr, 0, 0);
> +	rt = ip_route_output_key(dev_net(dev), &fl4);
> +	if (IS_ERR(rt)) {
> +		dev->stats.tx_carrier_errors++;
> +		goto tx_error_icmp;
> +	}
> +#ifdef CONFIG_XFRM
> +		/* if there is no transform then this tunnel is not functional. */
> +		if (!rt->dst.xfrm) {

What if this is a transport mode xfrm?
You should ensure that this is really a tunnel mode xfrm.

> +			stats->tx_carrier_errors++;
> +			goto tx_error_icmp;
> +		}
> +#endif

^ permalink raw reply

* Re: [PATCH] xfrm_user: Propagate netlink error codes properly.
From: Thomas Graf @ 2012-06-28  7:40 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120627.215728.137770920620706227.davem@davemloft.net>

On Wed, Jun 27, 2012 at 09:57:28PM -0700, David Miller wrote:
> 
> Instead of using a fixed value of "-1" or "-EMSGSIZE", propagate what
> the nla_*() interfaces actually return.
> 
> Signed-off-by: David S. Miller <davem@davemloft.net>

Reviewed-by: Thomas Graf <tgraf@suug.ch>

^ permalink raw reply

* [net-next.git 4/4 (v9)] phy: add the EEE support and the way to access to the MMD registers.
From: Giuseppe CAVALLARO @ 2012-06-28  7:14 UTC (permalink / raw)
  To: netdev
  Cc: eric.dumazet, rayagond, davem, yuvalmin, bhutchings,
	Giuseppe Cavallaro
In-Reply-To: <1340867678-18375-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the support for the Energy-Efficient Ethernet (EEE)
to the Physical Abstraction Layer.
To support the EEE we have to access to the MMD registers 3.20 and
7.60/61. So two new functions have been added to read/write the MMD
registers (clause 45).

An Ethernet driver (I tested the stmmac) can invoke the phy_init_eee to properly
check if the EEE is supported by the PHYs and it can also set the clock
stop enable bit in the 3.0 register.
The phy_get_eee_err can be used for reporting the number of time where
the PHY failed to complete its normal wake sequence.

In the end, this patch also adds the EEE ethtool support implementing:
 o phy_ethtool_set_eee
 o phy_ethtool_get_eee

v1: initial patch
v2: fixed some errors especially on naming convention
v3: renamed again the mmd read/write functions thank to Ben's feedback
v4: moved file to phy.c and added the ethtool support.
v5: fixed phy_adv_to_eee, phy_eee_to_supported, phy_eee_to_adv return
    values according to ethtool API (thanks to Ben's feedback).
    Renamed some macros to avoid too long names.
v6: fixed kernel-doc comments to be properly parsed.
    Fixed the phy_init_eee function: we need to check which link mode
    was autonegotiated and then the corresponding bits in 7.60 and 7.61
    registers.
v7: reviewed the way to get the negotiated settings.
v8: fixed a problem in the phy_init_eee return value erroneously added
    when included the phy_read_status call.
v9: do not remove the MDIO_AN_EEE_ADV_100TX and MDIO_AN_EEE_ADV_1000T
    and fixed the eee_{cap,lp,adv} declaration as "int" instead of u16.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/phy/phy.c |  281 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mdio.h  |   28 ++++-
 include/linux/mii.h   |    9 ++
 include/linux/phy.h   |    5 +
 4 files changed, 319 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2e1c237..7ca2ff9 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -35,6 +35,7 @@
 #include <linux/phy.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/mdio.h>
 
 #include <linux/atomic.h>
 #include <asm/io.h>
@@ -967,3 +968,283 @@ void phy_state_machine(struct work_struct *work)
 
 	schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
 }
+
+static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
+				    int addr)
+{
+	/* Write the desired MMD Devad */
+	bus->write(bus, addr, MII_MMD_CTRL, devad);
+
+	/* Write the desired MMD register address */
+	bus->write(bus, addr, MII_MMD_DATA, prtad);
+
+	/* Select the Function : DATA with no post increment */
+	bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
+}
+
+/**
+ * phy_read_mmd_indirect - reads data from the MMD registers
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ *
+ * Description: it reads data from the MMD registers (clause 22 to access to
+ * clause 45) of the specified phy address.
+ * To read these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Read  reg 14 // Read MMD data
+ */
+static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+				 int addr)
+{
+	u32 ret;
+
+	mmd_phy_indirect(bus, prtad, devad, addr);
+
+	/* Read the content of the MMD's selected register */
+	ret = bus->read(bus, addr, MII_MMD_DATA);
+
+	return ret;
+}
+
+/**
+ * phy_write_mmd_indirect - writes data to the MMD registers
+ * @bus: the target MII bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ * @data: data to write in the MMD register
+ *
+ * Description: Write data from the MMD registers of the specified
+ * phy address.
+ * To write these register we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Write reg 14 // Write MMD data
+ */
+static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
+				   int addr, u32 data)
+{
+	mmd_phy_indirect(bus, prtad, devad, addr);
+
+	/* Write the data into MMD's selected register */
+	bus->write(bus, addr, MII_MMD_DATA, data);
+}
+
+static u32 phy_eee_to_adv(u16 eee_adv)
+{
+	u32 adv = 0;
+
+	if (eee_adv & MDIO_EEE_100TX)
+		adv |= ADVERTISED_100baseT_Full;
+	if (eee_adv & MDIO_EEE_1000T)
+		adv |= ADVERTISED_1000baseT_Full;
+	if (eee_adv & MDIO_EEE_10GT)
+		adv |= ADVERTISED_10000baseT_Full;
+	if (eee_adv & MDIO_EEE_1000KX)
+		adv |= ADVERTISED_1000baseKX_Full;
+	if (eee_adv & MDIO_EEE_10GKX4)
+		adv |= ADVERTISED_10000baseKX4_Full;
+	if (eee_adv & MDIO_EEE_10GKR)
+		adv |= ADVERTISED_10000baseKR_Full;
+
+	return adv;
+}
+
+static u32 phy_eee_to_supported(u16 eee_caported)
+{
+	u32 supported = 0;
+
+	if (eee_caported & MDIO_EEE_100TX)
+		supported |= SUPPORTED_100baseT_Full;
+	if (eee_caported & MDIO_EEE_1000T)
+		supported |= SUPPORTED_1000baseT_Full;
+	if (eee_caported & MDIO_EEE_10GT)
+		supported |= SUPPORTED_10000baseT_Full;
+	if (eee_caported & MDIO_EEE_1000KX)
+		supported |= SUPPORTED_1000baseKX_Full;
+	if (eee_caported & MDIO_EEE_10GKX4)
+		supported |= SUPPORTED_10000baseKX4_Full;
+	if (eee_caported & MDIO_EEE_10GKR)
+		supported |= SUPPORTED_10000baseKR_Full;
+
+	return supported;
+}
+
+static u16 phy_adv_to_eee(u32 adv)
+{
+	u16 reg = 0;
+
+	if (adv & ADVERTISED_100baseT_Full)
+		reg |= MDIO_EEE_100TX;
+	if (adv & ADVERTISED_1000baseT_Full)
+		reg |= MDIO_EEE_1000T;
+	if (adv & ADVERTISED_10000baseT_Full)
+		reg |= MDIO_EEE_10GT;
+	if (adv & ADVERTISED_1000baseKX_Full)
+		reg |= MDIO_EEE_1000KX;
+	if (adv & ADVERTISED_10000baseKX4_Full)
+		reg |= MDIO_EEE_10GKX4;
+	if (adv & ADVERTISED_10000baseKR_Full)
+		reg |= MDIO_EEE_10GKR;
+
+	return reg;
+}
+
+/**
+ * phy_init_eee - init and check the EEE feature
+ * @phydev: target phy_device struct
+ * @clk_stop_enable: PHY may stop the clock during LPI
+ *
+ * Description: it checks if the Energy-Efficient Ethernet (EEE)
+ * is supported by looking at the MMD registers 3.20 and 7.60/61
+ * and it programs the MMD register 3.0 setting the "Clock stop enable"
+ * bit if required.
+ */
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
+{
+	int ret = -EPROTONOSUPPORT;
+
+	/* According to 802.3az,the EEE is supported only in full duplex-mode.
+	 * Also EEE feature is active when core is operating with MII, GMII
+	 * or RGMII.
+	 */
+	if ((phydev->duplex == DUPLEX_FULL) &&
+	    ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
+		int eee_lp, eee_cap, eee_adv;
+		u32 lp, cap, adv;
+		int idx, status;
+
+		/* Read phy status to properly get the right settings */
+		status = phy_read_status(phydev);
+		if (status)
+			return status;
+
+		/* First check if the EEE ability is supported */
+		eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+						MDIO_MMD_PCS, phydev->addr);
+		if (eee_cap < 0)
+			return eee_cap;
+
+		cap = phy_eee_to_supported(eee_cap);
+		if (!cap)
+			goto eee_exit;
+
+		/* Check which link settings negotiated and verify it in
+		 * the EEE advertising registers.
+		 */
+		eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+					       MDIO_MMD_AN, phydev->addr);
+		if (eee_lp < 0)
+			return eee_lp;
+
+		eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+						MDIO_MMD_AN, phydev->addr);
+		if (eee_adv < 0)
+			return eee_adv;
+
+		adv = phy_eee_to_adv(eee_adv);
+		lp = phy_eee_to_adv(eee_lp);
+		idx = phy_find_setting(phydev->speed, phydev->duplex);
+		if ((lp & adv & settings[idx].setting))
+			goto eee_exit;
+
+		if (clk_stop_enable) {
+			/* Configure the PHY to stop receiving xMII
+			 * clock while it is signaling LPI.
+			 */
+			int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
+							MDIO_MMD_PCS,
+							phydev->addr);
+			if (val < 0)
+				return val;
+
+			val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
+			phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
+					       MDIO_MMD_PCS, phydev->addr, val);
+		}
+
+		ret = 0; /* EEE supported */
+	}
+
+eee_exit:
+	return ret;
+}
+EXPORT_SYMBOL(phy_init_eee);
+
+/**
+ * phy_get_eee_err - report the EEE wake error count
+ * @phydev: target phy_device struct
+ *
+ * Description: it is to report the number of time where the PHY
+ * failed to complete its normal wake sequence.
+ */
+int phy_get_eee_err(struct phy_device *phydev)
+{
+	return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
+				     MDIO_MMD_PCS, phydev->addr);
+
+}
+EXPORT_SYMBOL(phy_get_eee_err);
+
+/**
+ * phy_ethtool_get_eee - get EEE supported and status
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reportes the Supported/Advertisement/LP Advertisement
+ * capabilities.
+ */
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+	int val;
+
+	/* Get Supported EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+				    MDIO_MMD_PCS, phydev->addr);
+	if (val < 0)
+		return val;
+	data->supported = phy_eee_to_supported(val);
+
+	/* Get advertisement EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+	data->advertised = phy_eee_to_adv(val);
+
+	/* Get LP advertisement EEE */
+	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+	data->lp_advertised = phy_eee_to_adv(val);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_get_eee);
+
+/**
+ * phy_ethtool_set_eee - set EEE supported and status
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it is to program the Advertisement EEE register.
+ */
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+	int val;
+
+	val = phy_adv_to_eee(data->advertised);
+	phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
+			       phydev->addr, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_ethtool_set_eee);
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index dfb9479..7cccafe 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -43,7 +43,11 @@
 #define MDIO_PKGID2		15
 #define MDIO_AN_ADVERTISE	16	/* AN advertising (base page) */
 #define MDIO_AN_LPA		19	/* AN LP abilities (base page) */
+#define MDIO_PCS_EEE_ABLE	20	/* EEE Capability register */
+#define MDIO_PCS_EEE_WK_ERR	22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
+#define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
+#define MDIO_AN_EEE_LPABLE	61	/* EEE link partner ability */
 
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
@@ -56,7 +60,6 @@
 #define MDIO_PCS_10GBRT_STAT2	33	/* 10GBASE-R/-T PCS status 2 */
 #define MDIO_AN_10GBT_CTRL	32	/* 10GBASE-T auto-negotiation control */
 #define MDIO_AN_10GBT_STAT	33	/* 10GBASE-T auto-negotiation status */
-#define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
 
 /* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
 #define MDIO_PMA_LASI_RXCTRL	0x9000	/* RX_ALARM control */
@@ -82,6 +85,7 @@
 #define MDIO_AN_CTRL1_RESTART		BMCR_ANRESTART
 #define MDIO_AN_CTRL1_ENABLE		BMCR_ANENABLE
 #define MDIO_AN_CTRL1_XNP		0x2000	/* Enable extended next page */
+#define MDIO_PCS_CTRL1_CLKSTOP_EN	0x400	/* Stop the clock during LPI */
 
 /* 10 Gb/s */
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
@@ -237,9 +241,25 @@
 #define MDIO_AN_10GBT_STAT_MS		0x4000	/* Master/slave config */
 #define MDIO_AN_10GBT_STAT_MSFLT	0x8000	/* Master/slave config fault */
 
-/* AN EEE Advertisement register. */
-#define MDIO_AN_EEE_ADV_100TX		0x0002	/* Advertise 100TX EEE cap */
-#define MDIO_AN_EEE_ADV_1000T		0x0004	/* Advertise 1000T EEE cap */
+/* EEE Supported/Advertisement/LP Advertisement registers.
+ *
+ * EEE capability Register (3.20), Advertisement (7.60) and
+ * Link partner ability (7.61) registers have and can use the same identical
+ * bit masks.
+ */
+#define MDIO_AN_EEE_ADV_100TX	0x0002	/* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T	0x0004	/* Advertise 1000T EEE cap */
+/* Note: the two defines above can be potentially used by the user-land
+ * and cannot remove them now.
+ * So, we define the new generic MDIO_EEE_100TX and MDIO_EEE_1000T macros
+ * using the previous ones (that can be considered obsolete).
+ */
+#define MDIO_EEE_100TX		MDIO_AN_EEE_ADV_100TX	/* 100TX EEE cap */
+#define MDIO_EEE_1000T		MDIO_AN_EEE_ADV_1000T	/* 1000T EEE cap */
+#define MDIO_EEE_10GT		0x0008	/* 10GT EEE cap */
+#define MDIO_EEE_1000KX		0x0010	/* 1000KX EEE cap */
+#define MDIO_EEE_10GKX4		0x0020	/* 10G KX4 EEE cap */
+#define MDIO_EEE_10GKR		0x0040	/* 10G KR EEE cap */
 
 /* LASI RX_ALARM control/status registers. */
 #define MDIO_PMA_LASI_RX_PHYXSLFLT	0x0001	/* PHY XS RX local fault */
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 2783eca..8ef3a7a 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -21,6 +21,8 @@
 #define MII_EXPANSION		0x06	/* Expansion register          */
 #define MII_CTRL1000		0x09	/* 1000BASE-T control          */
 #define MII_STAT1000		0x0a	/* 1000BASE-T status           */
+#define	MII_MMD_CTRL		0x0d	/* MMD Access Control Register */
+#define	MII_MMD_DATA		0x0e	/* MMD Access Data Register */
 #define MII_ESTATUS		0x0f	/* Extended Status             */
 #define MII_DCOUNTER		0x12	/* Disconnect counter          */
 #define MII_FCSCOUNTER		0x13	/* False carrier counter       */
@@ -141,6 +143,13 @@
 #define FLOW_CTRL_TX		0x01
 #define FLOW_CTRL_RX		0x02
 
+/* MMD Access Control register fields */
+#define MII_MMD_CTRL_DEVAD_MASK	0x1f	/* Mask MMD DEVAD*/
+#define MII_MMD_CTRL_ADDR	0x0000	/* Address */
+#define MII_MMD_CTRL_NOINCR	0x4000	/* no post increment */
+#define MII_MMD_CTRL_INCR_RDWT	0x8000	/* post increment on reads & writes */
+#define MII_MMD_CTRL_INCR_ON_WT	0xC000	/* post increment on writes only */
+
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
 struct mii_ioctl_data {
 	__u16		phy_id;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7eac80a..c35299e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -554,6 +554,11 @@ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
 		int (*run)(struct phy_device *));
 int phy_scan_fixups(struct phy_device *phydev);
 
+int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
+int phy_get_eee_err(struct phy_device *phydev);
+int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
+int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
+
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
 
-- 
1.7.4.4

^ permalink raw reply related

* [net-next.git 3/4 (v5)] stmmac: add the Energy Efficient Ethernet support
From: Giuseppe CAVALLARO @ 2012-06-28  7:14 UTC (permalink / raw)
  To: netdev
  Cc: eric.dumazet, rayagond, davem, yuvalmin, bhutchings,
	Giuseppe Cavallaro
In-Reply-To: <1340867678-18375-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the Energy Efficient Ethernet support to the stmmac.

Please see the driver's documentation for further details about this support
in the driver.

Thanks also goes to Rayagond Kokatanur for his first implementation.

Note:
 to clearly manage and expose the lpi interrupt status and eee ethtool
 stats I've had to do some modifications to the driver's design and I
 found really useful to move other parts of the code (e.g. mmc irq stat)
 in the main directly. So this means that some core has been reworked
 to introduce the EEE.

v1: initial patch
v2: fixed some sparse issues (typos)
v3: erroneously sent the v2 renamed as v3
v4:
	o Fixed the return value of the stmmac_eee_init as suggested by D.Miller
	o Totally reviewed the ethtool support for EEE
	o Added a new internal parameter to tune the SW timer for TX LPI.
v5: do not change any eee setting in case of the stmmac_ethtool_op_set_eee fails
    (it has to return -EOPNOTSUPP in that case).

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/common.h       |   31 ++++-
 drivers/net/ethernet/stmicro/stmmac/dwmac1000.h    |   20 +++
 .../net/ethernet/stmicro/stmmac/dwmac1000_core.c   |  101 +++++++++++-
 .../net/ethernet/stmicro/stmmac/dwmac100_core.c    |    4 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h    |    1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |    8 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   57 +++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  166 +++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 9 files changed, 372 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index bcd54d6..e2d0832 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -95,6 +95,16 @@ struct stmmac_extra_stats {
 	unsigned long poll_n;
 	unsigned long sched_timer_n;
 	unsigned long normal_irq_n;
+	unsigned long mmc_tx_irq_n;
+	unsigned long mmc_rx_irq_n;
+	unsigned long mmc_rx_csum_offload_irq_n;
+	/* EEE */
+	unsigned long irq_receive_pmt_irq_n;
+	unsigned long irq_tx_path_in_lpi_mode_n;
+	unsigned long irq_tx_path_exit_lpi_mode_n;
+	unsigned long irq_rx_path_in_lpi_mode_n;
+	unsigned long irq_rx_path_exit_lpi_mode_n;
+	unsigned long phy_eee_wakeup_error_n;
 };
 
 /* CSR Frequency Access Defines*/
@@ -162,6 +172,17 @@ enum tx_dma_irq_status {
 	handle_tx_rx = 3,
 };
 
+enum core_specific_irq_mask {
+	core_mmc_tx_irq = 1,
+	core_mmc_rx_irq = 2,
+	core_mmc_rx_csum_offload_irq = 4,
+	core_irq_receive_pmt_irq = 8,
+	core_irq_tx_path_in_lpi_mode = 16,
+	core_irq_tx_path_exit_lpi_mode = 32,
+	core_irq_rx_path_in_lpi_mode = 64,
+	core_irq_rx_path_exit_lpi_mode = 128,
+};
+
 /* DMA HW capabilities */
 struct dma_features {
 	unsigned int mbps_10_100;
@@ -208,6 +229,10 @@ struct dma_features {
 #define MAC_ENABLE_TX		0x00000008	/* Transmitter Enable */
 #define MAC_RNABLE_RX		0x00000004	/* Receiver Enable */
 
+/* Default LPI timers */
+#define STMMAC_DEFAULT_LIT_LS_TIMER	0x3E8
+#define STMMAC_DEFAULT_TWT_LS_TIMER	0x0
+
 struct stmmac_desc_ops {
 	/* DMA RX descriptor ring initialization */
 	void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
@@ -278,7 +303,7 @@ struct stmmac_ops {
 	/* Dump MAC registers */
 	void (*dump_regs) (void __iomem *ioaddr);
 	/* Handle extra events on specific interrupts hw dependent */
-	void (*host_irq_status) (void __iomem *ioaddr);
+	int (*host_irq_status) (void __iomem *ioaddr);
 	/* Multicast filter setting */
 	void (*set_filter) (struct net_device *dev, int id);
 	/* Flow control setting */
@@ -291,6 +316,10 @@ struct stmmac_ops {
 			       unsigned int reg_n);
 	void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
 			       unsigned int reg_n);
+	void (*set_eee_mode) (void __iomem *ioaddr);
+	void (*reset_eee_mode) (void __iomem *ioaddr);
+	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
+	void (*set_eee_pls) (void __iomem *ioaddr, int link);
 };
 
 struct mac_link {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 23478bf..f90fcb5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -36,6 +36,7 @@
 
 #define GMAC_INT_STATUS		0x00000038	/* interrupt status register */
 enum dwmac1000_irq_status {
+	lpiis_irq = 0x400,
 	time_stamp_irq = 0x0200,
 	mmc_rx_csum_offload_irq = 0x0080,
 	mmc_tx_irq = 0x0040,
@@ -60,6 +61,25 @@ enum power_event {
 	power_down = 0x00000001,
 };
 
+/* Energy Efficient Ethernet (EEE)
+ *
+ * LPI status, timer and control register offset
+ */
+#define LPI_CTRL_STATUS	0x0030
+#define LPI_TIMER_CTRL	0x0034
+
+/* LPI control and status defines */
+#define LPI_CTRL_STATUS_LPITXA	0x00080000	/* Enable LPI TX Automate */
+#define LPI_CTRL_STATUS_PLSEN	0x00040000	/* Enable PHY Link Status */
+#define LPI_CTRL_STATUS_PLS	0x00020000	/* PHY Link Status */
+#define LPI_CTRL_STATUS_LPIEN	0x00010000	/* LPI Enable */
+#define LPI_CTRL_STATUS_RLPIST	0x00000200	/* Receive LPI state */
+#define LPI_CTRL_STATUS_TLPIST	0x00000100	/* Transmit LPI state */
+#define LPI_CTRL_STATUS_RLPIEX	0x00000008	/* Receive LPI Exit */
+#define LPI_CTRL_STATUS_RLPIEN	0x00000004	/* Receive LPI Entry */
+#define LPI_CTRL_STATUS_TLPIEX	0x00000002	/* Transmit LPI Exit */
+#define LPI_CTRL_STATUS_TLPIEN	0x00000001	/* Transmit LPI Entry */
+
 /* GMAC HW ADDR regs */
 #define GMAC_ADDR_HIGH(reg)	(((reg > 15) ? 0x00000800 : 0x00000040) + \
 				(reg * 8))
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b5e4d02..bfe0226 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -194,26 +194,107 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
 }
 
 
-static void dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr)
 {
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+	int status = 0;
 
 	/* Not used events (e.g. MMC interrupts) are not handled. */
-	if ((intr_status & mmc_tx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
+	if ((intr_status & mmc_tx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_TX_INTR));
-	if (unlikely(intr_status & mmc_rx_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
+		status |= core_mmc_tx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_INTR));
-	if (unlikely(intr_status & mmc_rx_csum_offload_irq))
-		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
+		status |= core_mmc_rx_irq;
+	}
+	if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+		status |= core_mmc_rx_csum_offload_irq;
+	}
 	if (unlikely(intr_status & pmt_irq)) {
-		CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
+		CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
 		/* clear the PMT bits 5 and 6 by reading the PMT
 		 * status register. */
 		readl(ioaddr + GMAC_PMT);
+		status |= core_irq_receive_pmt_irq;
 	}
+	/* MAC trx/rx EEE LPI entry/exit interrupts */
+	if (intr_status & lpiis_irq) {
+		/* Clean LPI interrupt by reading the Reg 12 */
+		u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
+			status |= core_irq_tx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
+			status |= core_irq_tx_path_exit_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+			CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
+			status |= core_irq_rx_path_in_lpi_mode;
+		}
+		if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+			CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
+			status |= core_irq_rx_path_exit_lpi_mode;
+		}
+	}
+
+	return status;
+}
+
+static void  dwmac1000_set_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	/* Enable the link status receive on RGMII, SGMII ore SMII
+	 * receive path and instruct the transmit to enter in LPI
+	 * state. */
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+	value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+{
+	u32 value;
+
+	value = readl(ioaddr + LPI_CTRL_STATUS);
+
+	if (link)
+		value |= LPI_CTRL_STATUS_PLS;
+	else
+		value &= ~LPI_CTRL_STATUS_PLS;
+
+	writel(value, ioaddr + LPI_CTRL_STATUS);
+}
+
+static void  dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+{
+	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
+
+	/* Program the timers in the LPI timer control register:
+	 * LS: minimum time (ms) for which the link
+	 *  status from PHY should be ok before transmitting
+	 *  the LPI pattern.
+	 * TW: minimum time (us) for which the core waits
+	 *  after it has stopped transmitting the LPI pattern.
+	 */
+	writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
 static const struct stmmac_ops dwmac1000_ops = {
@@ -226,6 +307,10 @@ static const struct stmmac_ops dwmac1000_ops = {
 	.pmt = dwmac1000_pmt,
 	.set_umac_addr = dwmac1000_set_umac_addr,
 	.get_umac_addr = dwmac1000_get_umac_addr,
+	.set_eee_mode =  dwmac1000_set_eee_mode,
+	.reset_eee_mode =  dwmac1000_reset_eee_mode,
+	.set_eee_timer =  dwmac1000_set_eee_timer,
+	.set_eee_pls =  dwmac1000_set_eee_pls,
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 19e0f4e..f83210e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,9 +72,9 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
 	return 0;
 }
 
-static void dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr)
 {
-	return;
+	return 0;
 }
 
 static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 6e0360f..e678ce3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -70,6 +70,7 @@
 #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
 
 /* DMA Status register defines */
+#define DMA_STATUS_GLPII	0x40000000	/* GMAC LPI interrupt */
 #define DMA_STATUS_GPI		0x10000000	/* PMT interrupt */
 #define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
 #define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index dc20c56..ab4c376 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -87,6 +87,12 @@ struct stmmac_priv {
 #endif
 	int clk_csr;
 	int synopsys_id;
+	struct timer_list eee_ctrl_timer;
+	bool tx_path_in_lpi_mode;
+	int lpi_irq;
+	int eee_enabled;
+	int eee_active;
+	int tx_lpi_timer;
 };
 
 extern int phyaddr;
@@ -104,6 +110,8 @@ int stmmac_dvr_remove(struct net_device *ndev);
 struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 				     struct plat_stmmacenet_data *plat_dat,
 				     void __iomem *addr);
+void stmmac_disable_eee_mode(struct stmmac_priv *priv);
+bool stmmac_eee_init(struct stmmac_priv *priv);
 
 #ifdef CONFIG_HAVE_CLK
 static inline int stmmac_clk_enable(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index ce43184..76fd61a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -93,6 +93,16 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(poll_n),
 	STMMAC_STAT(sched_timer_n),
 	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(mmc_tx_irq_n),
+	STMMAC_STAT(mmc_rx_irq_n),
+	STMMAC_STAT(mmc_rx_csum_offload_irq_n),
+	STMMAC_STAT(irq_receive_pmt_irq_n),
+	STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
+	STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
+	STMMAC_STAT(phy_eee_wakeup_error_n),
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
@@ -366,6 +376,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 					     (*(u32 *)p);
 			}
 		}
+		if (priv->eee_enabled) {
+			int val = phy_get_eee_err(priv->phydev);
+			if (val)
+				priv->xstats.phy_eee_wakeup_error_n = val;
+		}
 	}
 	for (i = 0; i < STMMAC_STATS_LEN; i++) {
 		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -464,6 +479,46 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	return 0;
 }
 
+static int stmmac_ethtool_op_get_eee(struct net_device *dev,
+				     struct ethtool_eee *edata)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if (!priv->dma_cap.eee)
+		return -EOPNOTSUPP;
+
+	edata->eee_enabled = priv->eee_enabled;
+	edata->eee_active = priv->eee_active;
+	edata->tx_lpi_timer = priv->tx_lpi_timer;
+
+	return phy_ethtool_get_eee(priv->phydev, edata);
+}
+
+static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+				     struct ethtool_eee *edata)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	priv->eee_enabled = edata->eee_enabled;
+
+	if (!priv->eee_enabled)
+		stmmac_disable_eee_mode(priv);
+	else {
+		/* We are asking for enabling the EEE but it is safe
+		 * to verify all by invoking the eee_init function.
+		 * In case of failure it will return an error.
+		 */
+		priv->eee_enabled = stmmac_eee_init(priv);
+		if (!priv->eee_enabled)
+			return -EOPNOTSUPP;
+
+		/* Do not change tx_lpi_timer in case of failure */
+		priv->tx_lpi_timer = edata->tx_lpi_timer;
+	}
+
+	return phy_ethtool_set_eee(priv->phydev, edata);
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
 	.begin = stmmac_check_if_running,
 	.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -480,6 +535,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 	.get_strings = stmmac_get_strings,
 	.get_wol = stmmac_get_wol,
 	.set_wol = stmmac_set_wol,
+	.get_eee = stmmac_ethtool_op_get_eee,
+	.set_eee = stmmac_ethtool_op_set_eee,
 	.get_sset_count	= stmmac_get_sset_count,
 	.get_ts_info = ethtool_op_get_ts_info,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index eba49cb..ea3bc09 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -133,6 +133,12 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
 
+#define STMMAC_DEFAULT_LPI_TIMER	1000
+static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
+module_param(eee_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
+#define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
+
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_STMMAC_DEBUG_FS
@@ -161,6 +167,8 @@ static void stmmac_verify_args(void)
 		flow_ctrl = FLOW_OFF;
 	if (unlikely((pause < 0) || (pause > 0xffff)))
 		pause = PAUSE_TIME;
+	if (eee_timer < 0)
+		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
 }
 
 static void stmmac_clk_csr_set(struct stmmac_priv *priv)
@@ -229,6 +237,85 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
 					  phydev->speed);
 }
 
+static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Check and enter in LPI mode */
+	if ((priv->dirty_tx == priv->cur_tx) &&
+	    (priv->tx_path_in_lpi_mode == false))
+		priv->hw->mac->set_eee_mode(priv->ioaddr);
+}
+
+void stmmac_disable_eee_mode(struct stmmac_priv *priv)
+{
+	/* Exit and disable EEE in case of we are are in LPI state. */
+	priv->hw->mac->reset_eee_mode(priv->ioaddr);
+	del_timer_sync(&priv->eee_ctrl_timer);
+	priv->tx_path_in_lpi_mode = false;
+}
+
+/**
+ * stmmac_eee_ctrl_timer
+ * @arg : data hook
+ * Description:
+ *  If there is no data transfer and if we are not in LPI state,
+ *  then MAC Transmitter can be moved to LPI state.
+ */
+static void stmmac_eee_ctrl_timer(unsigned long arg)
+{
+	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
+
+	stmmac_enable_eee_mode(priv);
+	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+}
+
+/**
+ * stmmac_eee_init
+ * @priv: private device pointer
+ * Description:
+ *  If the EEE support has been enabled while configuring the driver,
+ *  if the GMAC actually supports the EEE (from the HW cap reg) and the
+ *  phy can also manage EEE, so enable the LPI state and start the timer
+ *  to verify if the tx path can enter in LPI state.
+ */
+bool stmmac_eee_init(struct stmmac_priv *priv)
+{
+	bool ret = false;
+
+	/* MAC core supports the EEE feature. */
+	if (priv->dma_cap.eee) {
+		/* Check if the PHY supports EEE */
+		if (phy_init_eee(priv->phydev, 1))
+			goto out;
+
+		priv->eee_active = 1;
+		init_timer(&priv->eee_ctrl_timer);
+		priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
+		priv->eee_ctrl_timer.data = (unsigned long)priv;
+		priv->eee_ctrl_timer.expires = STMMAC_LPI_TIMER(eee_timer);
+		add_timer(&priv->eee_ctrl_timer);
+
+		priv->hw->mac->set_eee_timer(priv->ioaddr,
+					     STMMAC_DEFAULT_LIT_LS_TIMER,
+					     priv->tx_lpi_timer);
+
+		pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
+
+		ret = true;
+	}
+out:
+	return ret;
+}
+
+static void stmmac_eee_adjust(struct stmmac_priv *priv)
+{
+	/* When the EEE has been already initialised we have to
+	 * modify the PLS bit in the LPI ctrl & status reg according
+	 * to the PHY link status. For this reason.
+	 */
+	if (priv->eee_enabled)
+		priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
+}
+
 /**
  * stmmac_adjust_link
  * @dev: net device structure
@@ -249,6 +336,7 @@ static void stmmac_adjust_link(struct net_device *dev)
 	    phydev->addr, phydev->link);
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	if (phydev->link) {
 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
 
@@ -315,6 +403,8 @@ static void stmmac_adjust_link(struct net_device *dev)
 	if (new_state && netif_msg_link(priv))
 		phy_print_status(phydev);
 
+	stmmac_eee_adjust(priv);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
@@ -332,7 +422,7 @@ static int stmmac_init_phy(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev;
-	char phy_id[MII_BUS_ID_SIZE + 3];
+	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
 	char bus_id[MII_BUS_ID_SIZE];
 	int interface = priv->plat->interface;
 	priv->oldlink = 0;
@@ -346,11 +436,12 @@ static int stmmac_init_phy(struct net_device *dev)
 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
 				priv->plat->bus_id);
 
-	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
 		 priv->plat->phy_addr);
-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
+	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
 
-	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
+	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0,
+			     interface);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -689,6 +780,11 @@ static void stmmac_tx(struct stmmac_priv *priv)
 		}
 		netif_tx_unlock(priv->dev);
 	}
+
+	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
+		stmmac_enable_eee_mode(priv);
+		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_TIMER(eee_timer));
+	}
 	spin_unlock(&priv->tx_lock);
 }
 
@@ -1027,6 +1123,17 @@ static int stmmac_open(struct net_device *dev)
 		}
 	}
 
+	/* Request the IRQ lines */
+	if (priv->lpi_irq != -ENXIO) {
+		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
+				  dev->name, dev);
+		if (unlikely(ret < 0)) {
+			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
+			       __func__, priv->lpi_irq, ret);
+			goto open_error_lpiirq;
+		}
+	}
+
 	/* Enable the MAC Rx/Tx */
 	stmmac_set_mac(priv->ioaddr, true);
 
@@ -1062,12 +1169,19 @@ static int stmmac_open(struct net_device *dev)
 	if (priv->phydev)
 		phy_start(priv->phydev);
 
+	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
+	priv->eee_enabled = stmmac_eee_init(priv);
+
 	napi_enable(&priv->napi);
 	skb_queue_head_init(&priv->rx_recycle);
 	netif_start_queue(dev);
 
 	return 0;
 
+open_error_lpiirq:
+	if (priv->wol_irq != dev->irq)
+		free_irq(priv->wol_irq, dev);
+
 open_error_wolirq:
 	free_irq(dev->irq, dev);
 
@@ -1093,6 +1207,9 @@ static int stmmac_release(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
+	if (priv->eee_enabled)
+		del_timer_sync(&priv->eee_ctrl_timer);
+
 	/* Stop and disconnect the PHY */
 	if (priv->phydev) {
 		phy_stop(priv->phydev);
@@ -1115,6 +1232,8 @@ static int stmmac_release(struct net_device *dev)
 	free_irq(dev->irq, dev);
 	if (priv->wol_irq != dev->irq)
 		free_irq(priv->wol_irq, dev);
+	if (priv->lpi_irq != -ENXIO)
+		free_irq(priv->lpi_irq, dev);
 
 	/* Stop TX/RX DMA and clear the descriptors */
 	priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1164,6 +1283,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	spin_lock(&priv->tx_lock);
 
+	if (priv->tx_path_in_lpi_mode)
+		stmmac_disable_eee_mode(priv);
+
 	entry = priv->cur_tx % txsize;
 
 #ifdef STMMAC_XMIT_DEBUG
@@ -1540,10 +1662,37 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
 		return IRQ_NONE;
 	}
 
-	if (priv->plat->has_gmac)
-		/* To handle GMAC own interrupts */
-		priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
+	/* To handle GMAC own interrupts */
+	if (priv->plat->has_gmac) {
+		int status = priv->hw->mac->host_irq_status((void __iomem *)
+							    dev->base_addr);
+		if (unlikely(status)) {
+			if (status & core_mmc_tx_irq)
+				priv->xstats.mmc_tx_irq_n++;
+			if (status & core_mmc_rx_irq)
+				priv->xstats.mmc_rx_irq_n++;
+			if (status & core_mmc_rx_csum_offload_irq)
+				priv->xstats.mmc_rx_csum_offload_irq_n++;
+			if (status & core_irq_receive_pmt_irq)
+				priv->xstats.irq_receive_pmt_irq_n++;
+
+			/* For LPI we need to save the tx status */
+			if (status & core_irq_tx_path_in_lpi_mode) {
+				priv->xstats.irq_tx_path_in_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = true;
+			}
+			if (status & core_irq_tx_path_exit_lpi_mode) {
+				priv->xstats.irq_tx_path_exit_lpi_mode_n++;
+				priv->tx_path_in_lpi_mode = false;
+			}
+			if (status & core_irq_rx_path_in_lpi_mode)
+				priv->xstats.irq_rx_path_in_lpi_mode_n++;
+			if (status & core_irq_rx_path_exit_lpi_mode)
+				priv->xstats.irq_rx_path_exit_lpi_mode_n++;
+		}
+	}
 
+	/* To handle DMA interrupts */
 	stmmac_dma_interrupt(priv);
 
 	return IRQ_HANDLED;
@@ -2155,6 +2304,9 @@ static int __init stmmac_cmdline_opt(char *str)
 		} else if (!strncmp(opt, "pause:", 6)) {
 			if (kstrtoint(opt + 6, 0, &pause))
 				goto err;
+		} else if (!strncmp(opt, "eee_timer:", 6)) {
+			if (kstrtoint(opt + 10, 0, &eee_timer))
+				goto err;
 #ifdef CONFIG_STMMAC_TIMER
 		} else if (!strncmp(opt, "tmrate:", 7)) {
 			if (kstrtoint(opt + 7, 0, &tmrate))
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 20eb502..7d36163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -156,6 +156,8 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 	if (priv->wol_irq == -ENXIO)
 		priv->wol_irq = priv->dev->irq;
 
+	priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
+
 	platform_set_drvdata(pdev, priv->dev);
 
 	pr_debug("STMMAC platform driver registration completed");
-- 
1.7.4.4

^ permalink raw reply related

* [net-next.git 2/4] stmmac: update the driver Documentation and add EEE
From: Giuseppe CAVALLARO @ 2012-06-28  7:14 UTC (permalink / raw)
  To: netdev
  Cc: eric.dumazet, rayagond, davem, yuvalmin, bhutchings,
	Giuseppe Cavallaro
In-Reply-To: <1340867678-18375-1-git-send-email-peppe.cavallaro@st.com>

This patch updates the stmmac's documentation adding
some missing files in the section used to describe the
internal driver's structure.

Also the patch adds a new section to describe the EEE support.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   36 +++++++++++++++++++++++++++++-----
 1 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 5cb9a19..c676b9c 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -257,9 +257,11 @@ reset procedure etc).
  o Makefile
  o stmmac_main.c: main network device driver;
  o stmmac_mdio.c: mdio functions;
+ o stmmac_pci: PCI driver;
+ o stmmac_platform.c: platform driver
  o stmmac_ethtool.c: ethtool support;
  o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
-		      Only tested on ST40 platforms based.
+		      (only tested on ST40 platforms based);
  o stmmac.h: private driver structure;
  o common.h: common definitions and VFTs;
  o descs.h: descriptor structure definitions;
@@ -269,9 +271,11 @@ reset procedure etc).
  o dwmac100_core: MAC 100 core and dma code;
  o dwmac100_dma.c: dma funtions for the MAC chip;
  o dwmac1000.h: specific header file for the MAC;
- o dwmac_lib.c: generic DMA functions shared among chips
- o enh_desc.c: functions for handling enhanced descriptors
- o norm_desc.c: functions for handling normal descriptors
+ o dwmac_lib.c: generic DMA functions shared among chips;
+ o enh_desc.c: functions for handling enhanced descriptors;
+ o norm_desc.c: functions for handling normal descriptors;
+ o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
+ o mmc_core.c/mmc.h: Management MAC Counters;
 
 5) Debug Information
 
@@ -304,7 +308,27 @@ All these are only useful during the developing stage
 and should never enabled inside the code for general usage.
 In fact, these can generate an huge amount of debug messages.
 
-6) TODO:
+6) Energy Efficient Ethernet
+
+Energy Efficient Ethernet(EEE) enables IEEE 802.3 MAC sublayer along
+with a family of Physical layer to operate in the Low power Idle(LPI)
+mode. The EEE mode supports the IEEE 802.3 MAC operation at 100Mbps,
+1000Mbps & 10Gbps.
+
+The LPI mode allows power saving by switching off parts of the
+communication device functionality when there is no data to be
+transmitted & received. The system on both the side of the link can
+disable some functionalities & save power during the period of low-link
+utilization. The MAC controls whether the system should enter or exit
+the LPI mode & communicate this to PHY.
+
+As soon as the interface is opened, the driver verifies if the EEE can
+be supported. This is done by looking at both the DMA HW capability
+register and the PHY devices MCD registers.
+To enter in Tx LPI mode the driver needs to have a software timer
+that enable and disable the LPI mode when there is nothing to be
+transmitted.
+
+7) TODO:
  o XGMAC is not supported.
- o Add the EEE - Energy Efficient Ethernet
  o Add the PTP - precision time protocol
-- 
1.7.4.4

^ permalink raw reply related

* [net-next.git 0/4] EEE for PAL and stmmac (V7)
From: Giuseppe CAVALLARO @ 2012-06-28  7:14 UTC (permalink / raw)
  To: netdev
  Cc: eric.dumazet, rayagond, davem, yuvalmin, bhutchings,
	Giuseppe Cavallaro

These patches add the EEE support in the stmmac device driver
restoring an old work I had done some months ago and not
completed in time.

I've tested all on ST STB with the IC+ 101G PHY device that has
this feature.

The initial EEE support for the stmmac has been written by Rayagond
but I have reworked all his code adding new parts and especially
performing tests on a real hardware. Thx Rayagond!

In these patches, we can see that the stmmac supports the EEE
only if the DMA HW capability register says that this
feature is actually available. In that case, the driver can enter
in the Tx LPI mode by using a timer as recommended by Synopsys.
Note that EEE is supported in new chip generations; in particular
I used the 3.61a.

At any rate, further information about how the driver treats the EEE
can be found in the stmmac.txt file (there is a patch for that).

Another patch is for Physical Abstraction Layer now able to
manage the MMD registers (clause 45); it also provides the ethtool
support to manage supported/advertisement/lp adv features.

v3: fixed the "stmmac: do not use strict_strtoul but kstrtoint"
    to use the kstrtoint.
v4: fixed the function to enable the EEE and add a check that verifies
    if the link auto-negotiated matches with the bits in the adv and lp
    registers.
v5: reviewed the way to get the negotiated settings
v6: fixed a broken return value in the phy_eee_init function
v7: do not remove the MDIO_AN_EEE_ADV_100TX and MDIO_AN_EEE_ADV_1000T
    and fixed the eee_{cap,lp,adv} declaration as "int" instead of u16.

Giuseppe Cavallaro (4):
  stmmac: do not use strict_strtoul but kstrtoint
  stmmac: update the driver Documentation and add EEE
  stmmac: add the Energy Efficient Ethernet support
  phy: add the EEE support and the way to access to the MMD registers.

 Documentation/networking/stmmac.txt                |   36 ++-
 drivers/net/ethernet/stmicro/stmmac/common.h       |   31 ++-
 drivers/net/ethernet/stmicro/stmmac/dwmac1000.h    |   20 ++
 .../net/ethernet/stmicro/stmmac/dwmac1000_core.c   |  101 +++++++-
 .../net/ethernet/stmicro/stmmac/dwmac100_core.c    |    4 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h    |    1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |    8 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   57 ++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  193 ++++++++++++--
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    2 +
 drivers/net/phy/phy.c                              |  281 ++++++++++++++++++++
 include/linux/mdio.h                               |   28 ++-
 include/linux/mii.h                                |    9 +
 include/linux/phy.h                                |    5 +
 14 files changed, 731 insertions(+), 45 deletions(-)

-- 
1.7.4.4

^ permalink raw reply

* [net-next.git 1/4 (v3)] stmmac: do not use strict_strtoul but kstrtoint
From: Giuseppe CAVALLARO @ 2012-06-28  7:14 UTC (permalink / raw)
  To: netdev
  Cc: eric.dumazet, rayagond, davem, yuvalmin, bhutchings,
	Giuseppe Cavallaro
In-Reply-To: <1340867678-18375-1-git-send-email-peppe.cavallaro@st.com>

This patch replaces the obsolete strict_strtoul with kstrtoint.

v2: also removed casting on kstrtoul.
v3: use kstrtoint instead of kstrtoul due to all vars are integer.
    thanks to E. Dumazet.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |   27 +++++++-------------
 1 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 590e95b..eba49cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2129,42 +2129,35 @@ static int __init stmmac_cmdline_opt(char *str)
 		return -EINVAL;
 	while ((opt = strsep(&str, ",")) != NULL) {
 		if (!strncmp(opt, "debug:", 6)) {
-			if (strict_strtoul(opt + 6, 0, (unsigned long *)&debug))
+			if (kstrtoint(opt + 6, 0, &debug))
 				goto err;
 		} else if (!strncmp(opt, "phyaddr:", 8)) {
-			if (strict_strtoul(opt + 8, 0,
-					   (unsigned long *)&phyaddr))
+			if (kstrtoint(opt + 8, 0, &phyaddr))
 				goto err;
 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
-			if (strict_strtoul(opt + 11, 0,
-					   (unsigned long *)&dma_txsize))
+			if (kstrtoint(opt + 11, 0, &dma_txsize))
 				goto err;
 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
-			if (strict_strtoul(opt + 11, 0,
-					   (unsigned long *)&dma_rxsize))
+			if (kstrtoint(opt + 11, 0, &dma_rxsize))
 				goto err;
 		} else if (!strncmp(opt, "buf_sz:", 7)) {
-			if (strict_strtoul(opt + 7, 0,
-					   (unsigned long *)&buf_sz))
+			if (kstrtoint(opt + 7, 0, &buf_sz))
 				goto err;
 		} else if (!strncmp(opt, "tc:", 3)) {
-			if (strict_strtoul(opt + 3, 0, (unsigned long *)&tc))
+			if (kstrtoint(opt + 3, 0, &tc))
 				goto err;
 		} else if (!strncmp(opt, "watchdog:", 9)) {
-			if (strict_strtoul(opt + 9, 0,
-					   (unsigned long *)&watchdog))
+			if (kstrtoint(opt + 9, 0, &watchdog))
 				goto err;
 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
-			if (strict_strtoul(opt + 10, 0,
-					   (unsigned long *)&flow_ctrl))
+			if (kstrtoint(opt + 10, 0, &flow_ctrl))
 				goto err;
 		} else if (!strncmp(opt, "pause:", 6)) {
-			if (strict_strtoul(opt + 6, 0, (unsigned long *)&pause))
+			if (kstrtoint(opt + 6, 0, &pause))
 				goto err;
 #ifdef CONFIG_STMMAC_TIMER
 		} else if (!strncmp(opt, "tmrate:", 7)) {
-			if (strict_strtoul(opt + 7, 0,
-					   (unsigned long *)&tmrate))
+			if (kstrtoint(opt + 7, 0, &tmrate))
 				goto err;
 #endif
 		}
-- 
1.7.4.4

^ permalink raw reply related

* Re: LOCKDEP complaints in l2tp_xmit_skb()
From: Eric Dumazet @ 2012-06-28  6:56 UTC (permalink / raw)
  To: Tom Parkin; +Cc: netdev
In-Reply-To: <20120627111152.GA2531@raven>

On Wed, 2012-06-27 at 12:11 +0100, Tom Parkin wrote:
> In testing L2TP ethernet pseudowires I have observed some complaints
> from lockdep due to circular/recursive locking in l2tp_xmit_skb().
> 
> I'm testing the -net tree, which includes Eric's recent patches to
> squash another lockdep error by converting l2tp to LLTX.  Git hash
> d7ffde35e31a811.
> 
> My test setup consists of two AMD64 boxes, both running 32bit kernels.
> One box is SMP, the other UP.  My test procedure consists of creating
> an L2TP tunnel containing N ethernet pseudowires.  I then run N iperf
> sessions across the N pseudowires.  The simplest configuration is:
> 
> 
> [On HOST A]
> ip l2tp add tunnel \
> 	tunnel_id 1 \
> 	peer_tunnel_id 1 \
> 	local <HOST A ip> \
> 	remote <HOST B ip> \
> 	udp_sport 9999 \
> 	udp_dport 9999
> ip add session \
> 	tunnel_id 1 \
> 	session_id 1 \
> 	peer_session_id 1
> ip addr add 172.16.0.1 \
> 	peer 172.16.0.2/24 \
> 	broadcast 172.16.0.255 \
> 	dev l2tpeth0
> ip link set l2tpeth0 up
> iperf -s -B 172.16.0.1
> 
> [On HOST B]
> ip l2tp add tunnel \
> 	tunnel_id 1 \
> 	peer_tunnel_id 1 \
> 	local <HOST B ip> \
> 	remote <HOST A ip> \
> 	udp_sport 9999 \
> 	udp_dport 9999
> ip add session \
> 	tunnel_id 1 \
> 	session_id 1 \
> 	peer_session_id 1
> ip addr add 172.16.0.2 \
> 	peer 172.16.0.1/24 \
> 	broadcast 172.16.0.255 \
> 	dev l2tpeth0
> ip link set l2tpeth0 up
> iperf -c 172.16.0.1
> 
> 
> If I run four concurrent iperf sessions across four pseudowires I
> see lockdep complaints on both SMP and UP boxes.
> 
> Lockdep output for the AMD64 SMP machine:
> 
> ======================================================
> [ INFO: possible circular locking dependency detected ]
> 3.5.0-rc2-net-lockdep-u64-sync-006-+ #2 Not tainted
> -------------------------------------------------------
> swapper/1/0 is trying to acquire lock:
>  (slock-AF_INET){+.-...}, at: [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
> 
> but task is already holding lock:
>  (&(&sch->busylock)->rlock){+.-...}, at: [<c14fb1b2>] dev_queue_xmit+0xb42/0xbd0
> 
> which lock already depends on the new lock.
> 
> 
> the existing dependency chain (in reverse order) is:
> 
> -> #1 (&(&sch->busylock)->rlock){+.-...}:
>        [<c10a8b48>] lock_acquire+0x88/0x120
>        [<c16157bb>] _raw_spin_lock+0x3b/0x70
>        [<c1535cf8>] __inet_hash_nolisten+0xb8/0x140
>        [<c1536b77>] __inet_hash_connect+0x267/0x2c0
>        [<c1536c10>] inet_hash_connect+0x40/0x50
>        [<c154e4d4>] tcp_v4_connect+0x2c4/0x510
>        [<c156293f>] inet_stream_connect+0x1ff/0x380
>        [<c14e30c1>] sys_connect+0xc1/0xe0
>        [<c14e3d13>] sys_socketcall+0xe3/0x2e0
>        [<c161d89f>] sysenter_do_call+0x12/0x38
> 
> -> #0 (slock-AF_INET){+.-...}:
>        [<c10a78cc>] __lock_acquire+0xaec/0x17d0
>        [<c10a8b48>] lock_acquire+0x88/0x120
>        [<c16157bb>] _raw_spin_lock+0x3b/0x70
>        [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
>        [<f851432d>] l2tp_eth_dev_xmit+0x2d/0x40 [l2tp_eth]
>        [<c14fa32f>] dev_hard_start_xmit+0x49f/0x7e0
>        [<c1515819>] sch_direct_xmit+0xa9/0x250
>        [<c14fa835>] dev_queue_xmit+0x1c5/0xbd0
>        [<c159442c>] ip6_finish_output2+0x11c/0x620
>        [<c159813f>] ip6_finish_output+0x7f/0x1e0
>        [<c15982ea>] ip6_output+0x4a/0x1f0
>        [<c15bbddc>] mld_sendpack+0x21c/0x530
>        [<c15bc817>] mld_ifc_timer_expire+0x187/0x260
>        [<c1055d10>] run_timer_softirq+0x140/0x370
>        [<c104da27>] __do_softirq+0x97/0x1f0
> 
> other info that might help us debug this:
> 
>  Possible unsafe locking scenario:
> 
>        CPU0                    CPU1
>        ----                    ----
>   lock(&(&sch->busylock)->rlock);
>                                lock(slock-AF_INET);
>                                lock(&(&sch->busylock)->rlock);
>   lock(slock-AF_INET);
> 
>  *** DEADLOCK ***
> 
> 5 locks held by swapper/1/0:
>  #0:  (&idev->mc_ifc_timer){+.-...}, at: [<c1055c88>] run_timer_softirq+0xb8/0x370
>  #1:  (rcu_read_lock){.+.+..}, at: [<c15bbbc0>] mld_sendpack+0x0/0x530
>  #2:  (rcu_read_lock){.+.+..}, at: [<c159434f>] ip6_finish_output2+0x3f/0x620
>  #3:  (rcu_read_lock_bh){.+....}, at: [<c14fa670>] dev_queue_xmit+0x0/0xbd0
>  #4:  (&(&sch->busylock)->rlock){+.-...}, at: [<c14fb1b2>] dev_queue_xmit+0xb42/0xbd0
> 
> stack backtrace:
> Pid: 0, comm: swapper/1 Not tainted 3.5.0-rc2-net-lockdep-u64-sync-006-+ #2
> Call Trace:
>  [<c160b540>] print_circular_bug+0x1b4/0x1be
>  [<c10a78cc>] __lock_acquire+0xaec/0x17d0
>  [<c10a8b48>] lock_acquire+0x88/0x120
>  [<f85f5bff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
>  [<c16157bb>] _raw_spin_lock+0x3b/0x70
>  [<f85f5bff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
>  [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
>  [<f851432d>] l2tp_eth_dev_xmit+0x2d/0x40 [l2tp_eth]
>  [<c14fa32f>] dev_hard_start_xmit+0x49f/0x7e0
>  [<c14f9ee1>] ? dev_hard_start_xmit+0x51/0x7e0
>  [<c1515819>] sch_direct_xmit+0xa9/0x250
>  [<c16157e1>] ? _raw_spin_lock+0x61/0x70
>  [<c14fa835>] dev_queue_xmit+0x1c5/0xbd0
>  [<c14fa670>] ? dev_hard_start_xmit+0x7e0/0x7e0
>  [<c159442c>] ip6_finish_output2+0x11c/0x620
>  [<c159434f>] ? ip6_finish_output2+0x3f/0x620
>  [<c159813f>] ip6_finish_output+0x7f/0x1e0
>  [<c15982ea>] ip6_output+0x4a/0x1f0
>  [<c15a6ae0>] ? ip6_blackhole_route+0x2c0/0x2c0
>  [<c15bbddc>] mld_sendpack+0x21c/0x530
>  [<c15bbbc0>] ? igmp6_group_added+0x170/0x170
>  [<c15bc817>] mld_ifc_timer_expire+0x187/0x260
>  [<c1055d10>] run_timer_softirq+0x140/0x370
>  [<c1055c88>] ? run_timer_softirq+0xb8/0x370
>  [<c1085776>] ? rebalance_domains+0x1b6/0x2a0
>  [<c15bc690>] ? igmp6_timer_handler+0x80/0x80
>  [<c104da27>] __do_softirq+0x97/0x1f0
>  [<c104d990>] ? local_bh_enable_ip+0xd0/0xd0
>  <IRQ>  [<c104ddce>] ? irq_exit+0x7e/0xa0
>  [<c161e0f9>] ? smp_apic_timer_interrupt+0x59/0x88
>  [<c12fb498>] ? trace_hardirqs_off_thunk+0xc/0x14
>  [<c1616882>] ? apic_timer_interrupt+0x36/0x3c
>  [<c10380d5>] ? native_safe_halt+0x5/0x10
>  [<c1018bdf>] ? default_idle+0x4f/0x1e0
>  [<c1018dc1>] ? amd_e400_idle+0x51/0x100
>  [<c10199c9>] ? cpu_idle+0xb9/0xe0
>  [<c16038fc>] ? start_secondary+0x1ea/0x1f0
> 
> 
> 
> And on AMD64 UP machine:
> 
> ============================================
>  INFO: possible recursive locking detected ]
> .5.0-rc2-net-lockdep-u64-sync-006-+ #2 Not tainted
> --------------------------------------------
> wapper/0/0 is trying to acquire lock:
> (slock-AF_INET){+.-...}, at: [<f864fbff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
> 
> ut task is already holding lock:
> (slock-AF_INET){+.-...}, at: [<c154c177>] tcp_delack_timer+0x17/0x1e0
> 
> ther info that might help us debug this:
> Possible unsafe locking scenario:
> 
>       CPU0
>       ----
>  lock(slock-AF_INET);
>  lock(slock-AF_INET);
> 
> *** DEADLOCK ***
> 
> May be due to missing lock nesting notation
> 
>  locks held by swapper/0/0:
> #0:  (&icsk->icsk_delack_timer){+.-...}, at: [<c1055c88>] run_timer_softirq+0xb8/0x370
> #1:  (slock-AF_INET){+.-...}, at: [<c154c177>] tcp_delack_timer+0x17/0x1e0
> #2:  (rcu_read_lock){.+.+..}, at: [<c1531bf0>] ip_queue_xmit+0x0/0x610
> #3:  (rcu_read_lock){.+.+..}, at: [<c1531456>] ip_finish_output+0x106/0x710
> #4:  (rcu_read_lock_bh){.+....}, at: [<c14fa670>] dev_queue_xmit+0x0/0xbd0
> 
> tack backtrace:
> id: 0, comm: swapper/0 Not tainted 3.5.0-rc2-net-lockdep-u64-sync-006-+ #2
> all Trace:
> [<c10a7b32>] __lock_acquire+0xd52/0x17d0
> [<c1017ba8>] ? sched_clock+0x8/0x10
> [<c107edbb>] ? sched_clock_local+0xcb/0x1c0
> [<c10a8b48>] lock_acquire+0x88/0x120
> [<f864fbff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
> [<c16157bb>] _raw_spin_lock+0x3b/0x70
> [<f864fbff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
> [<f864fbff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
> [<f853032d>] l2tp_eth_dev_xmit+0x2d/0x40 [l2tp_eth]
> [<c14fa32f>] dev_hard_start_xmit+0x49f/0x7e0
> [<c14f9ee1>] ? dev_hard_start_xmit+0x51/0x7e0
> [<c1515819>] sch_direct_xmit+0xa9/0x250
> [<c16157e1>] ? _raw_spin_lock+0x61/0x70
> [<c14fa835>] dev_queue_xmit+0x1c5/0xbd0
> [<c14fa670>] ? dev_hard_start_xmit+0x7e0/0x7e0
> [<c15065f7>] neigh_resolve_output+0x117/0x230
> [<c1514880>] ? eth_rebuild_header+0x80/0x80
> [<c1531612>] ip_finish_output+0x2c2/0x710
> [<c1531456>] ? ip_finish_output+0x106/0x710
> [<c1532770>] ? ip_output+0x60/0x120
> [<c10a585b>] ? trace_hardirqs_on+0xb/0x10
> [<c153278b>] ip_output+0x7b/0x120
> [<c1531b95>] ip_local_out+0x25/0x80
> [<c1531d73>] ip_queue_xmit+0x183/0x610
> [<c1531bf0>] ? ip_local_out+0x80/0x80
> [<c154ecb5>] ? tcp_md5_do_lookup+0x125/0x170
> [<c15498c6>] tcp_transmit_skb+0x396/0x970
> [<c154bb12>] ? tcp_send_ack+0x32/0x100
> [<c154bb9d>] tcp_send_ack+0xbd/0x100
> [<c154c271>] tcp_delack_timer+0x111/0x1e0
> [<c1055d10>] run_timer_softirq+0x140/0x370
> [<c1055c88>] ? run_timer_softirq+0xb8/0x370
> [<c154c160>] ? tcp_out_of_resources+0xb0/0xb0
> [<c14f88cc>] ? net_rx_action+0x10c/0x210
> [<c104da27>] __do_softirq+0x97/0x1f0
> [<c104d990>] ? local_bh_enable_ip+0xd0/0xd0
> <IRQ>  [<c104ddce>] ? irq_exit+0x7e/0xa0
> [<c161e02b>] ? do_IRQ+0x4b/0xc0
> [<c161de75>] ? common_interrupt+0x35/0x3c
> [<c10380d5>] ? native_safe_halt+0x5/0x10
> [<c1018bdf>] ? default_idle+0x4f/0x1e0
> [<c1018dc1>] ? amd_e400_idle+0x51/0x100
> [<c10199c9>] ? cpu_idle+0xb9/0xe0
> [<c15eab3e>] ? rest_init+0x112/0x124
> [<c15eaa2c>] ? __read_lock_failed+0x14/0x14
> [<c1907a11>] ? start_kernel+0x376/0x37c
> [<c19074d6>] ? repair_env_string+0x51/0x51
> [<c19072f8>] ? i386_start_kernel+0x9b/0xa2
> 

Hi Tom

Could you please test following patch ?

Thanks !

[PATCH] net: Qdisc busylock gets its own lockdep class

Tom Parkin reported following LOCKDEP splat :

======================================================
[ INFO: possible circular locking dependency detected ]
3.5.0-rc2-net-lockdep-u64-sync-006-+ #2 Not tainted
-------------------------------------------------------
swapper/1/0 is trying to acquire lock:
 (slock-AF_INET){+.-...}, at: [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0
[l2tp_core]

but task is already holding lock:
 (&(&sch->busylock)->rlock){+.-...}, at: [<c14fb1b2>] dev_queue_xmit
+0xb42/0xbd0

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&(&sch->busylock)->rlock){+.-...}:
       [<c10a8b48>] lock_acquire+0x88/0x120
       [<c16157bb>] _raw_spin_lock+0x3b/0x70
       [<c1535cf8>] __inet_hash_nolisten+0xb8/0x140
       [<c1536b77>] __inet_hash_connect+0x267/0x2c0
       [<c1536c10>] inet_hash_connect+0x40/0x50
       [<c154e4d4>] tcp_v4_connect+0x2c4/0x510
       [<c156293f>] inet_stream_connect+0x1ff/0x380
       [<c14e30c1>] sys_connect+0xc1/0xe0
       [<c14e3d13>] sys_socketcall+0xe3/0x2e0
       [<c161d89f>] sysenter_do_call+0x12/0x38

-> #0 (slock-AF_INET){+.-...}:
       [<c10a78cc>] __lock_acquire+0xaec/0x17d0
       [<c10a8b48>] lock_acquire+0x88/0x120
       [<c16157bb>] _raw_spin_lock+0x3b/0x70
       [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
       [<f851432d>] l2tp_eth_dev_xmit+0x2d/0x40 [l2tp_eth]
       [<c14fa32f>] dev_hard_start_xmit+0x49f/0x7e0
       [<c1515819>] sch_direct_xmit+0xa9/0x250
       [<c14fa835>] dev_queue_xmit+0x1c5/0xbd0
       [<c159442c>] ip6_finish_output2+0x11c/0x620
       [<c159813f>] ip6_finish_output+0x7f/0x1e0
       [<c15982ea>] ip6_output+0x4a/0x1f0
       [<c15bbddc>] mld_sendpack+0x21c/0x530
       [<c15bc817>] mld_ifc_timer_expire+0x187/0x260
       [<c1055d10>] run_timer_softirq+0x140/0x370
       [<c104da27>] __do_softirq+0x97/0x1f0

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&(&sch->busylock)->rlock);
                               lock(slock-AF_INET);
                               lock(&(&sch->busylock)->rlock);
  lock(slock-AF_INET);

 *** DEADLOCK ***

5 locks held by swapper/1/0:
 #0:  (&idev->mc_ifc_timer){+.-...}, at: [<c1055c88>] run_timer_softirq
+0xb8/0x370
 #1:  (rcu_read_lock){.+.+..}, at: [<c15bbbc0>] mld_sendpack+0x0/0x530
 #2:  (rcu_read_lock){.+.+..}, at: [<c159434f>] ip6_finish_output2
+0x3f/0x620
 #3:  (rcu_read_lock_bh){.+....}, at: [<c14fa670>] dev_queue_xmit
+0x0/0xbd0
 #4:  (&(&sch->busylock)->rlock){+.-...}, at: [<c14fb1b2>]
dev_queue_xmit+0xb42/0xbd0

stack backtrace:
Pid: 0, comm: swapper/1 Not tainted 3.5.0-rc2-net-lockdep-u64-sync-006-+
#2
Call Trace:
 [<c160b540>] print_circular_bug+0x1b4/0x1be
 [<c10a78cc>] __lock_acquire+0xaec/0x17d0
 [<c10a8b48>] lock_acquire+0x88/0x120
 [<f85f5bff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
 [<c16157bb>] _raw_spin_lock+0x3b/0x70
 [<f85f5bff>] ? l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
 [<f85f5bff>] l2tp_xmit_skb+0x13f/0x8e0 [l2tp_core]
 [<f851432d>] l2tp_eth_dev_xmit+0x2d/0x40 [l2tp_eth]
 [<c14fa32f>] dev_hard_start_xmit+0x49f/0x7e0
 [<c14f9ee1>] ? dev_hard_start_xmit+0x51/0x7e0
 [<c1515819>] sch_direct_xmit+0xa9/0x250
 [<c16157e1>] ? _raw_spin_lock+0x61/0x70
 [<c14fa835>] dev_queue_xmit+0x1c5/0xbd0
 [<c14fa670>] ? dev_hard_start_xmit+0x7e0/0x7e0
 [<c159442c>] ip6_finish_output2+0x11c/0x620
 [<c159434f>] ? ip6_finish_output2+0x3f/0x620
 [<c159813f>] ip6_finish_output+0x7f/0x1e0
 [<c15982ea>] ip6_output+0x4a/0x1f0
 [<c15a6ae0>] ? ip6_blackhole_route+0x2c0/0x2c0
 [<c15bbddc>] mld_sendpack+0x21c/0x530
 [<c15bbbc0>] ? igmp6_group_added+0x170/0x170
 [<c15bc817>] mld_ifc_timer_expire+0x187/0x260
 [<c1055d10>] run_timer_softirq+0x140/0x370
 [<c1055c88>] ? run_timer_softirq+0xb8/0x370
 [<c1085776>] ? rebalance_domains+0x1b6/0x2a0
 [<c15bc690>] ? igmp6_timer_handler+0x80/0x80
 [<c104da27>] __do_softirq+0x97/0x1f0
 [<c104d990>] ? local_bh_enable_ip+0xd0/0xd0
 <IRQ>  [<c104ddce>] ? irq_exit+0x7e/0xa0
 [<c161e0f9>] ? smp_apic_timer_interrupt+0x59/0x88
 [<c12fb498>] ? trace_hardirqs_off_thunk+0xc/0x14
 [<c1616882>] ? apic_timer_interrupt+0x36/0x3c
 [<c10380d5>] ? native_safe_halt+0x5/0x10
 [<c1018bdf>] ? default_idle+0x4f/0x1e0
 [<c1018dc1>] ? amd_e400_idle+0x51/0x100
 [<c10199c9>] ? cpu_idle+0xb9/0xe0
 [<c16038fc>] ? start_secondary+0x1ea/0x1f0

Instruct lockdep that each Qdisc busylock is independant, or else
bonding or various tunnels can trigger a splat.

Reported-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/sch_generic.h |    1 +
 net/sched/sch_generic.c   |    1 +
 2 files changed, 2 insertions(+)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 9d7d54a..a45b501 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -83,6 +83,7 @@ struct Qdisc {
 	struct rcu_head		rcu_head;
 	spinlock_t		busylock;
 	u32			limit;
+	struct lock_class_key	busylock_key;
 };
 
 static inline bool qdisc_is_running(const struct Qdisc *qdisc)
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 511323e..3357c6d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -572,6 +572,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
 	spin_lock_init(&sch->busylock);
+	lockdep_set_class(&sch->busylock, &sch->busylock_key);
 	sch->ops = ops;
 	sch->enqueue = ops->enqueue;
 	sch->dequeue = ops->dequeue;

^ permalink raw reply related

* Re: [net-next.git 4/4 (v8)] phy: add the EEE support and the way to access to the MMD registers.
From: Giuseppe CAVALLARO @ 2012-06-28  6:54 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, eric.dumazet, rayagond, davem, yuvalmin
In-Reply-To: <1340813737.2591.5.camel@bwh-desktop.uk.solarflarecom.com>

On 6/27/2012 6:15 PM, Ben Hutchings wrote:
> On Thu, 2012-06-21 at 08:03 +0200, Giuseppe CAVALLARO wrote:
> [...]
>> v8: fixed a problem in the phy_init_eee return value erroneously added
>>     when included the phy_read_status call.
> 
> Almost there. :-/

no problem :-)

> [...]
>> +int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
>> +{
>> +	int ret = -EPROTONOSUPPORT;
>> +
>> +	/* According to 802.3az,the EEE is supported only in full duplex-mode.
>> +	 * Also EEE feature is active when core is operating with MII, GMII
>> +	 * or RGMII.
>> +	 */
>> +	if ((phydev->duplex == DUPLEX_FULL) &&
>> +	    ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
>> +	    (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
>> +	    (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
>> +		u16 eee_lp, eee_cap, eee_adv;
>> +		u32 lp, cap, adv;
>> +		int idx, status;

[snip]

>> +
>> +		eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
>> +						MDIO_MMD_AN, phydev->addr);
>> +		if (eee_adv < 0)
>> +			return eee_adv;
> 
> You check for eee_{cap,lp,adv} < 0 but that's impossible since the
> variables are declared unsigned (u16).  (I wonder what compiler you are
> using, as I would expect this to result in a warning.)  I think they
> need to be declared int.

IIRC I have compiled w/ no warnings (on arm  and sh4 -- gcc 4.6.3) but
you are right and I'll fix that, no problem at all.

[snip]

>> +			u32 val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
>> +							MDIO_MMD_PCS,
>> +							phydev->addr);
>> +			if (val < 0)
>> +				return val;
> 
> Same problem here.

yes

> 
> [...]
>> --- a/include/linux/mdio.h
>> +++ b/include/linux/mdio.h
> [...]
>> @@ -237,9 +241,18 @@
>>  #define MDIO_AN_10GBT_STAT_MS		0x4000	/* Master/slave config */
>>  #define MDIO_AN_10GBT_STAT_MSFLT	0x8000	/* Master/slave config fault */
>>  
>> -/* AN EEE Advertisement register. */
>> -#define MDIO_AN_EEE_ADV_100TX		0x0002	/* Advertise 100TX EEE cap */
>> -#define MDIO_AN_EEE_ADV_1000T		0x0004	/* Advertise 1000T EEE cap */
> [...]
> 
> This header is exported to userland so I don't think these definitions
> can be removed.  But you could comment that they're redundant with the
> following MDIO_EEE_* definitions.

Indeed I agree with you and I've already fixed this w/o removing them.
I'm sending the new patches now.

Thanks again for your feedback and help.

Peppe

> 
> Ben.
> 

^ permalink raw reply

* Re: [patch net-next] virtio_net: allow to change mac when iface is running
From: Jiri Pirko @ 2012-06-28  6:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, virtualization, brouer, mst
In-Reply-To: <20120627.213046.1244710404799995026.davem@davemloft.net>

Thu, Jun 28, 2012 at 06:30:46AM CEST, davem@davemloft.net wrote:
>From: Jiri Pirko <jpirko@redhat.com>
>Date: Wed, 27 Jun 2012 17:27:46 +0200
>
>> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>
>Applied, but this seriously makes eth_mac_addr() completely useless.
>
>Technically, every eth_mac_addr() user in a software/virtual device
>should behave the way virtio_net does now.

I guess to. But for some HW devices eth_mac_addr() is needed (when they
does not support "life" mac change")

>
>It therefore probably makes sense to add a boolean arg which when true
>elides the netif_running() check then fixup and audit every caller.

I was thinking about this. Maybe probably __eth_mac_addr() which does
not have netif_running() check and eth_mac_addr() calling
netif_running() check and __eth_mac_addr() after that.

What do you think?

Jirka

^ permalink raw reply


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