* [PATCH 08/16] batman-adv: tvlv - convert tt query packet to use tvlv unicast packets
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Marek Lindner <lindner_marek@yahoo.de>
Instead of generating TT specific packets the TVLV unicast API is used
to send translation table data.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/main.c | 2 -
net/batman-adv/packet.h | 33 ---
net/batman-adv/routing.c | 78 ------
net/batman-adv/translation-table.c | 498 +++++++++++++++++++++----------------
net/batman-adv/translation-table.h | 5 -
5 files changed, 284 insertions(+), 332 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index cb9a446..39d9b44 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -414,8 +414,6 @@ static void batadv_recv_handler_init(void)
batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
/* vis packet */
batadv_rx_handler[BATADV_VIS] = batadv_recv_vis_packet;
- /* Translation table query (request or response) */
- batadv_rx_handler[BATADV_TT_QUERY] = batadv_recv_tt_query;
/* Roaming advertisement */
batadv_rx_handler[BATADV_ROAM_ADV] = batadv_recv_roam_adv;
/* unicast tvlv packet */
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index cd59fcc..a602efc 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -31,7 +31,6 @@ enum batadv_packettype {
BATADV_BCAST = 0x04,
BATADV_VIS = 0x05,
BATADV_UNICAST_FRAG = 0x06,
- BATADV_TT_QUERY = 0x07,
BATADV_ROAM_ADV = 0x08,
BATADV_UNICAST_4ADDR = 0x09,
BATADV_CODED = 0x0a,
@@ -83,9 +82,6 @@ enum batadv_unicast_frag_flags {
BATADV_UNI_FRAG_LARGETAIL = BIT(1),
};
-/* TT_QUERY subtypes */
-#define BATADV_TT_QUERY_TYPE_MASK 0x3
-
/* tt data subtypes */
#define BATADV_TT_DATA_TYPE_MASK 0x0F
@@ -271,30 +267,6 @@ struct batadv_vis_packet {
uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
};
-struct batadv_tt_query_packet {
- struct batadv_header header;
- /* the flag field is a combination of:
- * - TT_REQUEST or TT_RESPONSE
- * - TT_FULL_TABLE
- */
- uint8_t flags;
- uint8_t dst[ETH_ALEN];
- uint8_t src[ETH_ALEN];
- /* the ttvn field is:
- * if TT_REQUEST: ttvn that triggered the
- * request
- * if TT_RESPONSE: new ttvn for the src
- * orig_node
- */
- uint8_t ttvn;
- /* tt_data field is:
- * if TT_REQUEST: crc associated with the
- * ttvn
- * if TT_RESPONSE: table_size
- */
- __be16 tt_data;
-} __packed;
-
struct batadv_roam_adv_packet {
struct batadv_header header;
uint8_t reserved;
@@ -303,11 +275,6 @@ struct batadv_roam_adv_packet {
uint8_t client[ETH_ALEN];
} __packed;
-struct batadv_tt_change {
- uint8_t flags;
- uint8_t addr[ETH_ALEN];
-} __packed;
-
/**
* struct batadv_coded_packet - network coded packet
* @header: common batman packet header and ttl of first included packet
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 9640656..d128581 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -557,84 +557,6 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
return 0;
}
-int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
-{
- struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
- struct batadv_tt_query_packet *tt_query;
- uint16_t tt_size;
- int hdr_size = sizeof(*tt_query);
- char tt_flag;
- size_t packet_size;
-
- if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
- return NET_RX_DROP;
-
- /* I could need to modify it */
- if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0)
- goto out;
-
- tt_query = (struct batadv_tt_query_packet *)skb->data;
-
- switch (tt_query->flags & BATADV_TT_QUERY_TYPE_MASK) {
- case BATADV_TT_REQUEST:
- batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
-
- /* If we cannot provide an answer the tt_request is
- * forwarded
- */
- if (!batadv_send_tt_response(bat_priv, tt_query)) {
- if (tt_query->flags & BATADV_TT_FULL_TABLE)
- tt_flag = 'F';
- else
- tt_flag = '.';
-
- batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Routing TT_REQUEST to %pM [%c]\n",
- tt_query->dst,
- tt_flag);
- return batadv_route_unicast_packet(skb, recv_if);
- }
- break;
- case BATADV_TT_RESPONSE:
- batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
-
- if (batadv_is_my_mac(bat_priv, tt_query->dst)) {
- /* packet needs to be linearized to access the TT
- * changes
- */
- if (skb_linearize(skb) < 0)
- goto out;
- /* skb_linearize() possibly changed skb->data */
- tt_query = (struct batadv_tt_query_packet *)skb->data;
-
- tt_size = batadv_tt_len(ntohs(tt_query->tt_data));
-
- /* Ensure we have all the claimed data */
- packet_size = sizeof(struct batadv_tt_query_packet);
- packet_size += tt_size;
- if (unlikely(skb_headlen(skb) < packet_size))
- goto out;
-
- batadv_handle_tt_response(bat_priv, tt_query);
- } else {
- if (tt_query->flags & BATADV_TT_FULL_TABLE)
- tt_flag = 'F';
- else
- tt_flag = '.';
- batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Routing TT_RESPONSE to %pM [%c]\n",
- tt_query->dst,
- tt_flag);
- return batadv_route_unicast_packet(skb, recv_if);
- }
- break;
- }
-
-out:
- /* returning NET_RX_DROP will make the caller function kfree the skb */
- return NET_RX_DROP;
-}
-
int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 3fac67f..22fce8a 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -229,9 +229,15 @@ unlock:
atomic_inc(&bat_priv->tt.local_changes);
}
-int batadv_tt_len(int changes_num)
+/**
+ * batadv_tt_len - compute length in bytes of given number of tt changes
+ * @changes_num: number of tt changes
+ *
+ * Returns computed length in bytes.
+ */
+static int batadv_tt_len(int changes_num)
{
- return changes_num * sizeof(struct batadv_tt_change);
+ return changes_num * sizeof(struct batadv_tvlv_tt_change);
}
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
@@ -1555,9 +1561,14 @@ unlock:
return tt_req_node;
}
-/* data_ptr is useless here, but has to be kept to respect the prototype */
-static int batadv_tt_local_valid_entry(const void *entry_ptr,
- const void *data_ptr)
+/**
+ * batadv_tt_local_valid - verify that given tt entry is a valid one
+ * @entry_ptr: to be checked local tt entry
+ * @data_ptr: not used but definition required to satisfy the callback prototype
+ *
+ * Returns 1 if the entry is a valid, 0 otherwise.
+ */
+static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
{
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
@@ -1584,41 +1595,45 @@ static int batadv_tt_global_valid(const void *entry_ptr,
return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
}
-static struct sk_buff *
-batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
- struct batadv_hashtable *hash,
- struct batadv_priv *bat_priv,
- int (*valid_cb)(const void *, const void *),
- void *cb_data)
+/**
+ * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the
+ * tt entries from the specified tt hash
+ * @bat_priv: the bat priv with all the soft interface information
+ * @hash: hash table containing the tt entries
+ * @tt_len: expected tvlv tt data buffer length in number of bytes
+ * @valid_cb: function to filter tt change entries
+ * @cb_data: data passed to the filter function as argument
+ *
+ * Returns pointer to allocated tvlv tt data buffer if operation was
+ * successful or NULL otherwise.
+ */
+static struct batadv_tvlv_tt_data *
+batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+ struct batadv_hashtable *hash, uint16_t tt_len,
+ int (*valid_cb)(const void *, const void *),
+ void *cb_data)
{
struct batadv_tt_common_entry *tt_common_entry;
- struct batadv_tt_query_packet *tt_response;
- struct batadv_tt_change *tt_change;
+ struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
+ struct batadv_tvlv_tt_change *tt_change;
struct hlist_head *head;
- struct sk_buff *skb = NULL;
- uint16_t tt_tot, tt_count;
- ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
+ uint16_t tt_tot, tt_num_entries = 0;
+ ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data);
uint32_t i;
- size_t len;
- if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) {
- tt_len = bat_priv->soft_iface->mtu - tt_query_size;
- tt_len -= tt_len % sizeof(struct batadv_tt_change);
+ if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) {
+ tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size;
+ tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
}
- tt_tot = tt_len / sizeof(struct batadv_tt_change);
- len = tt_query_size + tt_len;
- skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
- if (!skb)
+ tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change);
+
+ tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
+ GFP_ATOMIC);
+ if (!tvlv_tt_data)
goto out;
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, ETH_HLEN);
- tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
- tt_response->ttvn = ttvn;
-
- tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size);
- tt_count = 0;
+ tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1);
rcu_read_lock();
for (i = 0; i < hash->size; i++) {
@@ -1626,7 +1641,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
hlist_for_each_entry_rcu(tt_common_entry,
head, hash_entry) {
- if (tt_count == tt_tot)
+ if (tt_tot == tt_num_entries)
break;
if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
@@ -1635,20 +1650,16 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
memcpy(tt_change->addr, tt_common_entry->addr,
ETH_ALEN);
tt_change->flags = tt_common_entry->flags;
+ tt_change->reserved = 0;
- tt_count++;
+ tt_num_entries++;
tt_change++;
}
}
rcu_read_unlock();
- /* store in the message the number of entries we have successfully
- * copied
- */
- tt_response->tt_data = htons(tt_count);
-
out:
- return skb;
+ return tvlv_tt_data;
}
static int batadv_send_tt_request(struct batadv_priv *bat_priv,
@@ -1656,12 +1667,10 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
uint8_t ttvn, uint16_t tt_crc,
bool full_table)
{
- struct sk_buff *skb = NULL;
- struct batadv_tt_query_packet *tt_request;
+ struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
struct batadv_hard_iface *primary_if;
struct batadv_tt_req_node *tt_req_node = NULL;
- int ret = 1;
- size_t tt_req_len;
+ bool ret = false;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
@@ -1674,157 +1683,136 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (!tt_req_node)
goto out;
- skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN);
- if (!skb)
+ tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC);
+ if (!tvlv_tt_data)
goto out;
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, ETH_HLEN);
-
- tt_req_len = sizeof(*tt_request);
- tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
-
- tt_request->header.packet_type = BATADV_TT_QUERY;
- tt_request->header.version = BATADV_COMPAT_VERSION;
- memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
- tt_request->header.ttl = BATADV_TTL;
- tt_request->ttvn = ttvn;
- tt_request->tt_data = htons(tt_crc);
- tt_request->flags = BATADV_TT_REQUEST;
+ tvlv_tt_data->flags = BATADV_TT_REQUEST;
+ tvlv_tt_data->ttvn = ttvn;
+ tvlv_tt_data->crc = htons(tt_crc);
if (full_table)
- tt_request->flags |= BATADV_TT_FULL_TABLE;
+ tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
- dst_orig_node->orig, (full_table ? 'F' : '.'));
+ dst_orig_node->orig, full_table ? 'F' : '.');
batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
-
- if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP)
- ret = 0;
+ batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
+ dst_orig_node->orig, BATADV_TVLV_TT, 1,
+ tvlv_tt_data, sizeof(*tvlv_tt_data));
+ ret = true;
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- if (ret)
- kfree_skb(skb);
if (ret && tt_req_node) {
spin_lock_bh(&bat_priv->tt.req_list_lock);
list_del(&tt_req_node->list);
spin_unlock_bh(&bat_priv->tt.req_list_lock);
kfree(tt_req_node);
}
+ kfree(tvlv_tt_data);
return ret;
}
-static bool
-batadv_send_other_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_request)
+/**
+ * batadv_send_other_tt_response - send reply to tt request concerning another
+ * node's translation table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_data: tt data containing the tt request information
+ * @req_src: mac address of tt request sender
+ * @req_dst: mac address of tt request recipient
+ *
+ * Returns true if tt request reply was sent, false otherwise.
+ */
+static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
+ struct batadv_tvlv_tt_data *tt_data,
+ uint8_t *req_src, uint8_t *req_dst)
{
struct batadv_orig_node *req_dst_orig_node;
struct batadv_orig_node *res_dst_orig_node = NULL;
- uint8_t orig_ttvn, req_ttvn, ttvn;
- int res, ret = false;
- unsigned char *tt_buff;
- bool full_table;
- uint16_t tt_len, tt_tot;
- struct sk_buff *skb = NULL;
- struct batadv_tt_query_packet *tt_response;
- uint8_t *packet_pos;
- size_t len;
+ struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
+ uint8_t orig_ttvn, req_ttvn;
+ uint16_t tt_len;
+ bool ret = false, full_table;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
- tt_request->src, tt_request->ttvn, tt_request->dst,
- (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
+ req_src, tt_data->ttvn, req_dst,
+ (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
/* Let's get the orig node of the REAL destination */
- req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst);
+ req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
if (!req_dst_orig_node)
goto out;
- res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
+ res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
if (!res_dst_orig_node)
goto out;
orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
- req_ttvn = tt_request->ttvn;
+ req_ttvn = tt_data->ttvn;
- /* I don't have the requested data */
+ /* this node doesn't have the requested data */
if (orig_ttvn != req_ttvn ||
- tt_request->tt_data != htons(req_dst_orig_node->tt_crc))
+ tt_data->crc != htons(req_dst_orig_node->tt_crc))
goto out;
/* If the full table has been explicitly requested */
- if (tt_request->flags & BATADV_TT_FULL_TABLE ||
+ if (tt_data->flags & BATADV_TT_FULL_TABLE ||
!req_dst_orig_node->tt_buff)
full_table = true;
else
full_table = false;
- /* In this version, fragmentation is not implemented, then
- * I'll send only one packet with as much TT entries as I can
+ /* TT fragmentation hasn't been implemented yet, so send as many
+ * TT entries fit a single packet as possible only
*/
if (!full_table) {
spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
tt_len = req_dst_orig_node->tt_buff_len;
- tt_tot = tt_len / sizeof(struct batadv_tt_change);
- len = sizeof(*tt_response) + tt_len;
- skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
- if (!skb)
+ tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
+ GFP_ATOMIC);
+ if (!tvlv_tt_data)
goto unlock;
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, ETH_HLEN);
- packet_pos = skb_put(skb, len);
- tt_response = (struct batadv_tt_query_packet *)packet_pos;
- tt_response->ttvn = req_ttvn;
- tt_response->tt_data = htons(tt_tot);
-
- tt_buff = skb->data + sizeof(*tt_response);
/* Copy the last orig_node's OGM buffer */
- memcpy(tt_buff, req_dst_orig_node->tt_buff,
+ memcpy(tvlv_tt_data + 1, req_dst_orig_node->tt_buff,
req_dst_orig_node->tt_buff_len);
-
spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
} else {
tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
- tt_len *= sizeof(struct batadv_tt_change);
- ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
+ tt_len = batadv_tt_len(tt_len);
- skb = batadv_tt_response_fill_table(tt_len, ttvn,
- bat_priv->tt.global_hash,
- bat_priv,
- batadv_tt_global_valid,
- req_dst_orig_node);
- if (!skb)
+ tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
+ bat_priv->tt.global_hash,
+ tt_len,
+ batadv_tt_global_valid,
+ req_dst_orig_node);
+ if (!tvlv_tt_data)
goto out;
-
- tt_response = (struct batadv_tt_query_packet *)skb->data;
}
- tt_response->header.packet_type = BATADV_TT_QUERY;
- tt_response->header.version = BATADV_COMPAT_VERSION;
- tt_response->header.ttl = BATADV_TTL;
- memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
- memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
- tt_response->flags = BATADV_TT_RESPONSE;
+ tvlv_tt_data->flags = BATADV_TT_RESPONSE;
+ tvlv_tt_data->ttvn = req_ttvn;
if (full_table)
- tt_response->flags |= BATADV_TT_FULL_TABLE;
+ tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
- res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
+ "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
+ res_dst_orig_node->orig, req_dst_orig_node->orig,
+ full_table ? 'F' : '.', req_ttvn);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
- res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL);
- if (res != NET_XMIT_DROP)
- ret = true;
+ batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
+ req_src, BATADV_TVLV_TT, 1,
+ tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
+ ret = true;
goto out;
unlock:
@@ -1835,37 +1823,40 @@ out:
batadv_orig_node_free_ref(res_dst_orig_node);
if (req_dst_orig_node)
batadv_orig_node_free_ref(req_dst_orig_node);
- if (!ret)
- kfree_skb(skb);
+ kfree(tvlv_tt_data);
return ret;
}
-static bool
-batadv_send_my_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_request)
+/**
+ * batadv_send_my_tt_response - send reply to tt request concerning this node's
+ * translation table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_data: tt data containing the tt request information
+ * @req_src: mac address of tt request sender
+ *
+ * Returns true if tt request reply was sent, false otherwise.
+ */
+static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
+ struct batadv_tvlv_tt_data *tt_data,
+ uint8_t *req_src)
{
+ struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
struct batadv_orig_node *orig_node;
struct batadv_hard_iface *primary_if = NULL;
- uint8_t my_ttvn, req_ttvn, ttvn;
- int ret = false;
- unsigned char *tt_buff;
+ uint8_t my_ttvn, req_ttvn;
bool full_table;
- uint16_t tt_len, tt_tot;
- struct sk_buff *skb = NULL;
- struct batadv_tt_query_packet *tt_response;
- uint8_t *packet_pos;
- size_t len;
+ uint16_t tt_len;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
- tt_request->src, tt_request->ttvn,
- (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
+ req_src, tt_data->ttvn,
+ (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
- req_ttvn = tt_request->ttvn;
+ req_ttvn = tt_data->ttvn;
- orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
+ orig_node = batadv_orig_hash_find(bat_priv, req_src);
if (!orig_node)
goto out;
@@ -1876,71 +1867,58 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
/* If the full table has been explicitly requested or the gap
* is too big send the whole local translation table
*/
- if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
+ if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
!bat_priv->tt.last_changeset)
full_table = true;
else
full_table = false;
- /* In this version, fragmentation is not implemented, then
- * I'll send only one packet with as much TT entries as I can
+ /* TT fragmentation hasn't been implemented yet, so send as many
+ * TT entries fit a single packet as possible only
*/
if (!full_table) {
spin_lock_bh(&bat_priv->tt.last_changeset_lock);
tt_len = bat_priv->tt.last_changeset_len;
- tt_tot = tt_len / sizeof(struct batadv_tt_change);
- len = sizeof(*tt_response) + tt_len;
- skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
- if (!skb)
+ tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
+ GFP_ATOMIC);
+ if (!tvlv_tt_data)
goto unlock;
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, ETH_HLEN);
- packet_pos = skb_put(skb, len);
- tt_response = (struct batadv_tt_query_packet *)packet_pos;
- tt_response->ttvn = req_ttvn;
- tt_response->tt_data = htons(tt_tot);
-
- tt_buff = skb->data + sizeof(*tt_response);
- memcpy(tt_buff, bat_priv->tt.last_changeset,
+ /* Copy the last orig_node's OGM buffer */
+ memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset,
bat_priv->tt.last_changeset_len);
spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
} else {
tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
- tt_len *= sizeof(struct batadv_tt_change);
- ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+ tt_len = batadv_tt_len(tt_len);
+ req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
- skb = batadv_tt_response_fill_table(tt_len, ttvn,
- bat_priv->tt.local_hash,
- bat_priv,
- batadv_tt_local_valid_entry,
- NULL);
- if (!skb)
+ tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
+ bat_priv->tt.local_hash,
+ tt_len,
+ batadv_tt_local_valid,
+ NULL);
+ if (!tvlv_tt_data)
goto out;
-
- tt_response = (struct batadv_tt_query_packet *)skb->data;
}
- tt_response->header.packet_type = BATADV_TT_QUERY;
- tt_response->header.version = BATADV_COMPAT_VERSION;
- tt_response->header.ttl = BATADV_TTL;
- memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
- tt_response->flags = BATADV_TT_RESPONSE;
+ tvlv_tt_data->flags = BATADV_TT_RESPONSE;
+ tvlv_tt_data->ttvn = req_ttvn;
if (full_table)
- tt_response->flags |= BATADV_TT_FULL_TABLE;
+ tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending TT_RESPONSE to %pM [%c]\n",
- orig_node->orig,
- (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
+ "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
+ orig_node->orig, full_table ? 'F' : '.', req_ttvn);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
- ret = true;
+ batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
+ req_src, BATADV_TVLV_TT, 1,
+ tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
+
goto out;
unlock:
@@ -1950,29 +1928,39 @@ out:
batadv_orig_node_free_ref(orig_node);
if (primary_if)
batadv_hardif_free_ref(primary_if);
- if (!ret)
- kfree_skb(skb);
- /* This packet was for me, so it doesn't need to be re-routed */
+ kfree(tvlv_tt_data);
+ /* The packet was for this host, so it doesn't need to be re-routed */
return true;
}
-bool batadv_send_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_request)
+/**
+ * batadv_send_tt_response - send reply to tt request
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_data: tt data containing the tt request information
+ * @req_src: mac address of tt request sender
+ * @req_dst: mac address of tt request recipient
+ *
+ * Returns true if tt request reply was sent, false otherwise.
+ */
+static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
+ struct batadv_tvlv_tt_data *tt_data,
+ uint8_t *req_src, uint8_t *req_dst)
{
- if (batadv_is_my_mac(bat_priv, tt_request->dst)) {
+ if (batadv_is_my_mac(bat_priv, req_dst)) {
/* don't answer backbone gws! */
- if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src))
+ if (batadv_bla_is_backbone_gw_orig(bat_priv, req_src))
return true;
- return batadv_send_my_tt_response(bat_priv, tt_request);
+ return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
} else {
- return batadv_send_other_tt_response(bat_priv, tt_request);
+ return batadv_send_other_tt_response(bat_priv, tt_data,
+ req_src, req_dst);
}
}
static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- struct batadv_tt_change *tt_change,
+ struct batadv_tvlv_tt_change *tt_change,
uint16_t tt_num_changes, uint8_t ttvn)
{
int i;
@@ -2002,11 +1990,12 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
}
static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_response)
+ struct batadv_tvlv_tt_data *tt_data,
+ uint8_t *resp_src, uint16_t num_entries)
{
struct batadv_orig_node *orig_node;
- orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
+ orig_node = batadv_orig_hash_find(bat_priv, resp_src);
if (!orig_node)
goto out;
@@ -2014,9 +2003,8 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
_batadv_tt_update_changes(bat_priv, orig_node,
- (struct batadv_tt_change *)(tt_response + 1),
- ntohs(tt_response->tt_data),
- tt_response->ttvn);
+ (struct batadv_tvlv_tt_change *)(tt_data + 1),
+ num_entries, tt_data->ttvn);
spin_lock_bh(&orig_node->tt_buff_lock);
kfree(orig_node->tt_buff);
@@ -2024,7 +2012,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
orig_node->tt_buff = NULL;
spin_unlock_bh(&orig_node->tt_buff_lock);
- atomic_set(&orig_node->last_ttvn, tt_response->ttvn);
+ atomic_set(&orig_node->last_ttvn, tt_data->ttvn);
out:
if (orig_node)
@@ -2034,7 +2022,7 @@ out:
static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
uint16_t tt_num_changes, uint8_t ttvn,
- struct batadv_tt_change *tt_change)
+ struct batadv_tvlv_tt_change *tt_change)
{
_batadv_tt_update_changes(bat_priv, orig_node, tt_change,
tt_num_changes, ttvn);
@@ -2065,40 +2053,46 @@ out:
return ret;
}
-void batadv_handle_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_response)
+/**
+ * batadv_handle_tt_response - process incoming tt reply
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_data: tt data containing the tt request information
+ * @resp_src: mac address of tt reply sender
+ * @num_entries: number of tt change entries appended to the tt data
+ */
+static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
+ struct batadv_tvlv_tt_data *tt_data,
+ uint8_t *resp_src, uint16_t num_entries)
{
struct batadv_tt_req_node *node, *safe;
struct batadv_orig_node *orig_node = NULL;
- struct batadv_tt_change *tt_change;
+ struct batadv_tvlv_tt_change *tt_change;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
- tt_response->src, tt_response->ttvn,
- ntohs(tt_response->tt_data),
- (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
+ resp_src, tt_data->ttvn, num_entries,
+ (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
/* we should have never asked a backbone gw */
- if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src))
+ if (batadv_bla_is_backbone_gw_orig(bat_priv, resp_src))
goto out;
- orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
+ orig_node = batadv_orig_hash_find(bat_priv, resp_src);
if (!orig_node)
goto out;
- if (tt_response->flags & BATADV_TT_FULL_TABLE) {
- batadv_tt_fill_gtable(bat_priv, tt_response);
+ if (tt_data->flags & BATADV_TT_FULL_TABLE) {
+ batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries);
} else {
- tt_change = (struct batadv_tt_change *)(tt_response + 1);
- batadv_tt_update_changes(bat_priv, orig_node,
- ntohs(tt_response->tt_data),
- tt_response->ttvn, tt_change);
+ tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
+ batadv_tt_update_changes(bat_priv, orig_node, num_entries,
+ tt_data->ttvn, tt_change);
}
/* Delete the tt_req_node from pending tt_requests list */
spin_lock_bh(&bat_priv->tt.req_list_lock);
list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
- if (!batadv_compare_eth(node->addr, tt_response->src))
+ if (!batadv_compare_eth(node->addr, resp_src))
continue;
list_del(&node->list);
kfree(node);
@@ -2437,7 +2431,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
{
uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
bool full_table = true;
- struct batadv_tt_change *tt_change;
+ struct batadv_tvlv_tt_change *tt_change;
/* don't care about a backbone gateways updates. */
if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
@@ -2458,7 +2452,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
goto request_table;
}
- tt_change = (struct batadv_tt_change *)tt_buff;
+ tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
ttvn, tt_change);
@@ -2599,6 +2593,81 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
}
/**
+ * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv
+ * container
+ * @bat_priv: the bat priv with all the soft interface information
+ * @src: mac address of tt tvlv sender
+ * @dst: mac address of tt tvlv recipient
+ * @tvlv_value: tvlv buffer containing the tt data
+ * @tvlv_value_len: tvlv buffer length
+ *
+ * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
+ * otherwise.
+ */
+static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
+ uint8_t *src, uint8_t *dst,
+ void *tvlv_value,
+ uint16_t tvlv_value_len)
+{
+ struct batadv_tvlv_tt_data *tt_data;
+ uint16_t num_entries;
+ char tt_flag;
+ bool ret;
+
+ if (tvlv_value_len < sizeof(*tt_data))
+ return NET_RX_SUCCESS;
+
+ tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
+ tvlv_value_len -= sizeof(*tt_data);
+
+ num_entries = tvlv_value_len / batadv_tt_len(1);
+
+ switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
+ case BATADV_TT_REQUEST:
+ batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
+
+ /* If this node cannot provide a TT response the tt_request is
+ * forwarded
+ */
+ ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
+ if (!ret) {
+ if (tt_data->flags & BATADV_TT_FULL_TABLE)
+ tt_flag = 'F';
+ else
+ tt_flag = '.';
+
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Routing TT_REQUEST to %pM [%c]\n",
+ dst, tt_flag);
+ /* tvlv API will re-route the packet */
+ return NET_RX_DROP;
+ }
+ break;
+ case BATADV_TT_RESPONSE:
+ batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
+
+ if (batadv_is_my_mac(bat_priv, dst)) {
+ batadv_handle_tt_response(bat_priv, tt_data,
+ src, num_entries);
+ return NET_RX_SUCCESS;
+ }
+
+ if (tt_data->flags & BATADV_TT_FULL_TABLE)
+ tt_flag = 'F';
+ else
+ tt_flag = '.';
+
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
+
+ /* tvlv API will re-route the packet */
+ return NET_RX_DROP;
+ }
+
+ return NET_RX_SUCCESS;
+}
+
+/**
* batadv_tt_init - initialise the translation table internals
* @bat_priv: the bat priv with all the soft interface information
*
@@ -2617,7 +2686,8 @@ int batadv_tt_init(struct batadv_priv *bat_priv)
return ret;
batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
- NULL, BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
+ batadv_tt_tvlv_unicast_handler_v1,
+ BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index a709249..b4b6dea 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -20,7 +20,6 @@
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
-int batadv_tt_len(int changes_num);
int batadv_tt_init(struct batadv_priv *bat_priv);
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex);
@@ -43,11 +42,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
const uint8_t *src,
const uint8_t *addr);
void batadv_tt_free(struct batadv_priv *bat_priv);
-bool batadv_send_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_request);
bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr);
-void batadv_handle_tt_response(struct batadv_priv *bat_priv,
- struct batadv_tt_query_packet *tt_response);
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
uint8_t *dst);
void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv);
--
1.8.3.2
^ permalink raw reply related
* [BUG Linux 3.11] Bonding : possible circular locking dependency detected
From: leroy christophe @ 2013-10-09 12:41 UTC (permalink / raw)
To: netdev
When configuring bonding in mode 1 with mii_status polling, I get the
following warning
[ 841.582838] ======================================================
[ 841.588946] [ INFO: possible circular locking dependency detected ]
[ 841.595168] 3.11.0-draft-drv-999-svn5204~_knld-999-svn5212 #220
Tainted: G W
[ 841.602975] -------------------------------------------------------
[ 841.609184] kworker/0:2/747 is trying to acquire lock:
[ 841.614246] (&bond->curr_slave_lock){++.+..}, at: [<c02654e4>]
bond_set_rx_mode+0xb4/0x10c
[ 841.622511]
[ 841.622511] but task is already holding lock:
[ 841.628274] (&bonding_netdev_addr_lock_key){+.....}, at:
[<c02d9eb8>] __dev_mc_add+0x3c/0x90
[ 841.636711]
[ 841.636711] which lock already depends on the new lock.
[ 841.636711]
[ 841.644799]
[ 841.644799] the existing dependency chain (in reverse order) is:
[ 841.652201]
-> #1 (&bonding_netdev_addr_lock_key){+.....}:
[ 841.657792] [<c006fb38>] __lock_acquire+0x394/0xb8c
[ 841.663216] [<c00703e4>] lock_acquire+0xb4/0x16c
[ 841.668379] [<c0404dcc>] _raw_spin_lock_bh+0x54/0x70
[ 841.673886] [<c02674fc>] bond_change_active_slave+0x278/0x5d0
[ 841.680169] [<c02678f8>] bond_select_active_slave+0xa4/0x1c4
[ 841.686365] [<c0267ebc>] bond_mii_monitor+0x4a4/0x6e0
[ 841.691960] [<c0039acc>] process_one_work+0x204/0x5ac
[ 841.697554] [<c0039fcc>] worker_thread+0x158/0x43c
[ 841.702889] [<c0043310>] kthread+0xc8/0xcc
[ 841.707536] [<c000ea18>] ret_from_kernel_thread+0x5c/0x64
[ 841.713483]
-> #0 (&bond->curr_slave_lock){++.+..}:
[ 841.718463] [<c006f5f4>] validate_chain+0xec4/0x1074
[ 841.723974] [<c006fb38>] __lock_acquire+0x394/0xb8c
[ 841.729396] [<c00703e4>] lock_acquire+0xb4/0x16c
[ 841.734560] [<c040540c>] _raw_read_lock+0x50/0x6c
[ 841.739809] [<c02654e4>] bond_set_rx_mode+0xb4/0x10c
[ 841.745318] [<c02ce428>] __dev_set_rx_mode+0x80/0xd0
[ 841.750825] [<c02d9ee4>] __dev_mc_add+0x68/0x90
[ 841.755902] [<c02d9f5c>] dev_mc_add+0x20/0x30
[ 841.760808] [<c03ac1d4>] igmp6_group_added+0x108/0x1e4
[ 841.766488] [<c03ac2f4>] ipv6_mc_up+0x44/0x70
[ 841.771393] [<c038e0cc>] ipv6_find_idev+0x58/0xb0
[ 841.776643] [<c038e15c>] addrconf_add_dev+0x38/0xc0
[ 841.782065] [<c0390ec0>] addrconf_notify+0x2b8/0x978
[ 841.787572] [<c004a974>] notifier_call_chain+0x78/0xdc
[ 841.793252] [<c004ab08>] raw_notifier_call_chain+0x24/0x34
[ 841.799277] [<c02d2430>] call_netdevice_notifiers_info+0x74/0x90
[ 841.805818] [<c02d246c>] call_netdevice_notifiers+0x20/0x30
[ 841.811928] [<c02d380c>] netdev_state_change+0x38/0x5c
[ 841.817608] [<c02e6804>] linkwatch_do_dev+0x64/0xa8
[ 841.823031] [<c02e6c7c>] __linkwatch_run_queue+0x10c/0x214
[ 841.829054] [<c02e6dbc>] linkwatch_event+0x38/0x4c
[ 841.834390] [<c0039acc>] process_one_work+0x204/0x5ac
[ 841.839984] [<c0039fcc>] worker_thread+0x158/0x43c
[ 841.845320] [<c0043310>] kthread+0xc8/0xcc
[ 841.849966] [<c000ea18>] ret_from_kernel_thread+0x5c/0x64
[ 841.855908]
[ 841.855908] other info that might help us debug this:
[ 841.855908]
[ 841.863824] Possible unsafe locking scenario:
[ 841.863824]
[ 841.869674] CPU0 CPU1
[ 841.874149] ---- ----
[ 841.878620] lock(&bonding_netdev_addr_lock_key);
[ 841.883352] lock(&bond->curr_slave_lock);
[ 841.889979] lock(&bonding_netdev_addr_lock_key);
[ 841.897206] lock(&bond->curr_slave_lock);
[ 841.901340]
[ 841.901340] *** DEADLOCK ***
[ 841.901340]
[ 841.907217] 7 locks held by kworker/0:2/747:
[ 841.911416] #0: (events){.+.+..}, at: [<c0039a44>]
process_one_work+0x17c/0x5ac
[ 841.918822] #1: ((linkwatch_work).work){+.+...}, at: [<c0039a44>]
process_one_work+0x17c/0x5ac
[ 841.927515] #2: (rtnl_mutex){+.+.+.}, at: [<c02e4ae0>]
rtnl_lock+0x28/0x38
[ 841.934486] #3: (&ndev->lock){++--..}, at: [<c03ac2e0>]
ipv6_mc_up+0x30/0x70
[ 841.941627] #4: (&(&mc->mca_lock)->rlock){+.-...}, at: [<c03ac120>]
igmp6_group_added+0x54/0x1e4
[ 841.950492] #5: (&bonding_netdev_addr_lock_key){+.....}, at:
[<c02d9eb8>] __dev_mc_add+0x3c/0x90
[ 841.959356] #6: (&bond->lock){++.?..}, at: [<c0265470>]
bond_set_rx_mode+0x40/0x10c
[ 841.967097]
[ 841.967097] stack backtrace:
[ 841.971448] CPU: 0 PID: 747 Comm: kworker/0:2 Tainted: G W
3.11.0-draft-drv-999-svn5204~_knld-999-svn5212 #220
[ 841.982222] Workqueue: events linkwatch_event
[ 841.986457] Call Trace:
[ 841.988931] [c7b71a00] [c0007198] show_stack+0xa8/0x238 (unreliable)
[ 841.995210] [c7b71a50] [c0405e8c] dump_stack+0x24/0x198
[ 842.000390] [c7b71a60] [c006dec8] print_circular_bug+0x1f8/0x320
[ 842.006313] [c7b71a90] [c006f5f4] validate_chain+0xec4/0x1074
[ 842.011993] [c7b71b20] [c006fb38] __lock_acquire+0x394/0xb8c
[ 842.017585] [c7b71b80] [c00703e4] lock_acquire+0xb4/0x16c
[ 842.022916] [c7b71bc0] [c040540c] _raw_read_lock+0x50/0x6c
[ 842.028352] [c7b71be0] [c02654e4] bond_set_rx_mode+0xb4/0x10c
[ 842.034029] [c7b71c00] [c02ce428] __dev_set_rx_mode+0x80/0xd0
[ 842.039698] [c7b71c20] [c02d9ee4] __dev_mc_add+0x68/0x90
[ 842.044945] [c7b71c40] [c02d9f5c] dev_mc_add+0x20/0x30
[ 842.050031] [c7b71c50] [c03ac1d4] igmp6_group_added+0x108/0x1e4
[ 842.055872] [c7b71c90] [c03ac2f4] ipv6_mc_up+0x44/0x70
[ 842.060958] [c7b71ca0] [c038e0cc] ipv6_find_idev+0x58/0xb0
[ 842.066373] [c7b71cb0] [c038e15c] addrconf_add_dev+0x38/0xc0
[ 842.071970] [c7b71cc0] [c0390ec0] addrconf_notify+0x2b8/0x978
[ 842.077652] [c7b71d60] [c004a974] notifier_call_chain+0x78/0xdc
[ 842.083501] [c7b71d90] [c004ab08] raw_notifier_call_chain+0x24/0x34
[ 842.089716] [c7b71da0] [c02d2430] call_netdevice_notifiers_info+0x74/0x90
[ 842.096416] [c7b71dc0] [c02d246c] call_netdevice_notifiers+0x20/0x30
[ 842.102699] [c7b71de0] [c02d380c] netdev_state_change+0x38/0x5c
[ 842.108567] [c7b71df0] [c02e6804] linkwatch_do_dev+0x64/0xa8
[ 842.114148] [c7b71e00] [c02e6c7c] __linkwatch_run_queue+0x10c/0x214
[ 842.120342] [c7b71e30] [c02e6dbc] linkwatch_event+0x38/0x4c
[ 842.125858] [c7b71e40] [c0039acc] process_one_work+0x204/0x5ac
[ 842.131611] [c7b71e80] [c0039fcc] worker_thread+0x158/0x43c
[ 842.137117] [c7b71eb0] [c0043310] kthread+0xc8/0xcc
[ 842.141943] [c7b71f40] [c000ea18] ret_from_kernel_thread+0x5c/0x64
Christophe
^ permalink raw reply
* Re: [BUG Linux 3.11] Bonding : possible circular locking dependency detected
From: Veaceslav Falico @ 2013-10-09 12:50 UTC (permalink / raw)
To: leroy christophe; +Cc: netdev
In-Reply-To: <52554F10.9000904@c-s.fr>
On Wed, Oct 09, 2013 at 02:41:52PM +0200, leroy christophe wrote:
>When configuring bonding in mode 1 with mii_status polling, I get the
>following warning
>
>
>[ 841.582838] ======================================================
>[ 841.588946] [ INFO: possible circular locking dependency detected ]
>[ 841.595168] 3.11.0-draft-drv-999-svn5204~_knld-999-svn5212 #220
>Tainted: G W
>[ 841.602975] -------------------------------------------------------
>[ 841.609184] kworker/0:2/747 is trying to acquire lock:
>[ 841.614246] (&bond->curr_slave_lock){++.+..}, at: [<c02654e4>]
>bond_set_rx_mode+0xb4/0x10c
It should go away in fresh kernels. One patch that for sure fixes it:
b32418 bonding: RCUify bond_set_rx_mode()
However it might have been fixed even before that.
>[ 841.622511]
>[ 841.622511] but task is already holding lock:
>[ 841.628274] (&bonding_netdev_addr_lock_key){+.....}, at:
>[<c02d9eb8>] __dev_mc_add+0x3c/0x90
>[ 841.636711]
>[ 841.636711] which lock already depends on the new lock.
>[ 841.636711]
>[ 841.644799]
>[ 841.644799] the existing dependency chain (in reverse order) is:
>[ 841.652201]
>-> #1 (&bonding_netdev_addr_lock_key){+.....}:
>[ 841.657792] [<c006fb38>] __lock_acquire+0x394/0xb8c
>[ 841.663216] [<c00703e4>] lock_acquire+0xb4/0x16c
>[ 841.668379] [<c0404dcc>] _raw_spin_lock_bh+0x54/0x70
>[ 841.673886] [<c02674fc>] bond_change_active_slave+0x278/0x5d0
>[ 841.680169] [<c02678f8>] bond_select_active_slave+0xa4/0x1c4
>[ 841.686365] [<c0267ebc>] bond_mii_monitor+0x4a4/0x6e0
>[ 841.691960] [<c0039acc>] process_one_work+0x204/0x5ac
>[ 841.697554] [<c0039fcc>] worker_thread+0x158/0x43c
>[ 841.702889] [<c0043310>] kthread+0xc8/0xcc
>[ 841.707536] [<c000ea18>] ret_from_kernel_thread+0x5c/0x64
>[ 841.713483]
>-> #0 (&bond->curr_slave_lock){++.+..}:
>[ 841.718463] [<c006f5f4>] validate_chain+0xec4/0x1074
>[ 841.723974] [<c006fb38>] __lock_acquire+0x394/0xb8c
>[ 841.729396] [<c00703e4>] lock_acquire+0xb4/0x16c
>[ 841.734560] [<c040540c>] _raw_read_lock+0x50/0x6c
>[ 841.739809] [<c02654e4>] bond_set_rx_mode+0xb4/0x10c
>[ 841.745318] [<c02ce428>] __dev_set_rx_mode+0x80/0xd0
>[ 841.750825] [<c02d9ee4>] __dev_mc_add+0x68/0x90
>[ 841.755902] [<c02d9f5c>] dev_mc_add+0x20/0x30
>[ 841.760808] [<c03ac1d4>] igmp6_group_added+0x108/0x1e4
>[ 841.766488] [<c03ac2f4>] ipv6_mc_up+0x44/0x70
>[ 841.771393] [<c038e0cc>] ipv6_find_idev+0x58/0xb0
>[ 841.776643] [<c038e15c>] addrconf_add_dev+0x38/0xc0
>[ 841.782065] [<c0390ec0>] addrconf_notify+0x2b8/0x978
>[ 841.787572] [<c004a974>] notifier_call_chain+0x78/0xdc
>[ 841.793252] [<c004ab08>] raw_notifier_call_chain+0x24/0x34
>[ 841.799277] [<c02d2430>] call_netdevice_notifiers_info+0x74/0x90
>[ 841.805818] [<c02d246c>] call_netdevice_notifiers+0x20/0x30
>[ 841.811928] [<c02d380c>] netdev_state_change+0x38/0x5c
>[ 841.817608] [<c02e6804>] linkwatch_do_dev+0x64/0xa8
>[ 841.823031] [<c02e6c7c>] __linkwatch_run_queue+0x10c/0x214
>[ 841.829054] [<c02e6dbc>] linkwatch_event+0x38/0x4c
>[ 841.834390] [<c0039acc>] process_one_work+0x204/0x5ac
>[ 841.839984] [<c0039fcc>] worker_thread+0x158/0x43c
>[ 841.845320] [<c0043310>] kthread+0xc8/0xcc
>[ 841.849966] [<c000ea18>] ret_from_kernel_thread+0x5c/0x64
>[ 841.855908]
>[ 841.855908] other info that might help us debug this:
>[ 841.855908]
>[ 841.863824] Possible unsafe locking scenario:
>[ 841.863824]
>[ 841.869674] CPU0 CPU1
>[ 841.874149] ---- ----
>[ 841.878620] lock(&bonding_netdev_addr_lock_key);
>[ 841.883352] lock(&bond->curr_slave_lock);
>[ 841.889979] lock(&bonding_netdev_addr_lock_key);
>[ 841.897206] lock(&bond->curr_slave_lock);
>[ 841.901340]
>[ 841.901340] *** DEADLOCK ***
>[ 841.901340]
>[ 841.907217] 7 locks held by kworker/0:2/747:
>[ 841.911416] #0: (events){.+.+..}, at: [<c0039a44>]
>process_one_work+0x17c/0x5ac
>[ 841.918822] #1: ((linkwatch_work).work){+.+...}, at:
>[<c0039a44>] process_one_work+0x17c/0x5ac
>[ 841.927515] #2: (rtnl_mutex){+.+.+.}, at: [<c02e4ae0>]
>rtnl_lock+0x28/0x38
>[ 841.934486] #3: (&ndev->lock){++--..}, at: [<c03ac2e0>]
>ipv6_mc_up+0x30/0x70
>[ 841.941627] #4: (&(&mc->mca_lock)->rlock){+.-...}, at:
>[<c03ac120>] igmp6_group_added+0x54/0x1e4
>[ 841.950492] #5: (&bonding_netdev_addr_lock_key){+.....}, at:
>[<c02d9eb8>] __dev_mc_add+0x3c/0x90
>[ 841.959356] #6: (&bond->lock){++.?..}, at: [<c0265470>]
>bond_set_rx_mode+0x40/0x10c
>[ 841.967097]
>[ 841.967097] stack backtrace:
>[ 841.971448] CPU: 0 PID: 747 Comm: kworker/0:2 Tainted: G W
>3.11.0-draft-drv-999-svn5204~_knld-999-svn5212 #220
>[ 841.982222] Workqueue: events linkwatch_event
>[ 841.986457] Call Trace:
>[ 841.988931] [c7b71a00] [c0007198] show_stack+0xa8/0x238 (unreliable)
>[ 841.995210] [c7b71a50] [c0405e8c] dump_stack+0x24/0x198
>[ 842.000390] [c7b71a60] [c006dec8] print_circular_bug+0x1f8/0x320
>[ 842.006313] [c7b71a90] [c006f5f4] validate_chain+0xec4/0x1074
>[ 842.011993] [c7b71b20] [c006fb38] __lock_acquire+0x394/0xb8c
>[ 842.017585] [c7b71b80] [c00703e4] lock_acquire+0xb4/0x16c
>[ 842.022916] [c7b71bc0] [c040540c] _raw_read_lock+0x50/0x6c
>[ 842.028352] [c7b71be0] [c02654e4] bond_set_rx_mode+0xb4/0x10c
>[ 842.034029] [c7b71c00] [c02ce428] __dev_set_rx_mode+0x80/0xd0
>[ 842.039698] [c7b71c20] [c02d9ee4] __dev_mc_add+0x68/0x90
>[ 842.044945] [c7b71c40] [c02d9f5c] dev_mc_add+0x20/0x30
>[ 842.050031] [c7b71c50] [c03ac1d4] igmp6_group_added+0x108/0x1e4
>[ 842.055872] [c7b71c90] [c03ac2f4] ipv6_mc_up+0x44/0x70
>[ 842.060958] [c7b71ca0] [c038e0cc] ipv6_find_idev+0x58/0xb0
>[ 842.066373] [c7b71cb0] [c038e15c] addrconf_add_dev+0x38/0xc0
>[ 842.071970] [c7b71cc0] [c0390ec0] addrconf_notify+0x2b8/0x978
>[ 842.077652] [c7b71d60] [c004a974] notifier_call_chain+0x78/0xdc
>[ 842.083501] [c7b71d90] [c004ab08] raw_notifier_call_chain+0x24/0x34
>[ 842.089716] [c7b71da0] [c02d2430] call_netdevice_notifiers_info+0x74/0x90
>[ 842.096416] [c7b71dc0] [c02d246c] call_netdevice_notifiers+0x20/0x30
>[ 842.102699] [c7b71de0] [c02d380c] netdev_state_change+0x38/0x5c
>[ 842.108567] [c7b71df0] [c02e6804] linkwatch_do_dev+0x64/0xa8
>[ 842.114148] [c7b71e00] [c02e6c7c] __linkwatch_run_queue+0x10c/0x214
>[ 842.120342] [c7b71e30] [c02e6dbc] linkwatch_event+0x38/0x4c
>[ 842.125858] [c7b71e40] [c0039acc] process_one_work+0x204/0x5ac
>[ 842.131611] [c7b71e80] [c0039fcc] worker_thread+0x158/0x43c
>[ 842.137117] [c7b71eb0] [c0043310] kthread+0xc8/0xcc
>[ 842.141943] [c7b71f40] [c000ea18] ret_from_kernel_thread+0x5c/0x64
>
>Christophe
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH RFC 00/77] Re-design MSI/MSI-X interrupts enablement pattern
From: Alexander Gordeev @ 2013-10-09 12:57 UTC (permalink / raw)
To: Tejun Heo
Cc: Benjamin Herrenschmidt, Ben Hutchings, linux-kernel,
Bjorn Helgaas, Ralf Baechle, Michael Ellerman, Martin Schwidefsky,
Ingo Molnar, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390, x86,
linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-devel
In-Reply-To: <20131007180111.GC2481@htj.dyndns.org>
On Mon, Oct 07, 2013 at 02:01:11PM -0400, Tejun Heo wrote:
> Hmmm... yean, the race condition could be an issue as multiple msi
> allocation might fail even if the driver can and explicitly handle
> multiple allocation if the quota gets reduced inbetween.
BTW, should we care about the quota getting increased inbetween?
That would entail.. kind of pci_get_msi_limit() :), but IMHO it is
not worth it.
> tejun
--
Regards,
Alexander Gordeev
agordeev@redhat.com
^ permalink raw reply
* [PATCH 15/16] batman-adv: remove packed from batadv_ogm_packet
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
Marek Lindner, Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
As we decreased the struct size from 26 to 24 byte, we can remove
__packed as the compiler will not add any more padding.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/packet.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index f02dbb1..4e5fe7d 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -175,7 +175,10 @@ struct batadv_ogm_packet {
uint8_t reserved;
uint8_t tq;
__be16 tvlv_len;
-} __packed;
+ /* __packed is not needed as the struct size is divisible by 4,
+ * and the largest data type in this struct has a size of 4.
+ */
+};
#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 12/16] batman-adv: remove vis functionality
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Marek Lindner,
Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
This is replaced by a userspace program, we don't need this
functionality to bloat the kernel.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
Documentation/ABI/testing/sysfs-class-net-mesh | 11 -
Documentation/networking/batman-adv.txt | 50 +-
net/batman-adv/Makefile | 1 -
net/batman-adv/bat_iv_ogm.c | 8 -
net/batman-adv/debugfs.c | 9 -
net/batman-adv/hard-interface.c | 9 -
net/batman-adv/main.c | 11 -
net/batman-adv/main.h | 2 -
net/batman-adv/packet.h | 21 +-
net/batman-adv/routing.c | 51 --
net/batman-adv/routing.h | 2 -
net/batman-adv/send.c | 1 -
net/batman-adv/soft-interface.c | 1 -
net/batman-adv/sysfs.c | 72 --
net/batman-adv/types.h | 84 ---
net/batman-adv/vis.c | 938 -------------------------
net/batman-adv/vis.h | 36 -
17 files changed, 3 insertions(+), 1304 deletions(-)
delete mode 100644 net/batman-adv/vis.c
delete mode 100644 net/batman-adv/vis.h
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index bdcd8b4..f00a69b 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -88,14 +88,3 @@ Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Defines the routing procotol this mesh instance
uses to find the optimal paths through the mesh.
-
-What: /sys/class/net/<mesh_iface>/mesh/vis_mode
-Date: May 2010
-Contact: Marek Lindner <lindner_marek@yahoo.de>
-Description:
- Each batman node only maintains information about its
- own local neighborhood, therefore generating graphs
- showing the topology of the entire mesh is not easily
- feasible without having a central instance to collect
- the local topologies from all nodes. This file allows
- to activate the collecting (server) mode.
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index c1d8204..897d1f4 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -69,8 +69,7 @@ folder:
# aggregated_ogms gw_bandwidth log_level
# ap_isolation gw_mode orig_interval
# bonding gw_sel_class routing_algo
-# bridge_loop_avoidance hop_penalty vis_mode
-# fragmentation
+# bridge_loop_avoidance hop_penalty fragmentation
There is a special folder for debugging information:
@@ -78,7 +77,7 @@ There is a special folder for debugging information:
# ls /sys/kernel/debug/batman_adv/bat0/
# bla_backbone_table log transtable_global
# bla_claim_table originators transtable_local
-# gateways socket vis_data
+# gateways socket
Some of the files contain all sort of status information regard-
ing the mesh network. For example, you can view the table of
@@ -127,51 +126,6 @@ ously assigned to interfaces now used by batman advanced, e.g.
# ifconfig eth0 0.0.0.0
-VISUALIZATION
--------------
-
-If you want topology visualization, at least one mesh node must
-be configured as VIS-server:
-
-# echo "server" > /sys/class/net/bat0/mesh/vis_mode
-
-Each node is either configured as "server" or as "client" (de-
-fault: "client"). Clients send their topology data to the server
-next to them, and server synchronize with other servers. If there
-is no server configured (default) within the mesh, no topology
-information will be transmitted. With these "synchronizing
-servers", there can be 1 or more vis servers sharing the same (or
-at least very similar) data.
-
-When configured as server, you can get a topology snapshot of
-your mesh:
-
-# cat /sys/kernel/debug/batman_adv/bat0/vis_data
-
-This raw output is intended to be easily parsable and convertable
-with other tools. Have a look at the batctl README if you want a
-vis output in dot or json format for instance and how those out-
-puts could then be visualised in an image.
-
-The raw format consists of comma separated values per entry where
-each entry is giving information about a certain source inter-
-face. Each entry can/has to have the following values:
--> "mac" - mac address of an originator's source interface
- (each line begins with it)
--> "TQ mac value" - src mac's link quality towards mac address
- of a neighbor originator's interface which
- is being used for routing
--> "TT mac" - TT announced by source mac
--> "PRIMARY" - this is a primary interface
--> "SEC mac" - secondary mac address of source
- (requires preceding PRIMARY)
-
-The TQ value has a range from 4 to 255 with 255 being the best.
-The TT entries are showing which hosts are connected to the mesh
-via bat0 or being bridged into the mesh network. The PRIMARY/SEC
-values are only applied on primary interfaces
-
-
LOGGING/DEBUGGING
-----------------
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 489bb36..8ddbfe6 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -38,4 +38,3 @@ batman-adv-y += soft-interface.o
batman-adv-y += sysfs.o
batman-adv-y += translation-table.o
batman-adv-y += unicast.o
-batman-adv-y += vis.o
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 871ba67..97b42d3 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -687,11 +687,9 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
struct batadv_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *primary_if;
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
- int vis_server;
uint32_t seqno;
uint16_t tvlv_len = 0;
- vis_server = atomic_read(&bat_priv->vis_mode);
primary_if = batadv_primary_if_get_selected(bat_priv);
if (hard_iface == primary_if) {
@@ -712,11 +710,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
batadv_ogm_packet->seqno = htonl(seqno);
atomic_inc(&hard_iface->bat_iv.ogm_seqno);
- if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC)
- batadv_ogm_packet->flags |= BATADV_VIS_SERVER;
- else
- batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
-
batadv_iv_ogm_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
@@ -790,7 +783,6 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
rcu_read_unlock();
- orig_node->flags = batadv_ogm_packet->flags;
neigh_node->last_seen = jiffies;
spin_lock_bh(&neigh_node->lq_update_lock);
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index f186a55..049a7a2 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -28,7 +28,6 @@
#include "gateway_common.h"
#include "gateway_client.h"
#include "soft-interface.h"
-#include "vis.h"
#include "icmp_socket.h"
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
@@ -300,12 +299,6 @@ static int batadv_transtable_local_open(struct inode *inode, struct file *file)
return single_open(file, batadv_tt_local_seq_print_text, net_dev);
}
-static int batadv_vis_data_open(struct inode *inode, struct file *file)
-{
- struct net_device *net_dev = (struct net_device *)inode->i_private;
- return single_open(file, batadv_vis_seq_print_text, net_dev);
-}
-
struct batadv_debuginfo {
struct attribute attr;
const struct file_operations fops;
@@ -356,7 +349,6 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
#endif
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
batadv_transtable_local_open);
-static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
#ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif
@@ -373,7 +365,6 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_dat_cache,
#endif
&batadv_debuginfo_transtable_local,
- &batadv_debuginfo_vis_data,
#ifdef CONFIG_BATMAN_ADV_NC
&batadv_debuginfo_nc_nodes,
#endif
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index c478e6b..eeb6671 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -194,22 +194,13 @@ out:
static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
struct batadv_hard_iface *oldif)
{
- struct batadv_vis_packet *vis_packet;
struct batadv_hard_iface *primary_if;
- struct sk_buff *skb;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
goto out;
batadv_dat_init_own_addr(bat_priv, primary_if);
-
- skb = bat_priv->vis.my_info->skb_packet;
- vis_packet = (struct batadv_vis_packet *)skb->data;
- memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(vis_packet->sender_orig,
- primary_if->net_dev->dev_addr, ETH_ALEN);
-
batadv_bla_update_orig_address(bat_priv, primary_if, oldif);
out:
if (primary_if)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index fc55acb..43dc92e 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -38,7 +38,6 @@
#include "distributed-arp-table.h"
#include "unicast.h"
#include "gateway_common.h"
-#include "vis.h"
#include "hash.h"
#include "bat_algo.h"
#include "network-coding.h"
@@ -112,8 +111,6 @@ int batadv_mesh_init(struct net_device *soft_iface)
spin_lock_init(&bat_priv->tt.roam_list_lock);
spin_lock_init(&bat_priv->tt.last_changeset_lock);
spin_lock_init(&bat_priv->gw.list_lock);
- spin_lock_init(&bat_priv->vis.hash_lock);
- spin_lock_init(&bat_priv->vis.list_lock);
spin_lock_init(&bat_priv->tvlv.container_list_lock);
spin_lock_init(&bat_priv->tvlv.handler_list_lock);
@@ -137,10 +134,6 @@ int batadv_mesh_init(struct net_device *soft_iface)
batadv_tt_local_add(soft_iface, soft_iface->dev_addr,
BATADV_NULL_IFINDEX);
- ret = batadv_vis_init(bat_priv);
- if (ret < 0)
- goto err;
-
ret = batadv_bla_init(bat_priv);
if (ret < 0)
goto err;
@@ -173,8 +166,6 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_purge_outstanding_packets(bat_priv, NULL);
- batadv_vis_quit(bat_priv);
-
batadv_gw_node_purge(bat_priv);
batadv_nc_mesh_free(bat_priv);
batadv_dat_free(bat_priv);
@@ -412,8 +403,6 @@ static void batadv_recv_handler_init(void)
batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
/* broadcast packet */
batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
- /* vis packet */
- batadv_rx_handler[BATADV_VIS] = batadv_recv_vis_packet;
/* unicast tvlv packet */
batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
}
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 397722f..e11c2ec 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -86,8 +86,6 @@
/* numbers of originator to contact for any PUT/GET DHT operation */
#define BATADV_DAT_CANDIDATES_NUM 3
-#define BATADV_VIS_INTERVAL 5000 /* 5 seconds */
-
/* how much worse secondary interfaces may be to be considered as bonding
* candidates
*/
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index ab3084f..87fcf2e 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -29,7 +29,6 @@ enum batadv_packettype {
BATADV_ICMP = 0x02,
BATADV_UNICAST = 0x03,
BATADV_BCAST = 0x04,
- BATADV_VIS = 0x05,
BATADV_UNICAST_FRAG = 0x06,
BATADV_UNICAST_4ADDR = 0x09,
BATADV_CODED = 0x0a,
@@ -56,7 +55,6 @@ enum batadv_subtype {
enum batadv_iv_flags {
BATADV_NOT_BEST_NEXT_HOP = BIT(3),
BATADV_PRIMARIES_FIRST_HOP = BIT(4),
- BATADV_VIS_SERVER = BIT(5),
BATADV_DIRECTLINK = BIT(6),
};
@@ -69,12 +67,6 @@ enum batadv_icmp_packettype {
BATADV_PARAMETER_PROBLEM = 12,
};
-/* vis defines */
-enum batadv_vis_packettype {
- BATADV_VIS_TYPE_SERVER_SYNC = 0,
- BATADV_VIS_TYPE_CLIENT_UPDATE = 1,
-};
-
/* fragmentation defines */
enum batadv_unicast_frag_flags {
BATADV_UNI_FRAG_HEAD = BIT(0),
@@ -161,7 +153,7 @@ struct batadv_header {
*/
struct batadv_ogm_packet {
struct batadv_header header;
- uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
+ uint8_t flags; /* 0x40: DIRECTLINK flag ... */
__be32 seqno;
uint8_t orig[ETH_ALEN];
uint8_t prev_sender[ETH_ALEN];
@@ -257,17 +249,6 @@ struct batadv_bcast_packet {
#pragma pack()
-struct batadv_vis_packet {
- struct batadv_header header;
- uint8_t vis_type; /* which type of vis-participant sent this? */
- __be32 seqno; /* sequence number */
- uint8_t entries; /* number of entries behind this struct */
- uint8_t reserved;
- uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */
- uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */
- uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
-};
-
/**
* struct batadv_coded_packet - network coded packet
* @header: common batman packet header and ttl of first included packet
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index a5bf8ff..2a9318b 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -25,7 +25,6 @@
#include "icmp_socket.h"
#include "translation-table.h"
#include "originator.h"
-#include "vis.h"
#include "unicast.h"
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
@@ -1168,53 +1167,3 @@ out:
batadv_orig_node_free_ref(orig_node);
return ret;
}
-
-int batadv_recv_vis_packet(struct sk_buff *skb,
- struct batadv_hard_iface *recv_if)
-{
- struct batadv_vis_packet *vis_packet;
- struct ethhdr *ethhdr;
- struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
- int hdr_size = sizeof(*vis_packet);
-
- /* keep skb linear */
- if (skb_linearize(skb) < 0)
- return NET_RX_DROP;
-
- if (unlikely(!pskb_may_pull(skb, hdr_size)))
- return NET_RX_DROP;
-
- vis_packet = (struct batadv_vis_packet *)skb->data;
- ethhdr = eth_hdr(skb);
-
- /* not for me */
- if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
- return NET_RX_DROP;
-
- /* ignore own packets */
- if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig))
- return NET_RX_DROP;
-
- if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig))
- return NET_RX_DROP;
-
- switch (vis_packet->vis_type) {
- case BATADV_VIS_TYPE_SERVER_SYNC:
- batadv_receive_server_sync_packet(bat_priv, vis_packet,
- skb_headlen(skb));
- break;
-
- case BATADV_VIS_TYPE_CLIENT_UPDATE:
- batadv_receive_client_update_packet(bat_priv, vis_packet,
- skb_headlen(skb));
- break;
-
- default: /* ignore unknown packet */
- break;
- }
-
- /* We take a copy of the data in the packet, so we should
- * always free the skbuf.
- */
- return NET_RX_DROP;
-}
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 0a7983b..b3f53d4 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -34,8 +34,6 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
-int batadv_recv_vis_packet(struct sk_buff *skb,
- struct batadv_hard_iface *recv_if);
int batadv_recv_tt_query(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_roam_adv(struct sk_buff *skb,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 0266edd..81d69fb 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -24,7 +24,6 @@
#include "translation-table.h"
#include "soft-interface.h"
#include "hard-interface.h"
-#include "vis.h"
#include "gateway_common.h"
#include "originator.h"
#include "network-coding.h"
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 84623a9..25e6004 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -469,7 +469,6 @@ static int batadv_softif_init_late(struct net_device *dev)
atomic_set(&bat_priv->distributed_arp_table, 1);
#endif
atomic_set(&bat_priv->ap_isolation, 0);
- atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20);
atomic_set(&bat_priv->gw.bandwidth_down, 100);
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index fbc1c25..869eb46 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -26,7 +26,6 @@
#include "hard-interface.h"
#include "gateway_common.h"
#include "gateway_client.h"
-#include "vis.h"
static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
{
@@ -231,74 +230,6 @@ __batadv_store_uint_attr(const char *buff, size_t count,
return ret;
}
-static ssize_t batadv_show_vis_mode(struct kobject *kobj,
- struct attribute *attr, char *buff)
-{
- struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
- int vis_mode = atomic_read(&bat_priv->vis_mode);
- const char *mode;
-
- if (vis_mode == BATADV_VIS_TYPE_CLIENT_UPDATE)
- mode = "client";
- else
- mode = "server";
-
- return sprintf(buff, "%s\n", mode);
-}
-
-static ssize_t batadv_store_vis_mode(struct kobject *kobj,
- struct attribute *attr, char *buff,
- size_t count)
-{
- struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
- struct batadv_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);
-
- if (((count == 2) && (!ret) &&
- (val == BATADV_VIS_TYPE_CLIENT_UPDATE)) ||
- (strncmp(buff, "client", 6) == 0) ||
- (strncmp(buff, "off", 3) == 0))
- vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE;
-
- if (((count == 2) && (!ret) &&
- (val == BATADV_VIS_TYPE_SERVER_SYNC)) ||
- (strncmp(buff, "server", 6) == 0))
- vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC;
-
- if (vis_mode_tmp < 0) {
- if (buff[count - 1] == '\n')
- buff[count - 1] = '\0';
-
- 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;
-
- if (atomic_read(&bat_priv->vis_mode) == BATADV_VIS_TYPE_CLIENT_UPDATE)
- old_mode = "client";
- else
- old_mode = "server";
-
- if (vis_mode_tmp == BATADV_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;
-}
-
static ssize_t batadv_show_bat_algo(struct kobject *kobj,
struct attribute *attr, char *buff)
{
@@ -431,8 +362,6 @@ BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
#endif
BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
-static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
- batadv_store_vis_mode);
static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
batadv_store_gw_mode);
@@ -463,7 +392,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
#endif
&batadv_attr_fragmentation,
&batadv_attr_ap_isolation,
- &batadv_attr_vis_mode,
&batadv_attr_routing_algo,
&batadv_attr_gw_mode,
&batadv_attr_orig_interval,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index e98915a..8fbd89d 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -99,7 +99,6 @@ struct batadv_hard_iface {
* @last_seen: time when last packet from this node was received
* @bcast_seqno_reset: time when the broadcast seqno window was reset
* @batman_seqno_reset: time when the batman seqno window was reset
- * @flags: for now only VIS_SERVER flag
* @capabilities: announced capabilities of this originator
* @last_ttvn: last seen translation table version number
* @tt_crc: CRC of the translation table
@@ -147,7 +146,6 @@ struct batadv_orig_node {
unsigned long last_seen;
unsigned long bcast_seqno_reset;
unsigned long batman_seqno_reset;
- uint8_t flags;
uint8_t capabilities;
atomic_t last_ttvn;
uint32_t tt_crc;
@@ -462,24 +460,6 @@ struct batadv_priv_tvlv {
};
/**
- * struct batadv_priv_vis - per mesh interface vis data
- * @send_list: list of batadv_vis_info packets to sent
- * @hash: hash table containing vis data from other nodes in the network
- * @hash_lock: lock protecting the hash table
- * @list_lock: lock protecting my_info::recv_list
- * @work: work queue callback item for vis packet sending
- * @my_info: holds this node's vis data sent on a regular basis
- */
-struct batadv_priv_vis {
- struct list_head send_list;
- struct batadv_hashtable *hash;
- spinlock_t hash_lock; /* protects hash */
- spinlock_t list_lock; /* protects my_info::recv_list */
- struct delayed_work work;
- struct batadv_vis_info *my_info;
-};
-
-/**
* struct batadv_priv_dat - per mesh interface DAT private data
* @addr: node DAT address
* @hash: hashtable representing the local ARP cache
@@ -536,7 +516,6 @@ struct batadv_priv_nc {
* enabled
* @distributed_arp_table: bool indicating whether distributed ARP table is
* enabled
- * @vis_mode: vis operation: client or server (see batadv_vis_packettype)
* @gw_mode: gateway operation: off, client or server (see batadv_gw_modes)
* @gw_sel_class: gateway selection class (applies if gw_mode client)
* @orig_interval: OGM broadcast interval in milliseconds
@@ -563,7 +542,6 @@ struct batadv_priv_nc {
* @gw: gateway data
* @tt: translation table data
* @tvlv: type-version-length-value data
- * @vis: vis data
* @dat: distributed arp table data
* @network_coding: bool indicating whether network coding is enabled
* @batadv_priv_nc: network coding data
@@ -583,7 +561,6 @@ struct batadv_priv {
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_t distributed_arp_table;
#endif
- atomic_t vis_mode;
atomic_t gw_mode;
atomic_t gw_sel_class;
atomic_t orig_interval;
@@ -615,7 +592,6 @@ struct batadv_priv {
struct batadv_priv_gw gw;
struct batadv_priv_tt tt;
struct batadv_priv_tvlv tvlv;
- struct batadv_priv_vis vis;
#ifdef CONFIG_BATMAN_ADV_DAT
struct batadv_priv_dat dat;
#endif
@@ -910,66 +886,6 @@ struct batadv_frag_packet_list_entry {
};
/**
- * struct batadv_vis_info - local data for vis information
- * @first_seen: timestamp used for purging stale vis info entries
- * @recv_list: List of server-neighbors we have received this packet from. This
- * packet should not be re-forward to them again. List elements are struct
- * batadv_vis_recvlist_node
- * @send_list: list of packets to be forwarded
- * @refcount: number of contexts the object is used
- * @hash_entry: hlist node for batadv_priv_vis::hash
- * @bat_priv: pointer to soft_iface this orig node belongs to
- * @skb_packet: contains the vis packet
- */
-struct batadv_vis_info {
- unsigned long first_seen;
- struct list_head recv_list;
- struct list_head send_list;
- struct kref refcount;
- struct hlist_node hash_entry;
- struct batadv_priv *bat_priv;
- struct sk_buff *skb_packet;
-} __packed;
-
-/**
- * struct batadv_vis_info_entry - contains link information for vis
- * @src: source MAC of the link, all zero for local TT entry
- * @dst: destination MAC of the link, client mac address for local TT entry
- * @quality: transmission quality of the link, or 0 for local TT entry
- */
-struct batadv_vis_info_entry {
- uint8_t src[ETH_ALEN];
- uint8_t dest[ETH_ALEN];
- uint8_t quality;
-} __packed;
-
-/**
- * struct batadv_vis_recvlist_node - list entry for batadv_vis_info::recv_list
- * @list: list node for batadv_vis_info::recv_list
- * @mac: MAC address of the originator from where the vis_info was received
- */
-struct batadv_vis_recvlist_node {
- struct list_head list;
- uint8_t mac[ETH_ALEN];
-};
-
-/**
- * struct batadv_vis_if_list_entry - auxiliary data for vis data generation
- * @addr: MAC address of the interface
- * @primary: true if this interface is the primary interface
- * @list: list node the interface list
- *
- * While scanning for vis-entries of a particular vis-originator
- * this list collects its interfaces to create a subgraph/cluster
- * out of them later
- */
-struct batadv_vis_if_list_entry {
- uint8_t addr[ETH_ALEN];
- bool primary;
- struct hlist_node list;
-};
-
-/**
* struct batadv_algo_ops - mesh algorithm callbacks
* @list: list node for the batadv_algo_list
* @name: name of the algorithm
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
deleted file mode 100644
index d8ea31a..0000000
--- a/net/batman-adv/vis.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/* Copyright (C) 2008-2013 B.A.T.M.A.N. contributors:
- *
- * Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#include "main.h"
-#include "send.h"
-#include "translation-table.h"
-#include "vis.h"
-#include "soft-interface.h"
-#include "hard-interface.h"
-#include "hash.h"
-#include "originator.h"
-
-#define BATADV_MAX_VIS_PACKET_SIZE 1000
-
-/* hash class keys */
-static struct lock_class_key batadv_vis_hash_lock_class_key;
-
-/* free the info */
-static void batadv_free_info(struct kref *ref)
-{
- struct batadv_vis_info *info;
- struct batadv_priv *bat_priv;
- struct batadv_vis_recvlist_node *entry, *tmp;
-
- info = container_of(ref, struct batadv_vis_info, refcount);
- bat_priv = info->bat_priv;
-
- list_del_init(&info->send_list);
- spin_lock_bh(&bat_priv->vis.list_lock);
- list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
- list_del(&entry->list);
- kfree(entry);
- }
-
- spin_unlock_bh(&bat_priv->vis.list_lock);
- kfree_skb(info->skb_packet);
- kfree(info);
-}
-
-/* Compare two vis packets, used by the hashing algorithm */
-static int batadv_vis_info_cmp(const struct hlist_node *node, const void *data2)
-{
- const struct batadv_vis_info *d1, *d2;
- const struct batadv_vis_packet *p1, *p2;
-
- d1 = container_of(node, struct batadv_vis_info, hash_entry);
- d2 = data2;
- p1 = (struct batadv_vis_packet *)d1->skb_packet->data;
- p2 = (struct batadv_vis_packet *)d2->skb_packet->data;
- return batadv_compare_eth(p1->vis_orig, p2->vis_orig);
-}
-
-/* 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 batadv_vis_info_choose(const void *data, uint32_t size)
-{
- const struct batadv_vis_info *vis_info = data;
- const struct batadv_vis_packet *packet;
- const unsigned char *key;
- uint32_t hash = 0;
- size_t i;
-
- packet = (struct batadv_vis_packet *)vis_info->skb_packet->data;
- key = packet->vis_orig;
- for (i = 0; i < ETH_ALEN; i++) {
- hash += key[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
-
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash % size;
-}
-
-static struct batadv_vis_info *
-batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
-{
- struct batadv_hashtable *hash = bat_priv->vis.hash;
- struct hlist_head *head;
- struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
- uint32_t index;
-
- if (!hash)
- return NULL;
-
- index = batadv_vis_info_choose(data, hash->size);
- head = &hash->table[index];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(vis_info, head, hash_entry) {
- if (!batadv_vis_info_cmp(&vis_info->hash_entry, data))
- continue;
-
- vis_info_tmp = vis_info;
- break;
- }
- rcu_read_unlock();
-
- return vis_info_tmp;
-}
-
-/* insert interface to the list of interfaces of one originator, if it
- * does not already exist in the list
- */
-static void batadv_vis_data_insert_interface(const uint8_t *interface,
- struct hlist_head *if_list,
- bool primary)
-{
- struct batadv_vis_if_list_entry *entry;
-
- hlist_for_each_entry(entry, if_list, list) {
- if (batadv_compare_eth(entry->addr, interface))
- return;
- }
-
- /* it's a new address, add it to the list */
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry)
- return;
- memcpy(entry->addr, interface, ETH_ALEN);
- entry->primary = primary;
- hlist_add_head(&entry->list, if_list);
-}
-
-static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
- const struct hlist_head *if_list)
-{
- struct batadv_vis_if_list_entry *entry;
-
- hlist_for_each_entry(entry, if_list, list) {
- if (entry->primary)
- seq_puts(seq, "PRIMARY, ");
- else
- seq_printf(seq, "SEC %pM, ", entry->addr);
- }
-}
-
-/* read an entry */
-static ssize_t
-batadv_vis_data_read_entry(struct seq_file *seq,
- const struct batadv_vis_info_entry *entry,
- const uint8_t *src, bool primary)
-{
- if (primary && entry->quality == 0)
- return seq_printf(seq, "TT %pM, ", entry->dest);
- else if (batadv_compare_eth(entry->src, src))
- return seq_printf(seq, "TQ %pM %d, ", entry->dest,
- entry->quality);
-
- return 0;
-}
-
-static void
-batadv_vis_data_insert_interfaces(struct hlist_head *list,
- struct batadv_vis_packet *packet,
- struct batadv_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 batadv_vis_packet *packet,
- struct batadv_vis_info_entry *entries)
-{
- int i;
- struct batadv_vis_if_list_entry *entry;
-
- hlist_for_each_entry(entry, 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_puts(seq, "\n");
- }
-}
-
-static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
- const struct hlist_head *head)
-{
- struct batadv_vis_info *info;
- struct batadv_vis_packet *packet;
- uint8_t *entries_pos;
- struct batadv_vis_info_entry *entries;
- struct batadv_vis_if_list_entry *entry;
- struct hlist_node *n;
-
- HLIST_HEAD(vis_if_list);
-
- hlist_for_each_entry_rcu(info, head, hash_entry) {
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
- entries_pos = (uint8_t *)packet + sizeof(*packet);
- entries = (struct batadv_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, n, &vis_if_list, list) {
- hlist_del(&entry->list);
- kfree(entry);
- }
- }
-}
-
-int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
-{
- struct batadv_hard_iface *primary_if;
- struct hlist_head *head;
- struct net_device *net_dev = (struct net_device *)seq->private;
- struct batadv_priv *bat_priv = netdev_priv(net_dev);
- struct batadv_hashtable *hash = bat_priv->vis.hash;
- uint32_t i;
- int ret = 0;
- int vis_server = atomic_read(&bat_priv->vis_mode);
-
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- goto out;
-
- if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
- goto out;
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
- batadv_vis_seq_print_text_bucket(seq, head);
- }
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-
-out:
- if (primary_if)
- batadv_hardif_free_ref(primary_if);
- return ret;
-}
-
-/* add the info packet to the send list, if it was not
- * already linked in.
- */
-static void batadv_send_list_add(struct batadv_priv *bat_priv,
- struct batadv_vis_info *info)
-{
- if (list_empty(&info->send_list)) {
- kref_get(&info->refcount);
- list_add_tail(&info->send_list, &bat_priv->vis.send_list);
- }
-}
-
-/* delete the info packet from the send list, if it was
- * linked in.
- */
-static void batadv_send_list_del(struct batadv_vis_info *info)
-{
- if (!list_empty(&info->send_list)) {
- list_del_init(&info->send_list);
- kref_put(&info->refcount, batadv_free_info);
- }
-}
-
-/* tries to add one entry to the receive list. */
-static void batadv_recv_list_add(struct batadv_priv *bat_priv,
- struct list_head *recv_list, const char *mac)
-{
- struct batadv_vis_recvlist_node *entry;
-
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry)
- return;
-
- memcpy(entry->mac, mac, ETH_ALEN);
- spin_lock_bh(&bat_priv->vis.list_lock);
- list_add_tail(&entry->list, recv_list);
- spin_unlock_bh(&bat_priv->vis.list_lock);
-}
-
-/* returns 1 if this mac is in the recv_list */
-static int batadv_recv_list_is_in(struct batadv_priv *bat_priv,
- const struct list_head *recv_list,
- const char *mac)
-{
- const struct batadv_vis_recvlist_node *entry;
-
- spin_lock_bh(&bat_priv->vis.list_lock);
- list_for_each_entry(entry, recv_list, list) {
- if (batadv_compare_eth(entry->mac, mac)) {
- spin_unlock_bh(&bat_priv->vis.list_lock);
- return 1;
- }
- }
- spin_unlock_bh(&bat_priv->vis.list_lock);
- return 0;
-}
-
-/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
- * broken.. ). vis hash must be locked outside. is_new is set when the packet
- * is newer than old entries in the hash.
- */
-static struct batadv_vis_info *
-batadv_add_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_packet *vis_packet, int vis_info_len,
- int *is_new, int make_broadcast)
-{
- struct batadv_vis_info *info, *old_info;
- struct batadv_vis_packet *search_packet, *old_packet;
- struct batadv_vis_info search_elem;
- struct batadv_vis_packet *packet;
- struct sk_buff *tmp_skb;
- int hash_added;
- size_t len;
- size_t max_entries;
-
- *is_new = 0;
- /* sanity check */
- if (!bat_priv->vis.hash)
- return NULL;
-
- /* see if the packet is already in vis_hash */
- search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet));
- if (!search_elem.skb_packet)
- return NULL;
- len = sizeof(*search_packet);
- tmp_skb = search_elem.skb_packet;
- search_packet = (struct batadv_vis_packet *)skb_put(tmp_skb, len);
-
- memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
- old_info = batadv_vis_hash_find(bat_priv, &search_elem);
- kfree_skb(search_elem.skb_packet);
-
- if (old_info) {
- tmp_skb = old_info->skb_packet;
- old_packet = (struct batadv_vis_packet *)tmp_skb->data;
- 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,
- vis_packet->sender_orig);
- return old_info;
- } else {
- /* newer packet is already in hash. */
- return NULL;
- }
- }
- /* remove old entry */
- 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);
- if (!info)
- return NULL;
-
- len = sizeof(*packet) + vis_info_len;
- info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
- if (!info->skb_packet) {
- kfree(info);
- return NULL;
- }
- info->skb_packet->priority = TC_PRIO_CONTROL;
- skb_reserve(info->skb_packet, ETH_HLEN);
- packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
-
- kref_init(&info->refcount);
- INIT_LIST_HEAD(&info->send_list);
- INIT_LIST_HEAD(&info->recv_list);
- info->first_seen = jiffies;
- info->bat_priv = bat_priv;
- memcpy(packet, vis_packet, len);
-
- /* initialize and add new packet. */
- *is_new = 1;
-
- /* Make it a broadcast packet, if required */
- if (make_broadcast)
- memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
-
- /* repair if entries is longer than packet. */
- max_entries = vis_info_len / sizeof(struct batadv_vis_info_entry);
- if (packet->entries > max_entries)
- packet->entries = max_entries;
-
- 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, 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, batadv_free_info);
- info = NULL;
- }
-
- return info;
-}
-
-/* handle the server sync packet, forward if needed. */
-void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_packet *vis_packet,
- int vis_info_len)
-{
- struct batadv_vis_info *info;
- int is_new, make_broadcast;
- int vis_server = atomic_read(&bat_priv->vis_mode);
-
- make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
- info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
- &is_new, make_broadcast);
- if (!info)
- goto end;
-
- /* only if we are server ourselves and packet is newer than the one in
- * hash.
- */
- if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
- batadv_send_list_add(bat_priv, info);
-end:
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-}
-
-/* handle an incoming client update packet and schedule forward if needed. */
-void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_packet *vis_packet,
- int vis_info_len)
-{
- struct batadv_vis_info *info;
- struct batadv_vis_packet *packet;
- int is_new;
- int vis_server = atomic_read(&bat_priv->vis_mode);
- int are_target = 0;
-
- /* clients shall not broadcast. */
- if (is_broadcast_ether_addr(vis_packet->target_orig))
- return;
-
- /* Are we the target for this VIS packet? */
- if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC &&
- batadv_is_my_mac(bat_priv, vis_packet->target_orig))
- are_target = 1;
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
- info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
- &is_new, are_target);
-
- if (!info)
- goto end;
- /* note that outdated packets will be dropped at this point. */
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
-
- /* send only if we're the target server or ... */
- if (are_target && is_new) {
- packet->vis_type = BATADV_VIS_TYPE_SERVER_SYNC; /* upgrade! */
- batadv_send_list_add(bat_priv, info);
-
- /* ... we're not the recipient (and thus need to forward). */
- } else if (!batadv_is_my_mac(bat_priv, packet->target_orig)) {
- batadv_send_list_add(bat_priv, info);
- }
-
-end:
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-}
-
-/* Walk the originators and find the VIS server with the best tq. Set the packet
- * address to its address and return the best_tq.
- *
- * Must be called with the originator hash locked
- */
-static int batadv_find_best_vis_server(struct batadv_priv *bat_priv,
- struct batadv_vis_info *info)
-{
- struct batadv_hashtable *hash = bat_priv->orig_hash;
- struct batadv_neigh_node *router;
- struct hlist_head *head;
- struct batadv_orig_node *orig_node;
- struct batadv_vis_packet *packet;
- int best_tq = -1;
- uint32_t i;
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- continue;
-
- if ((orig_node->flags & BATADV_VIS_SERVER) &&
- (router->tq_avg > best_tq)) {
- best_tq = router->tq_avg;
- memcpy(packet->target_orig, orig_node->orig,
- ETH_ALEN);
- }
- batadv_neigh_node_free_ref(router);
- }
- rcu_read_unlock();
- }
-
- return best_tq;
-}
-
-/* Return true if the vis packet is full. */
-static bool batadv_vis_packet_full(const struct batadv_vis_info *info)
-{
- const struct batadv_vis_packet *packet;
- size_t num;
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
- num = BATADV_MAX_VIS_PACKET_SIZE / sizeof(struct batadv_vis_info_entry);
-
- if (num < packet->entries + 1)
- return true;
- return false;
-}
-
-/* generates a packet of own vis data,
- * returns 0 on success, -1 if no packet could be generated
- */
-static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
-{
- struct batadv_hashtable *hash = bat_priv->orig_hash;
- struct hlist_head *head;
- struct batadv_orig_node *orig_node;
- struct batadv_neigh_node *router;
- struct batadv_vis_info *info = bat_priv->vis.my_info;
- struct batadv_vis_packet *packet;
- struct batadv_vis_info_entry *entry;
- struct batadv_tt_common_entry *tt_common_entry;
- uint8_t *packet_pos;
- int best_tq = -1;
- uint32_t i;
-
- info->first_seen = jiffies;
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
- packet->vis_type = atomic_read(&bat_priv->vis_mode);
-
- memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
- packet->header.ttl = BATADV_TTL;
- packet->seqno = htonl(ntohl(packet->seqno) + 1);
- packet->entries = 0;
- packet->reserved = 0;
- skb_trim(info->skb_packet, sizeof(*packet));
-
- if (packet->vis_type == BATADV_VIS_TYPE_CLIENT_UPDATE) {
- best_tq = batadv_find_best_vis_server(bat_priv, info);
-
- if (best_tq < 0)
- return best_tq;
- }
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- continue;
-
- if (!batadv_compare_eth(router->addr, orig_node->orig))
- goto next;
-
- if (router->if_incoming->if_status != BATADV_IF_ACTIVE)
- goto next;
-
- if (router->tq_avg < 1)
- goto next;
-
- /* fill one entry into buffer. */
- packet_pos = skb_put(info->skb_packet, sizeof(*entry));
- entry = (struct batadv_vis_info_entry *)packet_pos;
- memcpy(entry->src,
- router->if_incoming->net_dev->dev_addr,
- ETH_ALEN);
- memcpy(entry->dest, orig_node->orig, ETH_ALEN);
- entry->quality = router->tq_avg;
- packet->entries++;
-
-next:
- batadv_neigh_node_free_ref(router);
-
- if (batadv_vis_packet_full(info))
- goto unlock;
- }
- rcu_read_unlock();
- }
-
- hash = bat_priv->tt.local_hash;
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(tt_common_entry, head,
- hash_entry) {
- packet_pos = skb_put(info->skb_packet, sizeof(*entry));
- entry = (struct batadv_vis_info_entry *)packet_pos;
- memset(entry->src, 0, ETH_ALEN);
- memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
- entry->quality = 0; /* 0 means TT */
- packet->entries++;
-
- if (batadv_vis_packet_full(info))
- goto unlock;
- }
- rcu_read_unlock();
- }
-
- return 0;
-
-unlock:
- rcu_read_unlock();
- return 0;
-}
-
-/* free old vis packets. Must be called with this vis_hash_lock
- * held
- */
-static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
-{
- uint32_t i;
- struct batadv_hashtable *hash = bat_priv->vis.hash;
- struct hlist_node *node_tmp;
- struct hlist_head *head;
- struct batadv_vis_info *info;
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-
- hlist_for_each_entry_safe(info, node_tmp,
- head, hash_entry) {
- /* never purge own data. */
- if (info == bat_priv->vis.my_info)
- continue;
-
- if (batadv_has_timed_out(info->first_seen,
- BATADV_VIS_TIMEOUT)) {
- hlist_del(&info->hash_entry);
- batadv_send_list_del(info);
- kref_put(&info->refcount, batadv_free_info);
- }
- }
- }
-}
-
-static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_info *info)
-{
- struct batadv_hashtable *hash = bat_priv->orig_hash;
- struct hlist_head *head;
- struct batadv_orig_node *orig_node;
- struct batadv_vis_packet *packet;
- struct sk_buff *skb;
- uint32_t i, res;
-
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
-
- /* send to all routers in range. */
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
- /* if it's a vis server and reachable, send it. */
- if (!(orig_node->flags & BATADV_VIS_SERVER))
- continue;
-
- /* don't send it if we already received the packet from
- * this node.
- */
- if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
- orig_node->orig))
- continue;
-
- memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
- skb = skb_clone(info->skb_packet, GFP_ATOMIC);
- if (!skb)
- continue;
-
- res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res == NET_XMIT_DROP)
- kfree_skb(skb);
- }
- rcu_read_unlock();
- }
-}
-
-static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_info *info)
-{
- struct batadv_orig_node *orig_node;
- struct sk_buff *skb;
- struct batadv_vis_packet *packet;
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
-
- orig_node = batadv_orig_hash_find(bat_priv, packet->target_orig);
- if (!orig_node)
- goto out;
-
- skb = skb_clone(info->skb_packet, GFP_ATOMIC);
- if (!skb)
- goto out;
-
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
- kfree_skb(skb);
-
-out:
- if (orig_node)
- batadv_orig_node_free_ref(orig_node);
-}
-
-/* only send one vis packet. called from batadv_send_vis_packets() */
-static void batadv_send_vis_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_info *info)
-{
- struct batadv_hard_iface *primary_if;
- struct batadv_vis_packet *packet;
-
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- goto out;
-
- packet = (struct batadv_vis_packet *)info->skb_packet->data;
- if (packet->header.ttl < 2) {
- pr_debug("Error - can't send vis packet: ttl exceeded\n");
- goto out;
- }
-
- memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- packet->header.ttl--;
-
- if (is_broadcast_ether_addr(packet->target_orig))
- batadv_broadcast_vis_packet(bat_priv, info);
- else
- batadv_unicast_vis_packet(bat_priv, info);
- packet->header.ttl++; /* restore TTL */
-
-out:
- if (primary_if)
- batadv_hardif_free_ref(primary_if);
-}
-
-/* called from timer; send (and maybe generate) vis packet. */
-static void batadv_send_vis_packets(struct work_struct *work)
-{
- struct delayed_work *delayed_work;
- struct batadv_priv *bat_priv;
- struct batadv_priv_vis *priv_vis;
- struct batadv_vis_info *info;
-
- delayed_work = container_of(work, struct delayed_work, work);
- priv_vis = container_of(delayed_work, struct batadv_priv_vis, work);
- bat_priv = container_of(priv_vis, struct batadv_priv, vis);
- spin_lock_bh(&bat_priv->vis.hash_lock);
- batadv_purge_vis_packets(bat_priv);
-
- if (batadv_generate_vis_packet(bat_priv) == 0) {
- /* schedule if generation was successful */
- batadv_send_list_add(bat_priv, bat_priv->vis.my_info);
- }
-
- while (!list_empty(&bat_priv->vis.send_list)) {
- info = list_first_entry(&bat_priv->vis.send_list,
- typeof(*info), send_list);
-
- kref_get(&info->refcount);
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-
- batadv_send_vis_packet(bat_priv, info);
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
- batadv_send_list_del(info);
- kref_put(&info->refcount, batadv_free_info);
- }
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-
- queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
- msecs_to_jiffies(BATADV_VIS_INTERVAL));
-}
-
-/* init the vis server. this may only be called when if_list is already
- * initialized (e.g. bat0 is initialized, interfaces have been added)
- */
-int batadv_vis_init(struct batadv_priv *bat_priv)
-{
- struct batadv_vis_packet *packet;
- int hash_added;
- unsigned int len;
- unsigned long first_seen;
- struct sk_buff *tmp_skb;
-
- if (bat_priv->vis.hash)
- return 0;
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
-
- bat_priv->vis.hash = batadv_hash_new(256);
- if (!bat_priv->vis.hash) {
- pr_err("Can't initialize vis_hash\n");
- goto err;
- }
-
- batadv_hash_set_lock_class(bat_priv->vis.hash,
- &batadv_vis_hash_lock_class_key);
-
- bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
- if (!bat_priv->vis.my_info)
- goto err;
-
- len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
- bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL,
- len);
- if (!bat_priv->vis.my_info->skb_packet)
- goto free_info;
-
- bat_priv->vis.my_info->skb_packet->priority = TC_PRIO_CONTROL;
- skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
- tmp_skb = bat_priv->vis.my_info->skb_packet;
- packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
-
- /* prefill the vis info */
- first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
- bat_priv->vis.my_info->first_seen = first_seen;
- INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list);
- INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list);
- kref_init(&bat_priv->vis.my_info->refcount);
- bat_priv->vis.my_info->bat_priv = bat_priv;
- packet->header.version = BATADV_COMPAT_VERSION;
- packet->header.packet_type = BATADV_VIS;
- packet->header.ttl = BATADV_TTL;
- packet->seqno = 0;
- packet->reserved = 0;
- packet->entries = 0;
-
- INIT_LIST_HEAD(&bat_priv->vis.send_list);
-
- hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
- batadv_vis_info_choose,
- bat_priv->vis.my_info,
- &bat_priv->vis.my_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->vis.my_info->refcount, batadv_free_info);
- goto err;
- }
-
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-
- INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets);
- queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
- msecs_to_jiffies(BATADV_VIS_INTERVAL));
-
- return 0;
-
-free_info:
- kfree(bat_priv->vis.my_info);
- bat_priv->vis.my_info = NULL;
-err:
- spin_unlock_bh(&bat_priv->vis.hash_lock);
- batadv_vis_quit(bat_priv);
- return -ENOMEM;
-}
-
-/* Decrease the reference count on a hash item info */
-static void batadv_free_info_ref(struct hlist_node *node, void *arg)
-{
- struct batadv_vis_info *info;
-
- info = container_of(node, struct batadv_vis_info, hash_entry);
- batadv_send_list_del(info);
- kref_put(&info->refcount, batadv_free_info);
-}
-
-/* shutdown vis-server */
-void batadv_vis_quit(struct batadv_priv *bat_priv)
-{
- if (!bat_priv->vis.hash)
- return;
-
- cancel_delayed_work_sync(&bat_priv->vis.work);
-
- spin_lock_bh(&bat_priv->vis.hash_lock);
- /* properly remove, kill timers ... */
- batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL);
- bat_priv->vis.hash = NULL;
- bat_priv->vis.my_info = NULL;
- spin_unlock_bh(&bat_priv->vis.hash_lock);
-}
diff --git a/net/batman-adv/vis.h b/net/batman-adv/vis.h
deleted file mode 100644
index ad92b0e..0000000
--- a/net/batman-adv/vis.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (C) 2008-2013 B.A.T.M.A.N. contributors:
- *
- * Simon Wunderlich, Marek Lindner
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#ifndef _NET_BATMAN_ADV_VIS_H_
-#define _NET_BATMAN_ADV_VIS_H_
-
-/* timeout of vis packets in milliseconds */
-#define BATADV_VIS_TIMEOUT 200000
-
-int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
-void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_packet *vis_packet,
- int vis_info_len);
-void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
- struct batadv_vis_packet *vis_packet,
- int vis_info_len);
-int batadv_vis_init(struct batadv_priv *bat_priv);
-void batadv_vis_quit(struct batadv_priv *bat_priv);
-
-#endif /* _NET_BATMAN_ADV_VIS_H_ */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 11/16] batman-adv: move BATADV_TT_CLIENT_TEMP to higher bit
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
Client flags from bit 0 to 7 are sent over the wire.
BATADV_TT_CLIENT_TEMP is a local flag and is not supposed
to be sent to the network. Therefore it has occupy a
higher bit.
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/packet.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 7a337d7..ab3084f 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -106,10 +106,10 @@ enum batadv_tt_client_flags {
BATADV_TT_CLIENT_DEL = BIT(0),
BATADV_TT_CLIENT_ROAM = BIT(1),
BATADV_TT_CLIENT_WIFI = BIT(2),
- BATADV_TT_CLIENT_TEMP = BIT(3),
BATADV_TT_CLIENT_NOPURGE = BIT(8),
BATADV_TT_CLIENT_NEW = BIT(9),
BATADV_TT_CLIENT_PENDING = BIT(10),
+ BATADV_TT_CLIENT_TEMP = BIT(11),
};
/* claim frame types for the bridge loop avoidance */
--
1.8.3.2
^ permalink raw reply related
* RE: INVESTMENT/ RELOCATION ASSISTANCE. 9th/10/2013
From: Jamilahussain @ 2013-10-09 13:22 UTC (permalink / raw)
To: Recipients
Dear Beloved,
I am Mrs. Jamila Hussein a Teacher and a Muslim Convert here in Syria,i had sent a previous mail which i am not sure you got. I need your assistance to invest and assist relocate 3 kids who are 17 years and below so that they can get a better life there in your country due to the on going crises here in Syria.
I need your trust, before the death of their parents they had a savings with an Indian Bank, so money is not the issue.
I got your reference in my search for someone who suits my
purpose.If you can help me reply, let me know.
Regards,
Mrs. Jamila Hussein
=====================================4
^ permalink raw reply
* [PATCH 14/16] batman-adv: reorder packet types
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
Marek Lindner, Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
Reordering the packet type numbers allows us to handle unicast
packets in a general way - even if we don't know the specific packet
type, we can still forward it. There was already code handling
this for a couple of unicast packets, and this is the more
generalized version to do that.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/main.c | 20 +++++++++++++++-----
net/batman-adv/packet.h | 31 +++++++++++++++++++++++--------
net/batman-adv/routing.c | 28 ++++++++++++++++++++++++++++
net/batman-adv/routing.h | 2 ++
4 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b22368e..8b195e6 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -393,6 +393,9 @@ static void batadv_recv_handler_init(void)
for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++)
batadv_rx_handler[i] = batadv_recv_unhandled_packet;
+ for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++)
+ batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet;
+
/* compile time checks for struct member offsets */
BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
@@ -401,18 +404,20 @@ static void batadv_recv_handler_init(void)
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
- /* batman icmp packet */
- batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
+ /* broadcast packet */
+ batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
+
+ /* unicast packets ... */
/* unicast with 4 addresses packet */
batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
/* unicast packet */
batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
/* fragmented unicast packet */
batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
- /* broadcast packet */
- batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
/* unicast tvlv packet */
batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
+ /* batman icmp packet */
+ batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
}
int
@@ -420,7 +425,12 @@ batadv_recv_handler_register(uint8_t packet_type,
int (*recv_handler)(struct sk_buff *,
struct batadv_hard_iface *))
{
- if (batadv_rx_handler[packet_type] != &batadv_recv_unhandled_packet)
+ int (*curr)(struct sk_buff *,
+ struct batadv_hard_iface *);
+ curr = batadv_rx_handler[packet_type];
+
+ if ((curr != batadv_recv_unhandled_packet) &&
+ (curr != batadv_recv_unhandled_unicast_packet))
return -EBUSY;
batadv_rx_handler[packet_type] = recv_handler;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 87fcf2e..f02dbb1 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -22,17 +22,32 @@
/**
* enum batadv_packettype - types for batman-adv encapsulated packets
+ * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV
+ * @BATADV_BCAST: broadcast packets carrying broadcast payload
+ * @BATADV_CODED: network coded packets
+ *
+ * @BATADV_UNICAST: unicast packets carrying unicast payload traffic
+ * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
+ * payload packet
+ * @BATADV_UNICAST_4ADDR: unicast packet including the originator address of
+ * the sender
+ * @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute
* @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers
*/
enum batadv_packettype {
- BATADV_IV_OGM = 0x01,
- BATADV_ICMP = 0x02,
- BATADV_UNICAST = 0x03,
- BATADV_BCAST = 0x04,
- BATADV_UNICAST_FRAG = 0x06,
- BATADV_UNICAST_4ADDR = 0x09,
- BATADV_CODED = 0x0a,
- BATADV_UNICAST_TVLV = 0x0b,
+ /* 0x00 - 0x3f: local packets or special rules for handling */
+ BATADV_IV_OGM = 0x00,
+ BATADV_BCAST = 0x01,
+ BATADV_CODED = 0x02,
+ /* 0x40 - 0x7f: unicast */
+#define BATADV_UNICAST_MIN 0x40
+ BATADV_UNICAST = 0x40,
+ BATADV_UNICAST_FRAG = 0x41,
+ BATADV_UNICAST_4ADDR = 0x42,
+ BATADV_ICMP = 0x43,
+ BATADV_UNICAST_TVLV = 0x44,
+#define BATADV_UNICAST_MAX 0x7f
+ /* 0x80 - 0xff: reserved */
};
/**
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 2a9318b..457dfef 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -911,6 +911,34 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
return 1;
}
+/**
+ * batadv_recv_unhandled_unicast_packet - receive and process packets which
+ * are in the unicast number space but not yet known to the implementation
+ * @skb: unicast tvlv packet to process
+ * @recv_if: pointer to interface this packet was received on
+ *
+ * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
+ * otherwise.
+ */
+int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
+ struct batadv_hard_iface *recv_if)
+{
+ struct batadv_unicast_packet *unicast_packet;
+ struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+ int check, hdr_size = sizeof(*unicast_packet);
+
+ check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
+ if (check < 0)
+ return NET_RX_DROP;
+
+ /* we don't know about this type, drop it. */
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
+ if (batadv_is_my_mac(bat_priv, unicast_packet->dest))
+ return NET_RX_DROP;
+
+ return batadv_route_unicast_packet(skb, recv_if);
+}
+
int batadv_recv_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index b3f53d4..ea15fa6 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -40,6 +40,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_unicast_tvlv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
+int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
+ struct batadv_hard_iface *recv_if);
struct batadv_neigh_node *
batadv_find_router(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
--
1.8.3.2
^ permalink raw reply related
* Re: MBIM device refusing to be enabled
From: Dan Williams @ 2013-10-09 13:31 UTC (permalink / raw)
To: Oliver Neukum; +Cc: Bjørn Mork, netdev
In-Reply-To: <1381317745.3464.6.camel@linux-fkkt.site>
On Wed, 2013-10-09 at 13:22 +0200, Oliver Neukum wrote:
> On Wed, 2013-10-09 at 13:09 +0200, Bjørn Mork wrote:
> > Bjørn Mork <bjorn@mork.no> writes:
>
> Hi,
>
> >
> > > Sorry, that was nonsense. rfkill would only affect the HwRadioState.
> >
> > Turns out I wasn't completely off anyway... by pure luck ;-)
> >
> > > Looking at the commands following this message, it appears that MM
> > > correctly attempts to enable the SwRadioState but fails. I don't know
> > > why.
>
> Cool.
>
> > Is the device by any chance a Sierra Wireless device?
>
> Yes. Rebranded by HP but it is Sierra.
> HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module
>
> > I was able to recreate the behaviour you see after experimenting a bit
> > with my MC7710. This device (and I assume most other MBIM capable
> > Sierra Wireless minicards) can be configured to enter low power mode on
> > rfkill (W_DISABLE asserted), instead of powering off. Sony for example
> > are known to configure the built-in Sierra devices in this mode.
> >
> > When low power mode is forced by rfkill this way, the firmware
> > erroneously[1] claims
> >
> > HwRadioState: on
> > SwRadioState: off
> >
> > Any attempt to change this software state using MBIM will fail with
> > MBIM_STATUS_FAILURE. Exactly like your log shows. The modem must be
> > enabled using rfkill before MM can use it. Changing the firmware
> > behaviour will not do any good - it will just cause the modem to power
> > off and disappear instead.
> >
> > So I would start looking at rfkill after all. There are often problems
> > with these platform drivers and newer laptops, due to the lack of
> > documentation from the vendors. Here's one (now fixed) example:
> > https://bugzilla.kernel.org/show_bug.cgi?id=47751
>
> Thanks. A quick look shows that there's something wrong. There is no
> rfkill entry for the device. I am investigating.
PCIe minicard pinouts have a W_DISABLE# pin (row 1 pin 20, active low)
that kills the card. If your machine grounds that PIN or mishandles it
somehow, and the card cares about that pin, then the card will show as
rfkilled.
I have cards that care: Samsung Y3300/Y3400, and most Ericsson devices.
The devices themselves show as rfkilled (either through QMI, AT
commands, etc) but you can't do anything about it unless you have a way
to float W_DISABLE.
So depending on your laptop's slot pinout and BIOS behavior, and whether
or not the rfkill driver correctly supports your laptop, you might be
out of luck.
Dan
^ permalink raw reply
* [PATCH 13/16] batman-adv: add build check macros for packet member offset
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
Marek Lindner, Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
Since we removed the __packed from most of the packets, we should
make sure that the offset generated by the compiler are correct for
sent/received data.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 43dc92e..b22368e 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -393,6 +393,14 @@ static void batadv_recv_handler_init(void)
for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++)
batadv_rx_handler[i] = batadv_recv_unhandled_packet;
+ /* compile time checks for struct member offsets */
+ BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
+ BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_unicast_frag_packet, dest) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
+
/* batman icmp packet */
batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
/* unicast with 4 addresses packet */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 10/16] batman-adv: use CRC32C instead of CRC16 in TT code
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
CRC32C has to be preferred to CRC16 because of its possible
HW native support and because of the reduced collision
probability. With this change the Translation Table
component now uses CRC32C to compute the local and global
table checksum.
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/packet.h | 6 ++--
net/batman-adv/translation-table.c | 73 ++++++++++++++++++++------------------
net/batman-adv/types.h | 4 +--
3 files changed, 45 insertions(+), 38 deletions(-)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 5c08d26..7a337d7 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -345,12 +345,14 @@ struct batadv_tvlv_gateway_data {
* struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
* @flags: translation table flags (see batadv_tt_data_flags)
* @ttvn: translation table version number
- * @crc: crc16 checksum of the local translation table
+ * @reserved: field reserved for future use
+ * @crc: crc32 checksum of the local translation table
*/
struct batadv_tvlv_tt_data {
uint8_t flags;
uint8_t ttvn;
- __be16 crc;
+ uint16_t reserved;
+ __be32 crc;
};
/**
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index cb3c58e..4cdd743 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -27,7 +27,7 @@
#include "routing.h"
#include "bridge_loop_avoidance.h"
-#include <linux/crc16.h>
+#include <linux/crc32c.h>
/* hash class keys */
static struct lock_class_key batadv_tt_local_hash_lock_class_key;
@@ -409,7 +409,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
tt_data->flags = BATADV_TT_OGM_DIFF;
tt_data->ttvn = atomic_read(&bat_priv->tt.vn);
- tt_data->crc = htons(bat_priv->tt.local_crc);
+ tt_data->crc = htonl(bat_priv->tt.local_crc);
if (tt_diff_len == 0)
goto container_register;
@@ -481,7 +481,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
goto out;
seq_printf(seq,
- "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x):\n",
+ "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.8x):\n",
net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn),
bat_priv->tt.local_crc);
seq_printf(seq, " %-13s %-7s %-10s\n", "Client", "Flags",
@@ -993,7 +993,7 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
if (best_entry) {
last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
seq_printf(seq,
- " %c %pM (%3u) via %pM (%3u) (%#.4x) [%c%c%c]\n",
+ " %c %pM (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
'*', tt_global_entry->common.addr,
best_entry->ttvn, best_entry->orig_node->orig,
last_ttvn, best_entry->orig_node->tt_crc,
@@ -1037,7 +1037,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
seq_printf(seq,
"Globally announced TT entries received via the mesh %s\n",
net_dev->name);
- seq_printf(seq, " %-13s %s %-15s %s (%-6s) %s\n",
+ seq_printf(seq, " %-13s %s %-15s %s (%-10s) %s\n",
"Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC",
"Flags");
@@ -1394,17 +1394,19 @@ out:
return orig_node;
}
-/* Calculates the checksum of the local table of a given orig_node */
-static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
+/**
+ * batadv_tt_global_crc - calculates the checksum of the local table belonging
+ * to the given orig_node
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node)
{
- uint16_t total = 0, total_one;
struct batadv_hashtable *hash = bat_priv->tt.global_hash;
struct batadv_tt_common_entry *tt_common;
struct batadv_tt_global_entry *tt_global;
struct hlist_head *head;
- uint32_t i;
- int j;
+ uint32_t i, crc = 0;
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
@@ -1435,27 +1437,24 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
orig_node))
continue;
- total_one = 0;
- for (j = 0; j < ETH_ALEN; j++)
- total_one = crc16_byte(total_one,
- tt_common->addr[j]);
- total ^= total_one;
+ crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
}
rcu_read_unlock();
}
- return total;
+ return crc;
}
-/* Calculates the checksum of the local table */
-static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
+/**
+ * batadv_tt_local_crc - calculates the checksum of the local table
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
{
- uint16_t total = 0, total_one;
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
struct batadv_tt_common_entry *tt_common;
struct hlist_head *head;
- uint32_t i;
- int j;
+ uint32_t i, crc = 0;
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
@@ -1467,16 +1466,13 @@ static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
*/
if (tt_common->flags & BATADV_TT_CLIENT_NEW)
continue;
- total_one = 0;
- for (j = 0; j < ETH_ALEN; j++)
- total_one = crc16_byte(total_one,
- tt_common->addr[j]);
- total ^= total_one;
+
+ crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
}
rcu_read_unlock();
}
- return total;
+ return crc;
}
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
@@ -1662,9 +1658,18 @@ out:
return tvlv_tt_data;
}
+/**
+ * batadv_send_tt_request - send a TT Request message to a given node
+ * @bat_priv: the bat priv with all the soft interface information
+ * @dst_orig_node: the destination of the message
+ * @ttvn: the version number that the source of the message is looking for
+ * @tt_crc: the CRC associated with the version number
+ * @full_table: ask for the entire translation table if true, while only for the
+ * last TT diff otherwise
+ */
static int batadv_send_tt_request(struct batadv_priv *bat_priv,
struct batadv_orig_node *dst_orig_node,
- uint8_t ttvn, uint16_t tt_crc,
+ uint8_t ttvn, uint32_t tt_crc,
bool full_table)
{
struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
@@ -1689,7 +1694,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
tvlv_tt_data->flags = BATADV_TT_REQUEST;
tvlv_tt_data->ttvn = ttvn;
- tvlv_tt_data->crc = htons(tt_crc);
+ tvlv_tt_data->crc = htonl(tt_crc);
if (full_table)
tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
@@ -1756,7 +1761,7 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
/* this node doesn't have the requested data */
if (orig_ttvn != req_ttvn ||
- tt_data->crc != htons(req_dst_orig_node->tt_crc))
+ tt_data->crc != htonl(req_dst_orig_node->tt_crc))
goto out;
/* If the full table has been explicitly requested */
@@ -2403,13 +2408,13 @@ out:
* @tt_buff: buffer holding the tt information
* @tt_num_changes: number of tt changes inside the tt buffer
* @ttvn: translation table version number of this changeset
- * @tt_crc: crc16 checksum of orig node's translation table
+ * @tt_crc: crc32 checksum of orig node's translation table
*/
static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *tt_buff,
uint16_t tt_num_changes, uint8_t ttvn,
- uint16_t tt_crc)
+ uint32_t tt_crc)
{
uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
bool full_table = true;
@@ -2463,7 +2468,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
orig_node->tt_crc != tt_crc) {
request_table:
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u)\n",
+ "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.8x last_crc: %#.8x num_changes: %u)\n",
orig_node->orig, ttvn, orig_ttvn, tt_crc,
orig_node->tt_crc, tt_num_changes);
batadv_send_tt_request(bat_priv, orig_node, ttvn,
@@ -2571,7 +2576,7 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
batadv_tt_update_orig(bat_priv, orig,
(unsigned char *)(tt_data + 1),
- num_entries, tt_data->ttvn, ntohs(tt_data->crc));
+ num_entries, tt_data->ttvn, ntohl(tt_data->crc));
}
/**
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index bdabbc2..e98915a 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -150,7 +150,7 @@ struct batadv_orig_node {
uint8_t flags;
uint8_t capabilities;
atomic_t last_ttvn;
- uint16_t tt_crc;
+ uint32_t tt_crc;
unsigned char *tt_buff;
int16_t tt_buff_len;
spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */
@@ -377,7 +377,7 @@ struct batadv_priv_tt {
spinlock_t req_list_lock; /* protects req_list */
spinlock_t roam_list_lock; /* protects roam_list */
atomic_t local_entry_num;
- uint16_t local_crc;
+ uint32_t local_crc;
unsigned char *last_changeset;
int16_t last_changeset_len;
/* protects last_changeset & last_changeset_len */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 16/16] batman-adv: reorder batadv_iv_flags
From: Antonio Quartulli @ 2013-10-09 12:40 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
Marek Lindner, Antonio Quartulli
In-Reply-To: <1381322418-1349-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
The vis flag is not needed anymore, and since we do a compat bump we
can start with the first bit again
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/packet.h | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 4e5fe7d..4361bae 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -67,10 +67,19 @@ enum batadv_subtype {
/* this file is included by batctl which needs these defines */
#define BATADV_COMPAT_VERSION 15
+/**
+ * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets
+ * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was
+ * previously received from someone else than the best neighbor.
+ * @BATADV_PRIMARIES_FIRST_HOP: flag is set when the primary interface address
+ * is used, and the packet travels its first hop.
+ * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a
+ * one hop neighbor on the interface where it was originally received.
+ */
enum batadv_iv_flags {
- BATADV_NOT_BEST_NEXT_HOP = BIT(3),
- BATADV_PRIMARIES_FIRST_HOP = BIT(4),
- BATADV_DIRECTLINK = BIT(6),
+ BATADV_NOT_BEST_NEXT_HOP = BIT(0),
+ BATADV_PRIMARIES_FIRST_HOP = BIT(1),
+ BATADV_DIRECTLINK = BIT(2),
};
/* ICMP message types */
@@ -164,11 +173,12 @@ struct batadv_header {
/**
* struct batadv_ogm_packet - ogm (routing protocol) packet
* @header: common batman packet header
+ * @flags: contains routing relevant flags - see enum batadv_iv_flags
* @tvlv_len: length of tvlv data following the ogm header
*/
struct batadv_ogm_packet {
struct batadv_header header;
- uint8_t flags; /* 0x40: DIRECTLINK flag ... */
+ uint8_t flags;
__be32 seqno;
uint8_t orig[ETH_ALEN];
uint8_t prev_sender[ETH_ALEN];
--
1.8.3.2
^ permalink raw reply related
* [PATCH net-next] bnx2x: Add ndo_get_phys_port_id support
From: Yuval Mintz @ 2013-10-09 14:06 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval Mintz, Ariel Elior, Eilon Greenstein
Each network interface (either PF or VF) is identified by its port's MAC id.
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
Hi Dave,
Please consider applying this patch to 'net-next'.
Thanks,
Yuval Mintz
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 3 +
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 23 ++++
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 149 +++++++++++++++++++----
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 7 ++
4 files changed, 155 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8fe4bcb..5fb18cd 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1546,6 +1546,7 @@ struct bnx2x {
#define IS_VF_FLAG (1 << 22)
#define INTERRUPTS_ENABLED_FLAG (1 << 23)
#define BC_SUPPORTS_RMMOD_CMD (1 << 24)
+#define HAS_PHYS_PORT_ID (1 << 25)
#define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG)
@@ -1876,6 +1877,8 @@ struct bnx2x {
u32 dump_preset_idx;
bool stats_started;
struct semaphore stats_sema;
+
+ u8 phys_port_id[ETH_ALEN];
};
/* Tx queues may be less or equal to Rx queues */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 13a5694..e53ff1e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -11149,6 +11149,14 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
bnx2x_get_cnic_mac_hwinfo(bp);
}
+ if (!BP_NOMCP(bp)) {
+ /* Read physical port identifier from shmem */
+ val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
+ val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
+ bnx2x_set_mac_buf(bp->phys_port_id, val, val2);
+ bp->flags |= HAS_PHYS_PORT_ID;
+ }
+
memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
@@ -12044,6 +12052,20 @@ static int bnx2x_validate_addr(struct net_device *dev)
return 0;
}
+static int bnx2x_get_phys_port_id(struct net_device *netdev,
+ struct netdev_phys_port_id *ppid)
+{
+ struct bnx2x *bp = netdev_priv(netdev);
+
+ if (!(bp->flags & HAS_PHYS_PORT_ID))
+ return -EOPNOTSUPP;
+
+ ppid->id_len = sizeof(bp->phys_port_id);
+ memcpy(ppid->id, bp->phys_port_id, ppid->id_len);
+
+ return 0;
+}
+
static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_open = bnx2x_open,
.ndo_stop = bnx2x_close,
@@ -12073,6 +12095,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
#ifdef CONFIG_NET_RX_BUSY_POLL
.ndo_busy_poll = bnx2x_low_latency_recv,
#endif
+ .ndo_get_phys_port_id = bnx2x_get_phys_port_id,
};
static int bnx2x_set_coherency_mask(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index da16953..e4b90aa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -60,6 +60,30 @@ void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
mutex_unlock(&bp->vf2pf_mutex);
}
+/* Finds a TLV by type in a TLV buffer; If found, returns pointer to the TLV */
+static void *bnx2x_search_tlv_list(struct bnx2x *bp, void *tlvs_list,
+ enum channel_tlvs req_tlv)
+{
+ struct channel_tlv *tlv = (struct channel_tlv *)tlvs_list;
+
+ do {
+ if (tlv->type == req_tlv)
+ return tlv;
+
+ if (!tlv->length) {
+ BNX2X_ERR("Found TLV with length 0\n");
+ return NULL;
+ }
+
+ tlvs_list += tlv->length;
+ tlv = (struct channel_tlv *)tlvs_list;
+ } while (tlv->type != CHANNEL_TLV_LIST_END);
+
+ DP(BNX2X_MSG_IOV, "TLV list does not contain %d TLV\n", req_tlv);
+
+ return NULL;
+}
+
/* list the types and lengths of the tlvs on the buffer */
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
{
@@ -196,6 +220,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
int rc = 0, attempts = 0;
struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire;
struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp;
+ struct vfpf_port_phys_id_resp_tlv *phys_port_resp;
u32 vf_id;
bool resources_acquired = false;
@@ -219,8 +244,14 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
/* pf 2 vf bulletin board address */
req->bulletin_addr = bp->pf2vf_bulletin_mapping;
+ /* Request physical port identifier */
+ bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
+ CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));
+
/* add list termination tlv */
- bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
+ bnx2x_add_tlv(bp, req,
+ req->first_tlv.tl.length + sizeof(struct channel_tlv),
+ CHANNEL_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
/* output tlvs list */
@@ -287,6 +318,15 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
}
}
+ /* Retrieve physical port id (if possible) */
+ phys_port_resp = (struct vfpf_port_phys_id_resp_tlv *)
+ bnx2x_search_tlv_list(bp, resp,
+ CHANNEL_TLV_PHYS_PORT_ID);
+ if (phys_port_resp) {
+ memcpy(bp->phys_port_id, phys_port_resp->id, ETH_ALEN);
+ bp->flags |= HAS_PHYS_PORT_ID;
+ }
+
/* get HW info */
bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff);
bp->link_params.chip_id = bp->common.chip_id;
@@ -983,53 +1023,59 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
return bnx2x_issue_dmae_with_comp(bp, &dmae);
}
-static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
+static void bnx2x_vf_mbx_resp_single_tlv(struct bnx2x *bp,
+ struct bnx2x_virtf *vf)
{
struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
- u64 vf_addr;
- dma_addr_t pf_addr;
u16 length, type;
- int rc;
- struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
/* prepare response */
type = mbx->first_tlv.tl.type;
length = type == CHANNEL_TLV_ACQUIRE ?
sizeof(struct pfvf_acquire_resp_tlv) :
sizeof(struct pfvf_general_resp_tlv);
- bnx2x_add_tlv(bp, resp, 0, type, length);
- resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);
- bnx2x_add_tlv(bp, resp, length, CHANNEL_TLV_LIST_END,
+ bnx2x_add_tlv(bp, &mbx->msg->resp, 0, type, length);
+ bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
sizeof(struct channel_list_end_tlv));
+}
+
+static void bnx2x_vf_mbx_resp_send_msg(struct bnx2x *bp,
+ struct bnx2x_virtf *vf)
+{
+ struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
+ struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
+ dma_addr_t pf_addr;
+ u64 vf_addr;
+ int rc;
+
bnx2x_dp_tlv_list(bp, resp);
DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset);
+ resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);
+
/* send response */
vf_addr = HILO_U64(mbx->vf_addr_hi, mbx->vf_addr_lo) +
mbx->first_tlv.resp_msg_offset;
pf_addr = mbx->msg_mapping +
offsetof(struct bnx2x_vf_mbx_msg, resp);
- /* copy the response body, if there is one, before the header, as the vf
- * is sensitive to the header being written
+ /* Copy the response buffer. The first u64 is written afterwards, as
+ * the vf is sensitive to the header being written
*/
- if (resp->hdr.tl.length > sizeof(u64)) {
- length = resp->hdr.tl.length - sizeof(u64);
- vf_addr += sizeof(u64);
- pf_addr += sizeof(u64);
- rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
- U64_HI(vf_addr),
- U64_LO(vf_addr),
- length/4);
- if (rc) {
- BNX2X_ERR("Failed to copy response body to VF %d\n",
- vf->abs_vfid);
- goto mbx_error;
- }
- vf_addr -= sizeof(u64);
- pf_addr -= sizeof(u64);
+ vf_addr += sizeof(u64);
+ pf_addr += sizeof(u64);
+ rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
+ U64_HI(vf_addr),
+ U64_LO(vf_addr),
+ (sizeof(union pfvf_tlvs) - sizeof(u64))/4);
+ if (rc) {
+ BNX2X_ERR("Failed to copy response body to VF %d\n",
+ vf->abs_vfid);
+ goto mbx_error;
}
+ vf_addr -= sizeof(u64);
+ pf_addr -= sizeof(u64);
/* ack the FW */
storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
@@ -1060,6 +1106,36 @@ mbx_error:
bnx2x_vf_release(bp, vf, false); /* non blocking */
}
+static void bnx2x_vf_mbx_resp(struct bnx2x *bp,
+ struct bnx2x_virtf *vf)
+{
+ bnx2x_vf_mbx_resp_single_tlv(bp, vf);
+ bnx2x_vf_mbx_resp_send_msg(bp, vf);
+}
+
+static void bnx2x_vf_mbx_resp_phys_port(struct bnx2x *bp,
+ struct bnx2x_virtf *vf,
+ void *buffer,
+ u16 *offset)
+{
+ struct vfpf_port_phys_id_resp_tlv *port_id;
+
+ if (!(bp->flags & HAS_PHYS_PORT_ID))
+ return;
+
+ bnx2x_add_tlv(bp, buffer, *offset, CHANNEL_TLV_PHYS_PORT_ID,
+ sizeof(struct vfpf_port_phys_id_resp_tlv));
+
+ port_id = (struct vfpf_port_phys_id_resp_tlv *)
+ (((u8 *)buffer) + *offset);
+ memcpy(port_id->id, bp->phys_port_id, ETH_ALEN);
+
+ /* Offset should continue representing the offset to the tail
+ * of TLV data (outside this function scope)
+ */
+ *offset += sizeof(struct vfpf_port_phys_id_resp_tlv);
+}
+
static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct bnx2x_vf_mbx *mbx, int vfop_status)
{
@@ -1067,6 +1143,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct pfvf_acquire_resp_tlv *resp = &mbx->msg->resp.acquire_resp;
struct pf_vf_resc *resc = &resp->resc;
u8 status = bnx2x_pfvf_status_codes(vfop_status);
+ u16 length;
memset(resp, 0, sizeof(*resp));
@@ -1140,9 +1217,24 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
resc->hw_sbs[i].sb_qid);
DP_CONT(BNX2X_MSG_IOV, "]\n");
+ /* prepare response */
+ length = sizeof(struct pfvf_acquire_resp_tlv);
+ bnx2x_add_tlv(bp, &mbx->msg->resp, 0, CHANNEL_TLV_ACQUIRE, length);
+
+ /* Handle possible VF requests for physical port identifiers.
+ * 'length' should continue to indicate the offset of the first empty
+ * place in the buffer (i.e., where next TLV should be inserted)
+ */
+ if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
+ CHANNEL_TLV_PHYS_PORT_ID))
+ bnx2x_vf_mbx_resp_phys_port(bp, vf, &mbx->msg->resp, &length);
+
+ bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
+ sizeof(struct channel_list_end_tlv));
+
/* send the response */
vf->op_rc = vfop_status;
- bnx2x_vf_mbx_resp(bp, vf);
+ bnx2x_vf_mbx_resp_send_msg(bp, vf);
}
static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -1874,6 +1966,9 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event)
/* process the VF message header */
mbx->first_tlv = mbx->msg->req.first_tlv;
+ /* Clean response buffer to refrain from falsely seeing chains */
+ memset(&mbx->msg->resp, 0, sizeof(union pfvf_tlvs));
+
/* dispatch the request (will prepare the response) */
bnx2x_vf_mbx_request(bp, vf, mbx);
goto mbx_done;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index 1179fe0..208568b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -188,6 +188,12 @@ struct pfvf_acquire_resp_tlv {
} resc;
};
+struct vfpf_port_phys_id_resp_tlv {
+ struct channel_tlv tl;
+ u8 id[ETH_ALEN];
+ u8 padding[2];
+};
+
#define VFPF_INIT_FLG_STATS_COALESCE (1 << 0) /* when set the VFs queues
* stats will be coalesced on
* the leading RSS queue
@@ -398,6 +404,7 @@ enum channel_tlvs {
CHANNEL_TLV_PF_SET_MAC,
CHANNEL_TLV_PF_SET_VLAN,
CHANNEL_TLV_UPDATE_RSS,
+ CHANNEL_TLV_PHYS_PORT_ID,
CHANNEL_TLV_MAX
};
--
1.8.1.227.g44fe835
^ permalink raw reply related
* Re: bug in passing file descriptors
From: Steve Rago @ 2013-10-09 14:07 UTC (permalink / raw)
To: Andi Kleen
Cc: Andy Lutomirski, David Miller, Network Development,
Michael Kerrisk-manpages, Eric W. Biederman
In-Reply-To: <525437FF.5020905@nec-labs.com>
On 10/08/2013 12:51 PM, Steve Rago wrote:
> On 10/08/2013 12:41 PM, Andi Kleen wrote:
>>> I just want the semantics to be consistent. If you want Linux to
>>> always require applications that call recvmsg to provide a buffer
>>> size of CMSG_SPACE bytes long to retrieve control information, then
>>> fail the system call when the buffer is smaller. But if you do
>>> this, you risk breaking applications that work with FreeBSD, Mac OS
>>> X, Solaris, and probably a few others.
>>
>> The primary concern is to be binary compatible with Linux.
Not to application developers, by the way.
>>
>> But not being compatible between 32bit and 64bit Linux processes on the same
>> host would seem like a serious problem to me.
>>
>>> Regardless, copying 20 bytes and telling me you copied 24 is misleading and wrong.
>>
>> The question is could it break existing Linux applications to change it?
>> And would it help with the 32/64bit compatibility?
>>
>> If not some other way to fix the compat layer would need to be found.
>>
>> -Andi
>>
>
> I'm not sure if a 64-bit process and a 32-bit process exchange file descriptors on the same system has a problem. It
> certainly looks like the compat code does the right thing. I can test this tonight if you want.
I tested all combinations and they work fine as far as Linux binary compatibility is concerned.
Steve
^ permalink raw reply
* RE: [PATCH 10/16] batman-adv: use CRC32C instead of CRC16 in TT code
From: David Laight @ 2013-10-09 14:11 UTC (permalink / raw)
To: Antonio Quartulli, davem
Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381322418-1349-11-git-send-email-antonio@meshcoding.com>
> CRC32C has to be preferred to CRC16 because of its possible
> HW native support and because of the reduced collision
> probability. With this change the Translation Table
> component now uses CRC32C to compute the local and global
> table checksum.
...
> -/* Calculates the checksum of the local table of a given orig_node */
> -static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> +/**
> + * batadv_tt_global_crc - calculates the checksum of the local table belonging
> + * to the given orig_node
> + * @bat_priv: the bat priv with all the soft interface information
> + */
> +static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> struct batadv_orig_node *orig_node)
...
> for (i = 0; i < hash->size; i++) {
> head = &hash->table[i];
> @@ -1435,27 +1437,24 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> orig_node))
> continue;
>
...
> + crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
> }
Are you really generating CRC32 of a pile of ethernet MAC addresses
and the XORing the CRC together?
That gives the same answer as XORing together the MAC addresses and
then doing a CRC of the final value.
So it gives you almost no protection against corruption at all.
...
> -/* Calculates the checksum of the local table */
> -static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
> +/**
> + * batadv_tt_local_crc - calculates the checksum of the local table
> + * @bat_priv: the bat priv with all the soft interface information
> + */
> +static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
> {
...
This looks like a clone of the previous routine.
Surely you can avoid the code duplication.
David
^ permalink raw reply
* Re: [PATCH 10/16] batman-adv: use CRC32C instead of CRC16 in TT code
From: Antonio Quartulli @ 2013-10-09 14:35 UTC (permalink / raw)
To: David Laight; +Cc: davem, netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B7384@saturn3.aculab.com>
[-- Attachment #1: Type: text/plain, Size: 2770 bytes --]
On Wed, Oct 09, 2013 at 03:11:08PM +0100, David Laight wrote:
> > CRC32C has to be preferred to CRC16 because of its possible
> > HW native support and because of the reduced collision
> > probability. With this change the Translation Table
> > component now uses CRC32C to compute the local and global
> > table checksum.
> ...
> > -/* Calculates the checksum of the local table of a given orig_node */
> > -static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> > +/**
> > + * batadv_tt_global_crc - calculates the checksum of the local table belonging
> > + * to the given orig_node
> > + * @bat_priv: the bat priv with all the soft interface information
> > + */
> > +static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> > struct batadv_orig_node *orig_node)
> ...
> > for (i = 0; i < hash->size; i++) {
> > head = &hash->table[i];
> > @@ -1435,27 +1437,24 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
> > orig_node))
> > continue;
> >
> ...
> > + crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
> > }
>
> Are you really generating CRC32 of a pile of ethernet MAC addresses
> and the XORing the CRC together?
> That gives the same answer as XORing together the MAC addresses and
> then doing a CRC of the final value.
I was not sure about this since the CRC32 is not a linear operation. However
this routine is not on the fast path, so we can also live with this order.
> So it gives you almost no protection against corruption at all.
The corruption check is for the entire global table.
The global table is the union of the local tables of all the other nodes (each
node has a local and a global table).
The resulting value (the xor of the CRCs) is then compared to the value
sent by whom originated this piece of global table.
In this way each batman-adv node is sure to have the entries that the node
really generated in its local table.
(sorry for using the word table several times..)
Does this clarify? or have I misunderstood your objection?
>
> ...
> > -/* Calculates the checksum of the local table */
> > -static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
> > +/**
> > + * batadv_tt_local_crc - calculates the checksum of the local table
> > + * @bat_priv: the bat priv with all the soft interface information
> > + */
> > +static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
> > {
> ...
>
> This looks like a clone of the previous routine.
> Surely you can avoid the code duplication.
Some parts are the same, true. But this was already like this.
We can surely try to improve it later on with another patch.
Regards,
--
Antonio Quartulli
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Fwd: [PATCH 1/1] hso: fix problem with wrong status code sent by OPTION GTM601 during RING indication
From: Eric Verdonck @ 2013-10-09 14:38 UTC (permalink / raw)
To: marek.belisko, linux-usb, netdev; +Cc: Jan Dumon, linux-kernel
In-Reply-To: <7685369CB6CCA443BA30E328A476A8CB2BDD6D@SRV-SATURNUS.OPTION.local>
Met vriendelijke groeten,
Eric Verdonck
Driver Development
Option nv, Gaston Geenslaan 14, B-3001 Leuven
T: +32 16 311 597
F: +32 16 207 164
E-mail: e.verdonck@option.com
Website: www.option.com
Disclaimer:http://www.option.com/company/disclaimer.shtml
RPR Leuven 0429.375.448
On 10/09/2013 03:58 PM, Eric Verdonck wrote:
> Hi all,
>
> Thank you very much for your problem report. The line
> le16_to_cpu(serial_state_notification->wIndex) != W_INDEX) in the
> function "tiocmget_intr_callback" of the hso driver intents to discard
> the notification if the notification urb is not coming from the modem
> interface. Actually the line discards the urb if the interface number
> differs from the hard coded value W_INDEX ( see Table 67:
> Class-Specific Notifications of
> www.usb.org/developers/devclass_docs/usbcdc11.pdf for the meaning of
> wIndex). Depending of the tyoe of device used and/or depending of the
> actual configuration of the device the interface number of the modem
> port will vary. Therefore I would like to suggest to remove this check
> and replace it by a discard if the urb doesn't belong to an interface
> with its port_spec set to HSO_PORT_MODEM. This test has the advantage
> that it's independend of the actual configuration or type of the modem
> device ( see patch below)
>
> diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
> index e2dd324..288ec46 100644
> --- a/drivers/net/usb/hso.c
> +++ b/drivers/net/usb/hso.c
> @@ -1503,7 +1503,7 @@ static void tiocmget_intr_callback(struct urb *urb)
> if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
> serial_state_notification->bNotification != B_NOTIFICATION ||
> le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
> - le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
> + (serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM ||
> le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
> dev_warn(&usb->dev,
> "hso received invalid serial state notification\n");
> Best regards,
> Eric Verdonck
> Firmware development engineer
> Option nv, Gaston Geenslaan 14, B-3001 Leuven
>
> T: +32 16 311 597
> F: +32 16 207 164
> E-mail:e.verdonck@option.com
> Website:www.option.com
> Disclaimer:http://www.option.com/company/disclaimer.shtml
>
> RPR Leuven 0429.375.448
>
> On 10/09/2013 01:37 PM, Jan Dumon wrote:
>>
>>
>>
>> -------- Original Message --------
>> Subject: Fwd: [PATCH 1/1] hso: fix problem with wrong status code
>> sent by OPTION GTM601 during RING indication
>> Date: Fri, 4 Oct 2013 08:49:46 +0200
>> From: Jan Dumon <J.Dumon@option.com>
>> To: Axel Schollaert <a.schollaert@option.com>
>>
>>
>>
>>
>>
>>
>> -------- Original Message --------
>> Subject: [PATCH 1/1] hso: fix problem with wrong status code sent by
>> OPTION GTM601 during RING indication
>> Date: Wed, 2 Oct 2013 09:00:18 +0200
>> From: Dr. H. Nikolaus Schaller <hns@goldelico.com>
>> To: Jan Dumon <j.dumon@option.com>
>> CC: Belisko Marek <marek.belisko@gmail.com>,
>> linux-usb@vger.kernel.org, netdev@vger.kernel.org,
>> linux-kernel@vger.kernel.org
>>
>>
>>
>> Hi Jan,
>>
>> we are using a GTM601 modem (Firmware 1.7) for a while and have spotted an
>> issue that under some conditions the modem sends a packed wIndex over USB
>> that is rejected by the hso driver making troubles afterwards. Not rejecting makes
>> it work fine.
>>
>> BR,
>> Nikolaus Schaller
>>
>> ---
>>
>> From f5c7e15b61f2ce4fe3105ff914f6bfaf5d74af0d Mon Sep 17 00:00:00 2001
>> From: "H. Nikolaus Schaller"<hns@goldelico.com>
>> Date: Thu, 15 Nov 2012 14:40:57 +0100
>> Subject: [PATCH 1/1] hso: fix problem with wrong status code sent by OPTION
>> GTM601 during RING indication
>>
>> It has been observed that the GTM601 with 1.7 firmware sometimes sends a value
>> wIndex that has bit 0x04 set instead of being reset as the code expects. So we
>> mask it for the error check.
>>
>> Seehttp://lists.goldelico.com/pipermail/gta04-owner/2012-February/001643.html
>>
>> Signed-off-by: NeilBrown<neilb@suse.de>
>> Signed-off-by: H. Nikolaus Schaller<hns@goldelico.de>
>> ---
>> drivers/net/usb/hso.c | 3 ++-
>> 1 files changed, 2 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
>> index cba1d46..d146e26 100644
>> --- a/drivers/net/usb/hso.c
>> +++ b/drivers/net/usb/hso.c
>> @@ -1503,7 +1503,8 @@ static void tiocmget_intr_callback(struct urb *urb)
>> if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
>> serial_state_notification->bNotification != B_NOTIFICATION ||
>> le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
>> - le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
>> + (le16_to_cpu(serial_state_notification->wIndex) & ~0x4) !=
>> + W_INDEX ||
>> le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
>> dev_warn(&usb->dev,
>> "hso received invalid serial state notification\n");
>> --
>> 1.7.7.4
>>
>>
>>
>>
>>
>>
>
^ permalink raw reply
* Re: [PATCH] Stmmac: fix a bug when clk_csr == 0x0
From: Wan ZongShun @ 2013-10-09 15:02 UTC (permalink / raw)
To: Giuseppe CAVALLARO; +Cc: netdev
In-Reply-To: <52556BA2.1080004@st.com>
2013/10/9 Giuseppe CAVALLARO <peppe.cavallaro@st.com>:
> hello
>
>
> On 10/9/2013 4:37 AM, Wan ZongShun wrote:
>>
>> Hi Giuseppe,
>>
>> According to spec, if csr clock freq is 60-100Mhz, we have to set CR[5:2]
>> = 0000
>> but when I set the 'plat_dat.clk_csr = 0',acctually, this value is not
>> used
>> since the driver code judge 'if (!priv->plat->clk_csr)' then go to dynamic
>> tune
>> the MDC clock. So I add other judge condition.
>
>
> yes, and true in case of 60-100Mhz... I don't know if this was actually
> tested on SPEAr long time ago.
>
Hmmm, I am using other GBE chip based on synopsis IP, so I am testing
it on other platform.
> Pls document the new platform field in the stmmac.txt or find a way
> to reuse the clk_csr (maybe not the case)
Do you mean I need submit the other patch to add some comments for
this new field?
I can not find better way to fix this issue and make it more
compatible to another platform.
Wan.
>
> peppe
>
>
>>
>> Signed-off-by: Wan Zongshun <mcuos.com@gmail.com>
>> ---
>> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
>> include/linux/stmmac.h | 1 +
>> 2 files changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index 8d4ccd3..a849092c 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -2741,7 +2741,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct
>> device *device,
>> * set the MDC clock dynamically according to the csr actual
>> * clock input.
>> */
>> - if (!priv->plat->clk_csr)
>> + if (priv->plat->dynamic_mdc_clk_en)
>> stmmac_clk_csr_set(priv);
>> else
>> priv->clk_csr = priv->plat->clk_csr;
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index bb5deb0..e2552ce 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -101,6 +101,7 @@ struct plat_stmmacenet_data {
>> struct stmmac_mdio_bus_data *mdio_bus_data;
>> struct stmmac_dma_cfg *dma_cfg;
>> int clk_csr;
>> + int dynamic_mdc_clk_en;
>> int has_gmac;
>> int enh_desc;
>> int tx_coe;
>>
>
--
Wan ZongShun.
www.mcuos.com
^ permalink raw reply
* Re: [PATCH] Stmmac: fix a bug when clk_csr == 0x0
From: Giuseppe CAVALLARO @ 2013-10-09 14:43 UTC (permalink / raw)
To: Wan ZongShun; +Cc: netdev
In-Reply-To: <CAKT61h8mcj1Gvp1i8xkM_NS2+fv1WhPtCQaFq7mi=i=JUqT4Uw@mail.gmail.com>
hello
On 10/9/2013 4:37 AM, Wan ZongShun wrote:
> Hi Giuseppe,
>
> According to spec, if csr clock freq is 60-100Mhz, we have to set CR[5:2] = 0000
> but when I set the 'plat_dat.clk_csr = 0',acctually, this value is not used
> since the driver code judge 'if (!priv->plat->clk_csr)' then go to dynamic tune
> the MDC clock. So I add other judge condition.
yes, and true in case of 60-100Mhz... I don't know if this was actually
tested on SPEAr long time ago.
Pls document the new platform field in the stmmac.txt or find a way
to reuse the clk_csr (maybe not the case)
peppe
>
> Signed-off-by: Wan Zongshun <mcuos.com@gmail.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
> include/linux/stmmac.h | 1 +
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 8d4ccd3..a849092c 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2741,7 +2741,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct
> device *device,
> * set the MDC clock dynamically according to the csr actual
> * clock input.
> */
> - if (!priv->plat->clk_csr)
> + if (priv->plat->dynamic_mdc_clk_en)
> stmmac_clk_csr_set(priv);
> else
> priv->clk_csr = priv->plat->clk_csr;
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index bb5deb0..e2552ce 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -101,6 +101,7 @@ struct plat_stmmacenet_data {
> struct stmmac_mdio_bus_data *mdio_bus_data;
> struct stmmac_dma_cfg *dma_cfg;
> int clk_csr;
> + int dynamic_mdc_clk_en;
> int has_gmac;
> int enh_desc;
> int tx_coe;
>
^ permalink raw reply
* Re: [PATCH] Stmmac: fix a bug when clk_csr == 0x0
From: Giuseppe CAVALLARO @ 2013-10-09 15:16 UTC (permalink / raw)
To: Wan ZongShun; +Cc: netdev
In-Reply-To: <CAKT61h8ZLQRUsD99vOYyK8jj0o_SHhA+PN4MoPA5SS9V+eit5g@mail.gmail.com>
On 10/9/2013 5:02 PM, Wan ZongShun wrote:
> 2013/10/9 Giuseppe CAVALLARO <peppe.cavallaro@st.com>:
>> hello
>>
>>
>> On 10/9/2013 4:37 AM, Wan ZongShun wrote:
>>>
>>> Hi Giuseppe,
>>>
>>> According to spec, if csr clock freq is 60-100Mhz, we have to set CR[5:2]
>>> = 0000
>>> but when I set the 'plat_dat.clk_csr = 0',acctually, this value is not
>>> used
>>> since the driver code judge 'if (!priv->plat->clk_csr)' then go to dynamic
>>> tune
>>> the MDC clock. So I add other judge condition.
>>
>>
>> yes, and true in case of 60-100Mhz... I don't know if this was actually
>> tested on SPEAr long time ago.
>>
>
> Hmmm, I am using other GBE chip based on synopsis IP, so I am testing
> it on other platform.
>
>> Pls document the new platform field in the stmmac.txt or find a way
>> to reuse the clk_csr (maybe not the case)
>
> Do you mean I need submit the other patch to add some comments for
> this new field?
yes in the Documentation/networking/stmmac.txt
peppe
> I can not find better way to fix this issue and make it more
> compatible to another platform.
>
> Wan.
>
>>
>> peppe
>>
>>
>>>
>>> Signed-off-by: Wan Zongshun <mcuos.com@gmail.com>
>>> ---
>>> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
>>> include/linux/stmmac.h | 1 +
>>> 2 files changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> index 8d4ccd3..a849092c 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> @@ -2741,7 +2741,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct
>>> device *device,
>>> * set the MDC clock dynamically according to the csr actual
>>> * clock input.
>>> */
>>> - if (!priv->plat->clk_csr)
>>> + if (priv->plat->dynamic_mdc_clk_en)
>>> stmmac_clk_csr_set(priv);
>>> else
>>> priv->clk_csr = priv->plat->clk_csr;
>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>> index bb5deb0..e2552ce 100644
>>> --- a/include/linux/stmmac.h
>>> +++ b/include/linux/stmmac.h
>>> @@ -101,6 +101,7 @@ struct plat_stmmacenet_data {
>>> struct stmmac_mdio_bus_data *mdio_bus_data;
>>> struct stmmac_dma_cfg *dma_cfg;
>>> int clk_csr;
>>> + int dynamic_mdc_clk_en;
>>> int has_gmac;
>>> int enh_desc;
>>> int tx_coe;
>>>
>>
>
>
>
^ permalink raw reply
* Re: [PATCH net 0/4] bridge: Fix problems around the PVID
From: Vlad Yasevich @ 2013-10-09 15:01 UTC (permalink / raw)
To: Toshiaki Makita
Cc: Toshiaki Makita, David Miller, netdev, Fernando Luis Vazquez Cao,
Patrick McHardy
In-Reply-To: <1380628602.3150.59.camel@ubuntu-vm-makita>
On 10/01/2013 07:56 AM, Toshiaki Makita wrote:
> On Mon, 2013-09-30 at 12:01 -0400, Vlad Yasevich wrote:
>> On 09/30/2013 07:46 AM, Toshiaki Makita wrote:
>>> On Fri, 2013-09-27 at 14:10 -0400, Vlad Yasevich wrote:
>>>> On 09/27/2013 01:11 PM, Toshiaki Makita wrote:
>>>>> On Thu, 2013-09-26 at 10:22 -0400, Vlad Yasevich wrote:
>>>>>> On 09/26/2013 06:38 AM, Toshiaki Makita wrote:
>>>>>>> On Tue, 2013-09-24 at 13:55 -0400, Vlad Yasevich wrote:
>>>>>>>> On 09/24/2013 01:30 PM, Toshiaki Makita wrote:
>>>>>>>>> On Tue, 2013-09-24 at 09:35 -0400, Vlad Yasevich wrote:
>>>>>>>>>> On 09/24/2013 07:45 AM, Toshiaki Makita wrote:
>>>>>>>>>>> On Mon, 2013-09-23 at 10:41 -0400, Vlad Yasevich
>>>>>>>>>>> wrote:
>>>>>>>>>>>> On 09/17/2013 04:12 AM, Toshiaki Makita wrote:
>>>>>>>>>>>>> On Mon, 2013-09-16 at 13:49 -0400, Vlad Yasevich
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>> On 09/13/2013 08:06 AM, Toshiaki Makita wrote:
>>>>>>>>>>>>>>> On Thu, 2013-09-12 at 16:00 -0400, David
>>>>>>>>>>>>>>> Miller wrote:
>>>>>>>>>>>>>>>> From: Toshiaki Makita
>>>>>>>>>>>>>>>> <makita.toshiaki@lab.ntt.co.jp> Date: Tue,
>>>>>>>>>>>>>>>> 10 Sep 2013 19:27:54 +0900
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> There seem to be some undesirable
>>>>>>>>>>>>>>>>> behaviors related with PVID. 1. It has no
>>>>>>>>>>>>>>>>> effect assigning PVID to a port. PVID
>>>>>>>>>>>>>>>>> cannot be applied to any frame regardless
>>>>>>>>>>>>>>>>> of whether we set it or not. 2. FDB
>>>>>>>>>>>>>>>>> entries learned via frames applied PVID
>>>>>>>>>>>>>>>>> are registered with VID 0 rather than VID
>>>>>>>>>>>>>>>>> value of PVID. 3. We can set 0 or 4095 as
>>>>>>>>>>>>>>>>> a PVID that are not allowed in IEEE
>>>>>>>>>>>>>>>>> 802.1Q. This leads interoperational
>>>>>>>>>>>>>>>>> problems such as sending frames with VID
>>>>>>>>>>>>>>>>> 4095, which is not allowed in IEEE
>>>>>>>>>>>>>>>>> 802.1Q, and treating frames with VID 0 as
>>>>>>>>>>>>>>>>> they belong to VLAN 0, which is expected
>>>>>>>>>>>>>>>>> to be handled as they have no VID
>>>>>>>>>>>>>>>>> according to IEEE 802.1Q.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Note: 2nd and 3rd problems are potential
>>>>>>>>>>>>>>>>> and not exposed unless 1st problem is
>>>>>>>>>>>>>>>>> fixed, because we cannot activate PVID
>>>>>>>>>>>>>>>>> due to it.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Please work out the issues in patch #2 with
>>>>>>>>>>>>>>>> Vlad and resubmit this series.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Thank you.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I'm hovering between whether we should fix
>>>>>>>>>>>>>>> the issue by changing vlan 0 interface
>>>>>>>>>>>>>>> behavior in 8021q module or enabling a bridge
>>>>>>>>>>>>>>> port to sending priority-tagged frames, or
>>>>>>>>>>>>>>> another better way.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> If you could comment it, I'd appreciate it
>>>>>>>>>>>>>>> :)
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> BTW, I think what is discussed in patch #2 is
>>>>>>>>>>>>>>> another problem about handling priority-tags,
>>>>>>>>>>>>>>> and it exists without this patch set
>>>>>>>>>>>>>>> applied. It looks like that we should prepare
>>>>>>>>>>>>>>> another patch set than this to fix that
>>>>>>>>>>>>>>> problem.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Should I include patches that fix the
>>>>>>>>>>>>>>> priority-tags problem in this patch set and
>>>>>>>>>>>>>>> resubmit them all together?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I am thinking that we might need to do it in
>>>>>>>>>>>>>> bridge and it looks like the simplest way to do
>>>>>>>>>>>>>> it is to have default priority regeneration
>>>>>>>>>>>>>> table (table 6-5 from 802.1Q doc).
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> That way I think we would conform to the spec.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -vlad
>>>>>>>>>>>>>
>>>>>>>>>>>>> Unfortunately I don't think the default priority
>>>>>>>>>>>>> regeneration table resolves the problem because
>>>>>>>>>>>>> IEEE 802.1Q says that a VLAN-aware bridge can
>>>>>>>>>>>>> transmit untagged or VLAN-tagged frames only (the
>>>>>>>>>>>>> end of section 7.5 and 8.1.7).
>>>>>>>>>>>>>
>>>>>>>>>>>>> No mechanism to send priority-tagged frames is
>>>>>>>>>>>>> found as far as I can see the standard. I think
>>>>>>>>>>>>> the regenerated priority is used for outgoing
>>>>>>>>>>>>> PCP field only if egress policy is not untagged
>>>>>>>>>>>>> (i.e. transmitting as VLAN-tagged), and unused if
>>>>>>>>>>>>> untagged (Section 6.9.2 3rd/4th Paragraph).
>>>>>>>>>>>>>
>>>>>>>>>>>>> If we want to transmit priority-tagged frames
>>>>>>>>>>>>> from a bridge port, I think we need to implement
>>>>>>>>>>>>> a new (optional) feature that is above the
>>>>>>>>>>>>> standard, as I stated previously.
>>>>>>>>>>>>>
>>>>>>>>>>>>> How do you feel about adding a per-port policy
>>>>>>>>>>>>> that enables a bridge to send priority-tagged
>>>>>>>>>>>>> frames instead of untagged frames when egress
>>>>>>>>>>>>> policy for the port is untagged? With this
>>>>>>>>>>>>> change, we can transmit frames for a given vlan
>>>>>>>>>>>>> as either all untagged, all priority-tagged or
>>>>>>>>>>>>> all VLAN-tagged.
>>>>>>>>>>>>
>>>>>>>>>>>> That would work. What I am thinking is that we do
>>>>>>>>>>>> it by special casing the vid 0 egress policy
>>>>>>>>>>>> specification. Let it be untagged by default and
>>>>>>>>>>>> if it is tagged, then we preserve the priority
>>>>>>>>>>>> field and forward it on.
>>>>>>>>>>>>
>>>>>>>>>>>> This keeps the API stable and doesn't require
>>>>>>>>>>>> user/admin from knowing exactly what happens.
>>>>>>>>>>>> Default operation conforms to the spec and allows
>>>>>>>>>>>> simple change to make it backward-compatible.
>>>>>>>>>>>>
>>>>>>>>>>>> What do you think. I've done a simple prototype of
>>>>>>>>>>>> this an it seems to work with the VMs I am testing
>>>>>>>>>>>> with.
>>>>>>>>>>>
>>>>>>>>>>> Are you saying that - by default, set the 0th bit of
>>>>>>>>>>> untagged_bitmap; and - if we unset the 0th bit and
>>>>>>>>>>> set the "vid"th bit, we transmit frames classified as
>>>>>>>>>>> belonging to VLAN "vid" as priority-tagged?
>>>>>>>>>>>
>>>>>>>>>>> If so, though it's attractive to keep current API,
>>>>>>>>>>> I'm worried about if it could be a bit confusing and
>>>>>>>>>>> not intuitive for kernel/iproute2 developers that VID
>>>>>>>>>>> 0 has a special meaning only in the egress policy.
>>>>>>>>>>> Wouldn't it be better to adding a new member to
>>>>>>>>>>> struct net_port_vlans instead of using VID 0 of
>>>>>>>>>>> untagged_bitmap?
>>>>>>>>>>>
>>>>>>>>>>> Or are you saying that we use a new flag in struct
>>>>>>>>>>> net_port_vlans but use the BRIDGE_VLAN_INFO_UNTAGGED
>>>>>>>>>>> bit with VID 0 in netlink to set the flag?
>>>>>>>>>>>
>>>>>>>>>>> Even in that case, I'm afraid that it might be
>>>>>>>>>>> confusing for developers for the same reason. We are
>>>>>>>>>>> going to prohibit to specify VID with 0 (and 4095) in
>>>>>>>>>>> adding/deleting a FDB entry or a vlan filtering
>>>>>>>>>>> entry, but it would allow us to use VID 0 only when a
>>>>>>>>>>> vlan filtering entry is configured. I am thinking a
>>>>>>>>>>> new nlattr is a straightforward approach to
>>>>>>>>>>> configure it.
>>>>>>>>>>
>>>>>>>>>> By making this an explicit attribute it makes vid 0 a
>>>>>>>>>> special case for any automatic tool that would
>>>>>>>>>> provision such filtering. Seeing vid 0 would mean that
>>>>>>>>>> these tools would have to know that this would have to
>>>>>>>>>> be translated to a different attribute instead of
>>>>>>>>>> setting the policy values.
>>>>>>>>>
>>>>>>>>> Yes, I agree with you that we can do it by the way you
>>>>>>>>> explained. What I don't understand is the advantage of
>>>>>>>>> using vid 0 over another way such as adding a new
>>>>>>>>> nlattr. I think we can indicate transmitting
>>>>>>>>> priority-tags explicitly by such a nlattr. Using vid 0
>>>>>>>>> seems to be easier to implement than a new nlattr, but,
>>>>>>>>> for me, it looks less intuitive and more difficult to
>>>>>>>>> maintain because we have to care about vid 0 instead of
>>>>>>>>> simply ignoring it.
>>>>>>>>>
>>>>>>>>
>>>>>>>> The point I am trying to make is that regardless of the
>>>>>>>> approach someone has to know what to do when enabling
>>>>>>>> priority tagged frames. You proposal would require the
>>>>>>>> administrator or config tool to have that knowledge.
>>>>>>>> Example is: Admin does: bridge vlan set priority on dev
>>>>>>>> eth0 Automated app: if (vid == 0) /* Turn on priority
>>>>>>>> tagged frame support */
>>>>>>>>
>>>>>>>> My proposal would require the bridge filtering
>>>>>>>> implementation to have it. user tool: bridge vlan add vid 0
>>>>>>>> tagged Automated app: No special case.
>>>>>>>>
>>>>>>>> IMO its better to have 1 piece code handling the special
>>>>>>>> case then putting it multiple places.
>>>>>>>
>>>>>>> Thank you for the detailed explanation. Now I understand your
>>>>>>> intention.
>>>>>>>
>>>>>>> I have one question about your proposal. I guess the way to
>>>>>>> enable priority-tagged is something like bridge vlan add vid
>>>>>>> 10 dev eth0 bridge vlan add vid 10 dev vnet0 pvid untagged
>>>>>>> bridge vlan add vid 0 dev vnet0 tagged where vnet0 has sub
>>>>>>> interface vnet0.0.
>>>>>>>
>>>>>>> Here the admin have to know the egress policy is applied to a
>>>>>>> frame twice in a certain order when it is transmitted from
>>>>>>> the port vnet0 attached, that is, first, a frame with vid 10
>>>>>>> get untagged, and then, an untagged frame get
>>>>>>> priority-tagged.
>>>>>>>
>>>>>>> This behavior looks difficult to know without previous
>>>>>>> knowledge. Any good idea to avoid such a need for the admin's
>>>>>>> additional knowledge?
>>>>>>
>>>>>> To me, the fact that there is vnet0.0 (or typically, there is
>>>>>> eth0.0 in the guest or on the remote host) already tells the
>>>>>> admin vlan 0 has to be tagged. The fact that we codify this in
>>>>>> the policy makes it explicit.
>>>>>
>>>>> My worry is that the admin might not be able to guess how to use
>>>>> bridge commands to enable priority-tag without any additional
>>>>> hint in "man bridge", "bridge vlan help", etc. I actually
>>>>> couldn't hit upon such a usage before seeing example commands you
>>>>> gave, because I had never think the egress policy could be
>>>>> applied twice.
>>>>>
>>>>>>
>>>>>> However, I can see strong argument to be made for an addition
>>>>>> egress policy attribute that could be for instance:
>>>>>>
>>>>>> bridge vlan add vid 10 dev eth0 pvid bridge vlan add vid 10 dev
>>>>>> vnet0 pvid untagged prio_tag
>>>>>>
>>>>>> But this has the same connotations as wrt to egress policy.
>>>>>> The 2 policies are applied: (1) untag the frame. (2) add
>>>>>> priority_tag.
>>>>>>
>>>>>> (2) only happens if initial fame received on eth0 was priority
>>>>>> tagged.
>>>>>
>>>>> If we do so, we will not be able to communicate using vlan 0
>>>>> interface under a certain circumstance. Eth0 can be receive mixed
>>>>> untagged and priority-tagged frames according to the network
>>>>> element it is connected to: for example, Open vSwitch can send
>>>>> such two kinds of frames from the same port even if original
>>>>> incoming frames belong to the same vlan.
>>>>
>>>> Which priority would you assign to the frame that was received
>>>> untagged?
>>>
>>> Untagged frame's priority is by default 0, so I think 0 is likely.
>>>
>>> 802.1Q 6.9.1 i) The received priority value and the drop_eligible
>>> parameter value are the values in the M_UNITDATA.indication.
>>>
>>> M_UNITDATA is passed from ISS.
>>>
>>> 802.1Q 6.7.1 The priority parameter provided in a data indication
>>> primitive shall take the value of the Default User Priority parameter
>>> for the Port through which the MAC frame was received. The default
>>> value of this parameter is 0, it may be set by management in which
>>> case the capability to set it to any of the values 0 through 7 shall
>>> be provided.
>>>
>>>>
>>>>> In this situation, we can only receive frames that is
>>>>> priority-tagged when received on eth0.
>>>>
>>>> Not sure I understand. Let's look at this config: bridge vlan add
>>>> vid 10 dev eth0 pvid bridge vlan add vid 10 dev vnet0 pvid untagged
>>>> prio_tag
>>>>
>>>> Here, eth0 is allowed to receive vid 10 tagged, untagged, and
>>>> prio_tagged (if we look at the patch 2 from this set). Now, frame
>>>> is forwarded to vnet0. 1) if the frame had vid 10 in the tag or was
>>>> untagged, it should probably be sent untagged. 2) if the frame had
>>>> a priority tag, it should probably be sent as such.
>>>>
>>>> Now, I think a case could be made that if the frame had any
>>>> priority markings in the vlan header, we should try to preserve
>>>> those markings if prio_tag is turned on. We can assume value of 0
>>>> means not set.
>>>
>>> If we don't insert prio_tag when PCP is 0, we might receive mixed
>>> priority-tagged and untagged frames on eth0.
>>
>> Right, and that's what you were trying to handle in your patch:
>>
>>> + /* PVID is set on this port. Any untagged or priority-tagged +
>>> * ingress frame is considered to belong to this vlan. */
>>
>> So, in this case we are prepared to handle the "mixed" scenario on ingress.
>>
>>> Even if we are sending frames from eth0.0 with some priority other
>>> than 0, we could receive frames with priority 0 or untagged on the
>>> other side of the bridge.
>>> For example, if we receive untagged arp reply on the bridge port, we
>>> migit not be able to communicate with such an end station, because
>>> untagged reply will not be passed to eth0.0.
>>
>> So the ARP request was sent tagged, but the reply came back untagged?
>
> Yes, it can happen.
> These are problematic cases.
>
> Example 1:
> prio_tagged prio_tagged
> +------------+ ---> +------------+ ---> +----------+
> |guest eth0.0|------|host1 Bridge|------|host2 eth0|
> +------------+ <--- +------------+ <--- +----------+
> untagged untagged
>
> Note: Host2 eth0, which is an interface on Linux, can receive
> priority-tagged frames if it doesn't have vlan 0 interface (eth0.0).
Hmm.. Just to see if this works, I ran the this scenario with
a dumb switch in the middle, and it did not work as you noted.
I then realized that one of the kernels was rather old and after
updating it, behaved differently. The communication still didn't
work, but host2 behaved properly.
>>
>> How does that work when the end station is attached directly to the
>> HW switch instead of a linux bridge?
>>
>> The station configures eth0.0 and sends priority-tagged traffic to
>> the HW switch. If the HW switch sends back untagged traffic, then
>> the untagged traffic will never reach eth0.0.
>
> Currently we cannot communicate using eth0.0 via directly connected
> 802.1Q conformed switch, because we never receive priority-tagged frames
> from the switch.
> It is not a problem of Linux bridge and is why I wondered whether it
> should be fixed by bridge or vlan 0 interface.
>
>>
>>>
>>>>
>>>>> IMO, if prio_tag is configured, the bridge should send any
>>>>> untagged frame as priority-tagged regardless of whatever it is on
>>>>> eth0.
>>>>
>>>> Which priority would you use, 0? You are not guaranteed to
>>>> properly deliver the traffic then for a configuration such as: VM:
>>>> eth0: 10.0.0.1/24 eth0.0: 10.0.1.1/24
>>>
>>> I'd like to use priority 0 for untagged frames.
>>>
>>> I am assuming that one of our goals is at least that eth0.0 comes to
>>> be able to communicate with another end station. It seems to be hard
>>> to use both eth0 and eth0.0 simultaneously.
>>
>> I understand, but I don't agree that we should always tag.
>>
>> Consider config:
>>
>> hw switch <---> (eth0: Linux Bridge: eth1) <--- (em1.0:end station)
>>
>> If the end station sends priority-tagged traffic it should receive
>> priority tagged traffic back. Otherwise, untagged traffic may be
>> dropped by the end station. This is true whether it is connected to
>> the hw switch or Linux bridge.
>
> Though such a behavior is generally not necessary as far as I can read
> 802.1Q spec, it is essential for vlan 0 interface on Linux, I think.
> My proposal aims to resolve it at least when we use Linux bridge.
>
> Example configuration:
> bridge vlan add vid 10 dev eth1 pvid untagged
> bridge vlan add vid 10 dev eth0
> bridge vlan set prio_tag on dev eth1
>
> Intended behavior:
>
> VID10-tagged prio_tagged
> +---------+ <--- +------------------------+ <--- +-----------------+
> |hw switch|------|eth0: Linux Bridge: eth1|------|em1.0:end station|
> +---------+ ---> +------------------------+ ---> +-----------------+
> VID10-tagged prio_tagged
> (always if egress policy untagged)
Ok, I think you've convinced me that this is the right approach. The
only thing that I am not crazy about is the API. I'd almost want to
introduce a new flag that can be set in a 'vlan add' or 'vlan set'
command that communicates a new policy.
Thanks
-vlad
>
> Thanks,
>
> Toshiaki Makita
>
>>
>> -vlad
>>
>>>
>>> Thanks,
>>>
>>> Toshiaki Makita
>>>
>>>>
>>>> -vlad
>>>>
>>>>>
>>>>>>
>>>>>> I think I am ok with either approach. Explicit vid 0 policy is
>>>>>> easier for automatic provisioning. The flag based one is
>>>>>> easier for admin/ manual provisioning.
>>>>>
>>>>> Supposing we have to add something to help or man in any case, I
>>>>> think flag based is better. The format below seems to suitable
>>>>> for a per-port policy. bridge vlan set prio_tag on dev vnet0
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Toshiaki Makita
>>>>>
>>>>>>
>>>>>> -vlad.
>>>>>>
>>>>>> -vlad
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks -vlad
>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>>
>>>>>>>>> Toshiaki Makita
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> How it is implemented internally in the kernel isn't as
>>>>>>>>>> big of an issue. We can do it as a separate flag or as
>>>>>>>>>> part of existing policy.
>>>>>>>>>>
>>>>>>>>>> -vlad
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>>
>>>>>>>>>>> Toshiaki Makita
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> -vlad
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Toshiaki Makita
>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Toshiaki Makita
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> -- To unsubscribe from this list: send the
>>>>>>>>>>>>>>>> line "unsubscribe netdev" in the body of a
>>>>>>>>>>>>>>>> message to majordomo@vger.kernel.org More
>>>>>>>>>>>>>>>> majordomo info at
>>>>>>>>>>>>>>>> http://vger.kernel.org/majordomo-info.html
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> -- To unsubscribe from this list: send the line
>>>>>>>>>>>>> "unsubscribe netdev" in the body of a message to
>>>>>>>>>>>>> majordomo@vger.kernel.org More majordomo info at
>>>>>>>>>>>>> http://vger.kernel.org/majordomo-info.html
>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [RFC] net: stmmac: keep RXC running in LPI mode to avoid system overload
From: Giuseppe CAVALLARO @ 2013-10-09 15:28 UTC (permalink / raw)
To: Romain Baeriswyl; +Cc: David S. Miller, netdev, linux-kernel, Romain Baeriswyl
In-Reply-To: <1381244795-3922-1-git-send-email-romainba@abilis.com>
Hello Romain
On 10/8/2013 5:06 PM, Romain Baeriswyl wrote:
> In order to avoid system overload, the clock RXC from the Phy should not be
> stopped when in LPI mode.
>
> With the RTL8211E PHY which support EEE mode and with Apple Airport Extreme that
> supports it also, the kernel get frozen as soon as some Ethernet transfers are
hmm, I have a board with this transceiver so I could do some tests
this could take a while, unfortunately.
> on-going. System seems to be overloaded with too many interrupts. The 'top'
> command reports often around ~80% irq.
do you mean lpi mac interrupts?
>
> By letting the RXC clock running even in LPI mode as proposed below, the issue
> seems solved. Is it the right way to proceed?
For EEE capability, RX_CLK may be halted for this reason i used it as
default in the stmmac and never seen your issue.
>
> What is the power impact to not stop RXC in LPI mode?
I can point you to "22.2.2.8a Receive direction LPI transition"
in IEEE802-3az... where is it reported that the PHY halt the RX_CLK
in LPI mode.
May I suspect some issues on your HW? or disable it with ethtool
peppe
>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index e9eab29..d40d26b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -314,7 +314,8 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
> /* MAC core supports the EEE feature. */
> if (priv->dma_cap.eee) {
> /* Check if the PHY supports EEE */
> - if (phy_init_eee(priv->phydev, 1))
> + /* Keeps RXC running in LPI mode to avoid stability issue */
> + if (phy_init_eee(priv->phydev, 0))
> goto out;
>
> if (!priv->eee_active) {
> @@ -770,7 +771,8 @@ static void stmmac_adjust_link(struct net_device *dev)
> /* At this stage, it could be needed to setup the EEE or adjust some
> * MAC related HW registers.
> */
> - priv->eee_enabled = stmmac_eee_init(priv);
> + if (new_state)
> + priv->eee_enabled = stmmac_eee_init(priv);
this seems out of context and not necessary
>
> spin_unlock_irqrestore(&priv->lock, flags);
> }
>
^ permalink raw reply
* pull request: wireless 2013-10-09
From: John W. Linville @ 2013-10-09 15:28 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 16475 bytes --]
Dave,
Please pull this batch of fixes intended for 3.12...
Most of the bits are for iwlwifi -- Johannes says:
"I have a fix for WoWLAN/D3, a PCIe device fix, we're removing a
warning, there's a fix for RF-kill while scanning (which goes together
with a mac80211 fix) and last but not least we have many new PCI IDs."
Also for iwlwifi is a patch from Johannes to correct some merge damage
that crept into the tree before the last merge window.
On top of that, Felix Fietkau sends an ath9k patch to avoid a Tx
scheduling hang when changing channels to do a scan.
Please let me know if there are problems!
Thanks,
John
---
The following changes since commit 9684d7b0dab3cf3a897edd85dca501d413888d56:
Merge branch 'sfc-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc (2013-10-08 21:56:09 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
for you to fetch changes up to b26082b9945a9aca85d51be37824f852617c7129:
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2013-10-09 11:19:05 -0400)
----------------------------------------------------------------
Alexander Bondar (1):
iwlwifi: mvm: Disable uAPSD for D3 image
Emmanuel Grumbach (4):
iwlwifi: pcie: don't reset the TX queue counter
iwlwifi: don't WARN on host commands sent when firmware is dead
iwlwifi: pcie: add SKUs for 6000, 6005 and 6235 series
iwlwifi: mvm: call ieee80211_scan_completed when needed
Felix Fietkau (1):
ath9k: fix tx queue scheduling after channel changes
Johannes Berg (1):
iwlwifi: pcie: fix merge damage
John W. Linville (2):
Merge branch 'for-john' of git://git.kernel.org/.../iwlwifi/iwlwifi-fixes
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
Matti Gottlieb (1):
iwlwifi: pcie: add new SKUs for 7000 & 3160 NIC series
drivers/net/wireless/ath/ath9k/main.c | 23 ++++++++---------
drivers/net/wireless/iwlwifi/iwl-6000.c | 6 +++++
drivers/net/wireless/iwlwifi/iwl-config.h | 1 +
drivers/net/wireless/iwlwifi/iwl-trans.h | 6 +++--
drivers/net/wireless/iwlwifi/mvm/power.c | 5 +++-
drivers/net/wireless/iwlwifi/mvm/scan.c | 12 ++++++++-
drivers/net/wireless/iwlwifi/pcie/drv.c | 42 +++++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/pcie/trans.c | 8 +++---
drivers/net/wireless/iwlwifi/pcie/tx.c | 2 ++
9 files changed, 85 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e4f6590..709301f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -208,6 +208,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
unsigned long flags;
+ int i;
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
@@ -235,6 +236,15 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
work:
ath_restart_work(sc);
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+
+ spin_lock_bh(&sc->tx.txq[i].axq_lock);
+ ath_txq_schedule(sc, &sc->tx.txq[i]);
+ spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+ }
}
ieee80211_wake_queues(sc->hw);
@@ -539,21 +549,10 @@ chip_reset:
static int ath_reset(struct ath_softc *sc)
{
- int i, r;
+ int r;
ath9k_ps_wakeup(sc);
-
r = ath_reset_internal(sc, NULL);
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
-
- spin_lock_bh(&sc->tx.txq[i].axq_lock);
- ath_txq_schedule(sc, &sc->tx.txq[i]);
- spin_unlock_bh(&sc->tx.txq[i].axq_lock);
- }
-
ath9k_ps_restore(sc);
return r;
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 30d45e2..8ac305b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -240,6 +240,12 @@ const struct iwl_cfg iwl6035_2agn_cfg = {
.ht_params = &iwl6000_ht_params,
};
+const struct iwl_cfg iwl6035_2agn_sff_cfg = {
+ .name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN",
+ IWL_DEVICE_6035,
+ .ht_params = &iwl6000_ht_params,
+};
+
const struct iwl_cfg iwl1030_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
IWL_DEVICE_6030,
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index e4d370b..b03c25e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -280,6 +280,7 @@ extern const struct iwl_cfg iwl2000_2bgn_cfg;
extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
extern const struct iwl_cfg iwl2030_2bgn_cfg;
extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_sff_cfg;
extern const struct iwl_cfg iwl105_bgn_cfg;
extern const struct iwl_cfg iwl105_bgn_d_cfg;
extern const struct iwl_cfg iwl135_bgn_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index dd57a36..80b4750 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -601,8 +601,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
{
int ret;
- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
- "%s bad state = %d", __func__, trans->state);
+ if (trans->state != IWL_TRANS_FW_ALIVE) {
+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ return -EIO;
+ }
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 21407a3..d58e393 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -273,7 +273,10 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
if (!mvmvif->queue_params[ac].uapsd)
continue;
- cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+ if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
+ cmd->flags |=
+ cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+
cmd->uapsd_ac_flags |= BIT(ac);
/* QNDP TID - the highest TID with no admission control */
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 9a7ab84..621fb71 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -394,6 +394,11 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait,
return false;
}
+ /*
+ * If scan cannot be aborted, it means that we had a
+ * SCAN_COMPLETE_NOTIFICATION in the pipe and it called
+ * ieee80211_scan_completed already.
+ */
IWL_DEBUG_SCAN(mvm, "Scan cannot be aborted, exit now: %d\n",
*resp);
return true;
@@ -417,14 +422,19 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
SCAN_COMPLETE_NOTIFICATION };
int ret;
+ if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+ return;
+
iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
scan_abort_notif,
ARRAY_SIZE(scan_abort_notif),
iwl_mvm_scan_abort_notif, NULL);
- ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
+ ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD,
+ CMD_SYNC | CMD_SEND_IN_RFKILL, 0, NULL);
if (ret) {
IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
+ /* mac80211's state will be cleaned in the fw_restart flow */
goto out_remove_notif;
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index dc02cb9..26108a1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -139,13 +139,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
/* 6x00 Series */
{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)},
{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)},
{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)},
{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
@@ -153,12 +156,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
{IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
@@ -240,8 +247,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
/* 6x35 Series */
{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
@@ -260,54 +270,86 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
#if IS_ENABLED(CONFIG_IWLMVM)
/* 7000 Series */
{IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7260_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)},
{IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)},
/* 3160 Series */
{IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0072, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0172, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)},
{IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x0272, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0472, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x0370, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8072, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8172, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
{IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
{IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
#endif /* CONFIG_IWLMVM */
{0}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index bad95d2..c3f904d 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1401,6 +1401,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
spin_lock_init(&trans_pcie->reg_lock);
init_waitqueue_head(&trans_pcie->ucode_write_waitq);
+ err = pci_enable_device(pdev);
+ if (err)
+ goto out_no_pci;
+
if (!cfg->base_params->pcie_l1_allowed) {
/*
* W/A - seems to solve weird behavior. We need to remove this
@@ -1412,10 +1416,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
PCIE_LINK_STATE_CLKPM);
}
- err = pci_enable_device(pdev);
- if (err)
- goto out_no_pci;
-
pci_set_master(pdev);
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index f45eb29..1424335 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1102,6 +1102,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
* non-AGG queue.
*/
iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+
+ ssn = trans_pcie->txq[txq_id].q.read_ptr;
}
/* Place first TFD at index corresponding to start sequence number.
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [PATCH RFC 00/77] Re-design MSI/MSI-X interrupts enablement pattern
From: Tejun Heo @ 2013-10-09 15:41 UTC (permalink / raw)
To: Alexander Gordeev
Cc: Benjamin Herrenschmidt, Ben Hutchings, linux-kernel,
Bjorn Helgaas, Ralf Baechle, Michael Ellerman, Martin Schwidefsky,
Ingo Molnar, Dan Williams, Andy King, Jon Mason, Matt Porter,
linux-pci, linux-mips, linuxppc-dev, linux390, linux-s390, x86,
linux-ide, iss_storagedev, linux-nvme, linux-rdma, netdev,
e1000-devel, linux-driver, Solarflare linux maintainers, "VMw
In-Reply-To: <20131008122215.GA14389@dhcp-26-207.brq.redhat.com>
Hello,
On Tue, Oct 08, 2013 at 02:22:16PM +0200, Alexander Gordeev wrote:
> If we talk about pSeries quota, then the current pSeries pci_enable_msix()
> implementation is racy internally and could fail if the quota went down
> *while* pci_enable_msix() is executing. In this case the loop will have to
> exit rather than retry with a lower number (what number?).
Ah, okay, so that one is already broken.
> In this regard the new scheme does not bring anything new and relies on
> the fact this race does not hit and therefore does not worry.
>
> If we talk about quota as it has to be, then yes - the loop scheme seems
> more preferable.
>
> Overall, looks like we just need to fix the pSeries implementation,
> if the guys want it, he-he :)
If we can't figure out a better interface for the retry case, I think
what can really help is having a simple interface for the simpler
cases.
> > The problem case is where multiple msi(x) allocation fails completely
> > because the global limit went down before inquiry and allocation. In
> > the loop based interface, it'd retry with the lower number.
>
> I am probably missing something here. If the global limit went down before
> inquiry then the inquiry will get what is available and try to allocate with
> than number.
Oh, I should have written between inquiry and allocation. Sorry.
Thanks.
--
tejun
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox