* Re: [PATCH] can: flexcan: use be32_to_cpup to handle the value of dt entry
From: Shawn Guo @ 2012-06-27 11:26 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: davem, netdev, linux-can, Hui Wang
In-Reply-To: <1340789236-28266-2-git-send-email-mkl@pengutronix.de>
On 27 June 2012 17:27, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> From: Hui Wang <jason77.wang@gmail.com>
>
> The freescale arm i.MX series platform can support this driver, and
> usually the arm cpu works in the little endian mode by default, while
> device tree entry value is stored in big endian format, we should use
> be32_to_cpup() to handle them, after modification, it can work well
> both on the le cpu and be cpu.
>
I'm wondering if you want to just use of_property_read_u32() to make
it a little bit easier.
Regards,
Shawn
> Cc: stable <stable@vger.kernel.org> # v3.2+
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Signed-off-by: Hui Wang <jason77.wang@gmail.com>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
> drivers/net/can/flexcan.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index 38c0690..81d4741 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -939,12 +939,12 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> return PTR_ERR(pinctrl);
>
> if (pdev->dev.of_node) {
> - const u32 *clock_freq_p;
> + const __be32 *clock_freq_p;
>
> clock_freq_p = of_get_property(pdev->dev.of_node,
> "clock-frequency", NULL);
> if (clock_freq_p)
> - clock_freq = *clock_freq_p;
> + clock_freq = be32_to_cpup(clock_freq_p);
> }
>
> if (!clock_freq) {
> --
> 1.7.10
>
^ permalink raw reply
* Re: [PATCH] can: flexcan: use be32_to_cpup to handle the value of dt entry
From: Marc Kleine-Budde @ 2012-06-27 11:34 UTC (permalink / raw)
To: Shawn Guo; +Cc: davem, netdev, linux-can, Hui Wang
In-Reply-To: <CAAQ0ZWT3ovG7eKZZuoSZkx4FGd+W9XvnTk8R1yuD02u4wqGNHQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 927 bytes --]
On 06/27/2012 01:26 PM, Shawn Guo wrote:
> On 27 June 2012 17:27, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>> From: Hui Wang <jason77.wang@gmail.com>
>>
>> The freescale arm i.MX series platform can support this driver, and
>> usually the arm cpu works in the little endian mode by default, while
>> device tree entry value is stored in big endian format, we should use
>> be32_to_cpup() to handle them, after modification, it can work well
>> both on the le cpu and be cpu.
>>
> I'm wondering if you want to just use of_property_read_u32() to make
> it a little bit easier.
Even better. Hui can you send a updated patch.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* [net-next patch] bnx2x: Define bnx2x_tests_str_arr as const
From: Merav Sicron @ 2012-06-27 11:52 UTC (permalink / raw)
To: davem, netdev, eilong; +Cc: Merav Sicron
This patch changes the definition of bnx2x_tests_str_arr from static char to
static const char.
Reported-by: Joe Perches <joe@perches.com>
Signed-off-by: Merav Sicron <meravs@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
Hi Dave,
Please consider applying this patch to net-next.
Thanks,
Merav
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index bff3129..81cadb6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1600,7 +1600,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
return 0;
}
-static char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
+static const char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
"register_test (offline) ",
"memory_test (offline) ",
"int_loopback_test (offline)",
--
1.7.10
^ permalink raw reply related
* RE: [net-next patch] bnx2x: Define bnx2x_tests_str_arr as const
From: David Laight @ 2012-06-27 11:59 UTC (permalink / raw)
To: Merav Sicron, davem, netdev, eilong
In-Reply-To: <1340797976-13827-1-git-send-email-meravs@broadcom.com>
> -static char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
> +static const char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
> "register_test (offline) ",
> "memory_test (offline) ",
> "int_loopback_test (offline)",
You are still missing a 'const'.
You probably want:
static const char *const bnx2x_tests_str_arr[] ...
However if you are going to pad the strings to [28]
you might as well remove the layer of indirection - ie:
static const char bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF][28] = { ...
}
Or pad to 32 chars to (probably) remove some code bytes.
David
^ permalink raw reply
* [PATCH v2] l2tp: use per-cpu variables for u64_stats updates
From: Tom Parkin @ 2012-06-27 12:00 UTC (permalink / raw)
To: netdev; +Cc: David.Laight, Tom Parkin, James Chapman
This patch fixes a race condition in l2tp when updating tunnel and
session statistics. Previously it was possible for multiple threads
to concurrently call u64_stats_update*(), which lead to statistics
readers blocking forever.
This race was discovered on an AMD64 SMP machine running a 32bit
kernel. Running "ip l2tp" while sending data over an Ethernet
pseudowire resulted in an occasional soft lockup in
u64_stats_fetch_begin() called from l2tp_nl_session_send().
For safe lockless update of l2tp stats, data is now stored in per-cpu
variables. These per-cpu datasets are then summed at read time via.
an extra helper function l2tp_stats_copy() which has been added to
l2tp_core.c.
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: James Chapman <jchapman@katalix.com>
---
net/l2tp/l2tp_core.c | 286 ++++++++++++++++++++++++++++-------------------
net/l2tp/l2tp_core.h | 44 ++++++--
net/l2tp/l2tp_debugfs.c | 42 ++++---
net/l2tp/l2tp_netlink.c | 64 ++++-------
net/l2tp/l2tp_ppp.c | 75 ++++++++-----
5 files changed, 301 insertions(+), 210 deletions(-)
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 32b2155..ab2ffc0 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -320,6 +320,43 @@ struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth)
}
EXPORT_SYMBOL_GPL(l2tp_tunnel_find_nth);
+/*
+ * Sum tunnel/session statistics across all CPUs
+ */
+int l2tp_stats_copy(struct l2tp_stats *cpustats, struct l2tp_stats *dest)
+{
+ int i;
+ unsigned int start;
+
+ if (!cpustats || !dest)
+ return 1;
+
+ memset(dest, 0, sizeof(struct l2tp_stats));
+
+ for_each_possible_cpu(i) {
+ struct l2tp_stats *stats = per_cpu_ptr(cpustats, i);
+
+ do {
+ start = u64_stats_fetch_begin(&stats->tx.syncp);
+ dest->tx.packets += stats->tx.packets;
+ dest->tx.bytes += stats->tx.bytes;
+ dest->tx.errors += stats->tx.errors;
+ } while (u64_stats_fetch_retry(&stats->tx.syncp, start));
+
+ do {
+ start = u64_stats_fetch_begin(&stats->rx.syncp);
+ dest->rx.packets += stats->rx.packets;
+ dest->rx.bytes += stats->rx.bytes;
+ dest->rx.errors += stats->rx.errors;
+ dest->rx.seq_discards += stats->rx.seq_discards;
+ dest->rx.oos_packets += stats->rx.oos_packets;
+ } while (u64_stats_fetch_retry(&stats->rx.syncp, start));
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(l2tp_stats_copy);
+
/*****************************************************************************
* Receive data handling
*****************************************************************************/
@@ -335,7 +372,6 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk
struct l2tp_stats *sstats;
spin_lock_bh(&session->reorder_q.lock);
- sstats = &session->stats;
skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
if (L2TP_SKB_CB(skbp)->ns > ns) {
__skb_queue_before(&session->reorder_q, skbp, skb);
@@ -343,9 +379,10 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk
"%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
session->name, ns, L2TP_SKB_CB(skbp)->ns,
skb_queue_len(&session->reorder_q));
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_oos_packets++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.oos_packets++;
+ u64_stats_update_end(&sstats->rx.syncp);
goto out;
}
}
@@ -369,16 +406,17 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *
*/
skb_orphan(skb);
- tstats = &tunnel->stats;
- u64_stats_update_begin(&tstats->syncp);
- sstats = &session->stats;
- u64_stats_update_begin(&sstats->syncp);
- tstats->rx_packets++;
- tstats->rx_bytes += length;
- sstats->rx_packets++;
- sstats->rx_bytes += length;
- u64_stats_update_end(&tstats->syncp);
- u64_stats_update_end(&sstats->syncp);
+ tstats = this_cpu_ptr(tunnel->cpustats);
+ u64_stats_update_begin(&tstats->rx.syncp);
+ tstats->rx.packets++;
+ tstats->rx.bytes += length;
+ u64_stats_update_end(&tstats->rx.syncp);
+
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.packets++;
+ sstats->rx.bytes += length;
+ u64_stats_update_end(&sstats->rx.syncp);
if (L2TP_SKB_CB(skb)->has_seq) {
/* Bump our Nr */
@@ -417,13 +455,13 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)
*/
start:
spin_lock_bh(&session->reorder_q.lock);
- sstats = &session->stats;
skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) {
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_seq_discards++;
- sstats->rx_errors++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.seq_discards++;
+ sstats->rx.errors++;
+ u64_stats_update_end(&sstats->rx.syncp);
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n",
session->name, L2TP_SKB_CB(skb)->ns,
@@ -582,7 +620,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
struct l2tp_tunnel *tunnel = session->tunnel;
int offset;
u32 ns, nr;
- struct l2tp_stats *sstats = &session->stats;
+ struct l2tp_stats *sstats;
/* The ref count is increased since we now hold a pointer to
* the session. Take care to decrement the refcnt when exiting
@@ -599,9 +637,10 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
"%s: cookie mismatch (%u/%u). Discarding.\n",
tunnel->name, tunnel->tunnel_id,
session->session_id);
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_cookie_discards++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.cookie_discards++;
+ u64_stats_update_end(&sstats->rx.syncp);
goto discard;
}
ptr += session->peer_cookie_len;
@@ -670,9 +709,10 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
l2tp_warn(session, L2TP_MSG_SEQ,
"%s: recv data has no seq numbers when required. Discarding.\n",
session->name);
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_seq_discards++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.seq_discards++;
+ u64_stats_update_end(&sstats->rx.syncp);
goto discard;
}
@@ -691,9 +731,10 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
l2tp_warn(session, L2TP_MSG_SEQ,
"%s: recv data has no seq numbers when required. Discarding.\n",
session->name);
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_seq_discards++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.seq_discards++;
+ u64_stats_update_end(&sstats->rx.syncp);
goto discard;
}
}
@@ -747,9 +788,10 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
* packets
*/
if (L2TP_SKB_CB(skb)->ns != session->nr) {
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_seq_discards++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.seq_discards++;
+ u64_stats_update_end(&sstats->rx.syncp);
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n",
session->name, L2TP_SKB_CB(skb)->ns,
@@ -775,9 +817,10 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
return;
discard:
- u64_stats_update_begin(&sstats->syncp);
- sstats->rx_errors++;
- u64_stats_update_end(&sstats->syncp);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.errors++;
+ u64_stats_update_end(&sstats->rx.syncp);
kfree_skb(skb);
if (session->deref)
@@ -891,10 +934,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
discard_bad_csum:
LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0);
- tstats = &tunnel->stats;
- u64_stats_update_begin(&tstats->syncp);
- tstats->rx_errors++;
- u64_stats_update_end(&tstats->syncp);
+ tstats = this_cpu_ptr(tunnel->cpustats);
+ u64_stats_update_begin(&tstats->rx.syncp);
+ tstats->rx.errors++;
+ u64_stats_update_end(&tstats->rx.syncp);
kfree_skb(skb);
return 0;
@@ -1050,21 +1093,21 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
error = ip_queue_xmit(skb, fl);
/* Update stats */
- tstats = &tunnel->stats;
- u64_stats_update_begin(&tstats->syncp);
- sstats = &session->stats;
- u64_stats_update_begin(&sstats->syncp);
+ tstats = this_cpu_ptr(tunnel->cpustats);
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&tstats->tx.syncp);
+ u64_stats_update_begin(&sstats->tx.syncp);
if (error >= 0) {
- tstats->tx_packets++;
- tstats->tx_bytes += len;
- sstats->tx_packets++;
- sstats->tx_bytes += len;
+ tstats->tx.packets++;
+ tstats->tx.bytes += len;
+ sstats->tx.packets++;
+ sstats->tx.bytes += len;
} else {
- tstats->tx_errors++;
- sstats->tx_errors++;
+ tstats->tx.errors++;
+ sstats->tx.errors++;
}
- u64_stats_update_end(&tstats->syncp);
- u64_stats_update_end(&sstats->syncp);
+ u64_stats_update_end(&tstats->tx.syncp);
+ u64_stats_update_end(&sstats->tx.syncp);
return 0;
}
@@ -1256,6 +1299,8 @@ static void l2tp_tunnel_destruct(struct sock *sk)
sk->sk_destruct = tunnel->old_sk_destruct;
sk->sk_user_data = NULL;
+ free_percpu(tunnel->cpustats);
+
/* Call the original destructor */
if (sk->sk_destruct)
(*sk->sk_destruct)(sk);
@@ -1567,6 +1612,13 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
goto err;
}
+ tunnel->cpustats = alloc_percpu(struct l2tp_stats);
+ if (tunnel->cpustats == NULL) {
+ kfree(tunnel);
+ err = -ENOMEM;
+ goto err;
+ }
+
tunnel->version = version;
tunnel->tunnel_id = tunnel_id;
tunnel->peer_tunnel_id = peer_tunnel_id;
@@ -1692,6 +1744,8 @@ void l2tp_session_free(struct l2tp_session *session)
sock_put(tunnel->sock);
+ free_percpu(session->cpustats);
+
/* This will delete the tunnel context if this
* is the last session on the tunnel.
*/
@@ -1742,80 +1796,88 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
struct l2tp_session *session;
session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
- if (session != NULL) {
- session->magic = L2TP_SESSION_MAGIC;
- session->tunnel = tunnel;
+ if (session == NULL)
+ goto err;
- session->session_id = session_id;
- session->peer_session_id = peer_session_id;
- session->nr = 0;
+ session->cpustats = alloc_percpu(struct l2tp_stats);
+ if (session->cpustats == NULL) {
+ kfree(session);
+ goto err;
+ }
- sprintf(&session->name[0], "sess %u/%u",
- tunnel->tunnel_id, session->session_id);
+ session->magic = L2TP_SESSION_MAGIC;
+ session->tunnel = tunnel;
- skb_queue_head_init(&session->reorder_q);
-
- INIT_HLIST_NODE(&session->hlist);
- INIT_HLIST_NODE(&session->global_hlist);
-
- /* Inherit debug options from tunnel */
- session->debug = tunnel->debug;
-
- if (cfg) {
- session->pwtype = cfg->pw_type;
- session->debug = cfg->debug;
- session->mtu = cfg->mtu;
- session->mru = cfg->mru;
- session->send_seq = cfg->send_seq;
- session->recv_seq = cfg->recv_seq;
- session->lns_mode = cfg->lns_mode;
- session->reorder_timeout = cfg->reorder_timeout;
- session->offset = cfg->offset;
- session->l2specific_type = cfg->l2specific_type;
- session->l2specific_len = cfg->l2specific_len;
- session->cookie_len = cfg->cookie_len;
- memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
- session->peer_cookie_len = cfg->peer_cookie_len;
- memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
- }
+ session->session_id = session_id;
+ session->peer_session_id = peer_session_id;
+ session->nr = 0;
- if (tunnel->version == L2TP_HDR_VER_2)
- session->build_header = l2tp_build_l2tpv2_header;
- else
- session->build_header = l2tp_build_l2tpv3_header;
+ sprintf(&session->name[0], "sess %u/%u",
+ tunnel->tunnel_id, session->session_id);
- l2tp_session_set_header_len(session, tunnel->version);
+ skb_queue_head_init(&session->reorder_q);
+
+ INIT_HLIST_NODE(&session->hlist);
+ INIT_HLIST_NODE(&session->global_hlist);
+
+ /* Inherit debug options from tunnel */
+ session->debug = tunnel->debug;
+
+ if (cfg) {
+ session->pwtype = cfg->pw_type;
+ session->debug = cfg->debug;
+ session->mtu = cfg->mtu;
+ session->mru = cfg->mru;
+ session->send_seq = cfg->send_seq;
+ session->recv_seq = cfg->recv_seq;
+ session->lns_mode = cfg->lns_mode;
+ session->reorder_timeout = cfg->reorder_timeout;
+ session->offset = cfg->offset;
+ session->l2specific_type = cfg->l2specific_type;
+ session->l2specific_len = cfg->l2specific_len;
+ session->cookie_len = cfg->cookie_len;
+ memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
+ session->peer_cookie_len = cfg->peer_cookie_len;
+ memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
+ }
- /* Bump the reference count. The session context is deleted
- * only when this drops to zero.
- */
- l2tp_session_inc_refcount(session);
- l2tp_tunnel_inc_refcount(tunnel);
+ if (tunnel->version == L2TP_HDR_VER_2)
+ session->build_header = l2tp_build_l2tpv2_header;
+ else
+ session->build_header = l2tp_build_l2tpv3_header;
- /* Ensure tunnel socket isn't deleted */
- sock_hold(tunnel->sock);
+ l2tp_session_set_header_len(session, tunnel->version);
- /* Add session to the tunnel's hash list */
- write_lock_bh(&tunnel->hlist_lock);
- hlist_add_head(&session->hlist,
- l2tp_session_id_hash(tunnel, session_id));
- write_unlock_bh(&tunnel->hlist_lock);
+ /* Bump the reference count. The session context is deleted
+ * only when this drops to zero.
+ */
+ l2tp_session_inc_refcount(session);
+ l2tp_tunnel_inc_refcount(tunnel);
- /* And to the global session list if L2TPv3 */
- if (tunnel->version != L2TP_HDR_VER_2) {
- struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
+ /* Ensure tunnel socket isn't deleted */
+ sock_hold(tunnel->sock);
- spin_lock_bh(&pn->l2tp_session_hlist_lock);
- hlist_add_head_rcu(&session->global_hlist,
- l2tp_session_id_hash_2(pn, session_id));
- spin_unlock_bh(&pn->l2tp_session_hlist_lock);
- }
+ /* Add session to the tunnel's hash list */
+ write_lock_bh(&tunnel->hlist_lock);
+ hlist_add_head(&session->hlist,
+ l2tp_session_id_hash(tunnel, session_id));
+ write_unlock_bh(&tunnel->hlist_lock);
- /* Ignore management session in session count value */
- if (session->session_id != 0)
- atomic_inc(&l2tp_session_count);
+ /* And to the global session list if L2TPv3 */
+ if (tunnel->version != L2TP_HDR_VER_2) {
+ struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
+
+ spin_lock_bh(&pn->l2tp_session_hlist_lock);
+ hlist_add_head_rcu(&session->global_hlist,
+ l2tp_session_id_hash_2(pn, session_id));
+ spin_unlock_bh(&pn->l2tp_session_hlist_lock);
}
+ /* Ignore management session in session count value */
+ if (session->session_id != 0)
+ atomic_inc(&l2tp_session_count);
+
+err:
return session;
}
EXPORT_SYMBOL_GPL(l2tp_session_create);
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index a38ec6c..29bb34c 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -35,19 +35,34 @@ enum {
struct sk_buff;
-struct l2tp_stats {
- u64 tx_packets;
- u64 tx_bytes;
- u64 tx_errors;
- u64 rx_packets;
- u64 rx_bytes;
- u64 rx_seq_discards;
- u64 rx_oos_packets;
- u64 rx_errors;
- u64 rx_cookie_discards;
+/* Stats are synchronised via a synchronisation point for safe
+ * reader/writer access on 64 and 32 bit kernels. Stats are
+ * stored on a per-cpu basis for safe lockless updating, and
+ * summed at read time. This allows the statistics update in
+ * the data path to be fast at some small cost when reading.
+ */
+struct l2tp_rx_stats {
+ u64 packets;
+ u64 bytes;
+ u64 errors;
+ u64 seq_discards;
+ u64 cookie_discards;
+ u64 oos_packets;
+ struct u64_stats_sync syncp;
+};
+
+struct l2tp_tx_stats {
+ u64 packets;
+ u64 bytes;
+ u64 errors;
struct u64_stats_sync syncp;
};
+struct l2tp_stats {
+ struct l2tp_rx_stats rx;
+ struct l2tp_tx_stats tx;
+};
+
struct l2tp_tunnel;
/* Describes a session. Contains information to determine incoming
@@ -127,7 +142,9 @@ struct l2tp_session {
int mtu;
int mru;
enum l2tp_pwtype pwtype;
- struct l2tp_stats stats;
+
+ struct l2tp_stats *cpustats; /* per-cpu counters */
+
struct hlist_node global_hlist; /* Global hash list node */
int (*build_header)(struct l2tp_session *session, void *buf);
@@ -175,7 +192,8 @@ struct l2tp_tunnel {
int debug; /* bitmask of debug message
* categories */
enum l2tp_encap_type encap;
- struct l2tp_stats stats;
+
+ struct l2tp_stats *cpustats; /* per-cpu counters */
struct list_head list; /* Keep a list of all tunnels */
struct net *l2tp_net; /* the net we belong to */
@@ -246,6 +264,8 @@ extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int
extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops);
extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
+extern int l2tp_stats_copy(struct l2tp_stats *cpustats, struct l2tp_stats *dest);
+
/* Session reference counts. Incremented when code obtains a reference
* to a session.
*/
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index c3813bc..5ec4732 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -106,6 +106,7 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
int hash;
struct hlist_node *walk;
struct hlist_node *tmp;
+ struct l2tp_stats stats;
read_lock_bh(&tunnel->hlist_lock);
for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
@@ -146,14 +147,18 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0,
atomic_read(&tunnel->ref_count));
- seq_printf(m, " %08x rx %llu/%llu/%llu rx %llu/%llu/%llu\n",
- tunnel->debug,
- (unsigned long long)tunnel->stats.tx_packets,
- (unsigned long long)tunnel->stats.tx_bytes,
- (unsigned long long)tunnel->stats.tx_errors,
- (unsigned long long)tunnel->stats.rx_packets,
- (unsigned long long)tunnel->stats.rx_bytes,
- (unsigned long long)tunnel->stats.rx_errors);
+ if (!l2tp_stats_copy(tunnel->cpustats, &stats)) {
+ seq_printf(m, " %08x tx %llu/%llu/%llu rx %llu/%llu/%llu\n",
+ tunnel->debug,
+ (unsigned long long)stats.tx.packets,
+ (unsigned long long)stats.tx.bytes,
+ (unsigned long long)stats.tx.errors,
+ (unsigned long long)stats.rx.packets,
+ (unsigned long long)stats.rx.bytes,
+ (unsigned long long)stats.rx.errors);
+ } else {
+ seq_printf(m, " stats lookup failure\n");
+ }
if (tunnel->show != NULL)
tunnel->show(m, tunnel);
@@ -162,6 +167,7 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
{
struct l2tp_session *session = v;
+ struct l2tp_stats stats;
seq_printf(m, " SESSION %u, peer %u, %s\n", session->session_id,
session->peer_session_id,
@@ -203,14 +209,18 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
seq_printf(m, "\n");
}
- seq_printf(m, " %hu/%hu tx %llu/%llu/%llu rx %llu/%llu/%llu\n",
- session->nr, session->ns,
- (unsigned long long)session->stats.tx_packets,
- (unsigned long long)session->stats.tx_bytes,
- (unsigned long long)session->stats.tx_errors,
- (unsigned long long)session->stats.rx_packets,
- (unsigned long long)session->stats.rx_bytes,
- (unsigned long long)session->stats.rx_errors);
+ if (!l2tp_stats_copy(session->cpustats, &stats)) {
+ seq_printf(m, " %hu/%hu tx %llu/%llu/%llu rx %llu/%llu/%llu\n",
+ session->nr, session->ns,
+ (unsigned long long)stats.tx.packets,
+ (unsigned long long)stats.tx.bytes,
+ (unsigned long long)stats.tx.errors,
+ (unsigned long long)stats.rx.packets,
+ (unsigned long long)stats.rx.bytes,
+ (unsigned long long)stats.rx.errors);
+ } else {
+ seq_printf(m, " stats lookup failure\n");
+ }
if (session->show != NULL)
session->show(m, session);
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index ddc553e..09fd33d 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -246,7 +246,6 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
struct ipv6_pinfo *np = NULL;
#endif
struct l2tp_stats stats;
- unsigned int start;
hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags,
L2TP_CMD_TUNNEL_GET);
@@ -264,28 +263,19 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
if (nest == NULL)
goto nla_put_failure;
- do {
- start = u64_stats_fetch_begin(&tunnel->stats.syncp);
- stats.tx_packets = tunnel->stats.tx_packets;
- stats.tx_bytes = tunnel->stats.tx_bytes;
- stats.tx_errors = tunnel->stats.tx_errors;
- stats.rx_packets = tunnel->stats.rx_packets;
- stats.rx_bytes = tunnel->stats.rx_bytes;
- stats.rx_errors = tunnel->stats.rx_errors;
- stats.rx_seq_discards = tunnel->stats.rx_seq_discards;
- stats.rx_oos_packets = tunnel->stats.rx_oos_packets;
- } while (u64_stats_fetch_retry(&tunnel->stats.syncp, start));
-
- if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
- nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
- nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
- nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
- nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
+ if (0 != l2tp_stats_copy(tunnel->cpustats, &stats))
+ goto nla_put_failure;
+
+ if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx.packets) ||
+ nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx.bytes) ||
+ nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx.errors) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx.packets) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx.bytes) ||
nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
- stats.rx_seq_discards) ||
+ stats.rx.seq_discards) ||
nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
- stats.rx_oos_packets) ||
- nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
+ stats.rx.oos_packets) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx.errors))
goto nla_put_failure;
nla_nest_end(skb, nest);
@@ -612,7 +602,6 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags
struct l2tp_tunnel *tunnel = session->tunnel;
struct sock *sk = NULL;
struct l2tp_stats stats;
- unsigned int start;
sk = tunnel->sock;
@@ -655,28 +644,19 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags
if (nest == NULL)
goto nla_put_failure;
- do {
- start = u64_stats_fetch_begin(&session->stats.syncp);
- stats.tx_packets = session->stats.tx_packets;
- stats.tx_bytes = session->stats.tx_bytes;
- stats.tx_errors = session->stats.tx_errors;
- stats.rx_packets = session->stats.rx_packets;
- stats.rx_bytes = session->stats.rx_bytes;
- stats.rx_errors = session->stats.rx_errors;
- stats.rx_seq_discards = session->stats.rx_seq_discards;
- stats.rx_oos_packets = session->stats.rx_oos_packets;
- } while (u64_stats_fetch_retry(&session->stats.syncp, start));
-
- if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
- nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
- nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
- nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
- nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
+ if (0 != l2tp_stats_copy(session->cpustats, &stats))
+ goto nla_put_failure;
+
+ if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx.packets) ||
+ nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx.bytes) ||
+ nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx.errors) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx.packets) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx.bytes) ||
nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
- stats.rx_seq_discards) ||
+ stats.rx.seq_discards) ||
nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
- stats.rx_oos_packets) ||
- nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
+ stats.rx.oos_packets) ||
+ nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx.errors))
goto nla_put_failure;
nla_nest_end(skb, nest);
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 286366e..054c069 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -222,6 +222,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
{
struct pppol2tp_session *ps = l2tp_session_priv(session);
struct sock *sk = NULL;
+ struct l2tp_stats *sstats = NULL;
/* If the socket is bound, send it in to PPP's input queue. Otherwise
* queue it on the session socket.
@@ -259,7 +260,10 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
session->name);
/* Not bound. Nothing we can do, so discard. */
- session->stats.rx_errors++;
+ sstats = this_cpu_ptr(session->cpustats);
+ u64_stats_update_begin(&sstats->rx.syncp);
+ sstats->rx.errors++;
+ u64_stats_update_end(&sstats->rx.syncp);
kfree_skb(skb);
}
@@ -1028,16 +1032,21 @@ end:
****************************************************************************/
static void pppol2tp_copy_stats(struct pppol2tp_ioc_stats *dest,
- struct l2tp_stats *stats)
+ struct l2tp_stats *cpustats)
{
- dest->tx_packets = stats->tx_packets;
- dest->tx_bytes = stats->tx_bytes;
- dest->tx_errors = stats->tx_errors;
- dest->rx_packets = stats->rx_packets;
- dest->rx_bytes = stats->rx_bytes;
- dest->rx_seq_discards = stats->rx_seq_discards;
- dest->rx_oos_packets = stats->rx_oos_packets;
- dest->rx_errors = stats->rx_errors;
+ struct l2tp_stats tmp;
+
+ if (0 != l2tp_stats_copy(cpustats, &tmp))
+ return;
+
+ dest->tx_packets = tmp.tx.packets;
+ dest->tx_bytes = tmp.tx.bytes;
+ dest->tx_errors = tmp.tx.errors;
+ dest->rx_packets = tmp.rx.packets;
+ dest->rx_bytes = tmp.rx.bytes;
+ dest->rx_seq_discards = tmp.rx.seq_discards;
+ dest->rx_oos_packets = tmp.rx.oos_packets;
+ dest->rx_errors = tmp.rx.errors;
}
/* Session ioctl helper.
@@ -1151,7 +1160,7 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session,
memset(&stats, 0, sizeof(stats));
stats.tunnel_id = tunnel->tunnel_id;
stats.session_id = session->session_id;
- pppol2tp_copy_stats(&stats, &session->stats);
+ pppol2tp_copy_stats(&stats, session->cpustats);
if (copy_to_user((void __user *) arg, &stats,
sizeof(stats)))
break;
@@ -1214,7 +1223,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel,
#ifdef CONFIG_XFRM
stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0;
#endif
- pppol2tp_copy_stats(&stats, &tunnel->stats);
+ pppol2tp_copy_stats(&stats, tunnel->cpustats);
if (copy_to_user((void __user *) arg, &stats, sizeof(stats))) {
err = -EFAULT;
break;
@@ -1666,19 +1675,24 @@ static void pppol2tp_seq_stop(struct seq_file *p, void *v)
static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
{
struct l2tp_tunnel *tunnel = v;
+ struct l2tp_stats tmp;
seq_printf(m, "\nTUNNEL '%s', %c %d\n",
tunnel->name,
(tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N',
atomic_read(&tunnel->ref_count) - 1);
- seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
- tunnel->debug,
- (unsigned long long)tunnel->stats.tx_packets,
- (unsigned long long)tunnel->stats.tx_bytes,
- (unsigned long long)tunnel->stats.tx_errors,
- (unsigned long long)tunnel->stats.rx_packets,
- (unsigned long long)tunnel->stats.rx_bytes,
- (unsigned long long)tunnel->stats.rx_errors);
+ if (!l2tp_stats_copy(tunnel->cpustats, &tmp)) {
+ seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
+ tunnel->debug,
+ (unsigned long long)tmp.tx.packets,
+ (unsigned long long)tmp.tx.bytes,
+ (unsigned long long)tmp.tx.errors,
+ (unsigned long long)tmp.rx.packets,
+ (unsigned long long)tmp.rx.bytes,
+ (unsigned long long)tmp.rx.errors);
+ } else {
+ seq_printf(m, " stats lookup failure\n");
+ }
}
static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
@@ -1687,6 +1701,7 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
struct l2tp_tunnel *tunnel = session->tunnel;
struct pppol2tp_session *ps = l2tp_session_priv(session);
struct pppox_sock *po = pppox_sk(ps->sock);
+ struct l2tp_stats tmp;
u32 ip = 0;
u16 port = 0;
@@ -1713,14 +1728,18 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
session->lns_mode ? "LNS" : "LAC",
session->debug,
jiffies_to_msecs(session->reorder_timeout));
- seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
- session->nr, session->ns,
- (unsigned long long)session->stats.tx_packets,
- (unsigned long long)session->stats.tx_bytes,
- (unsigned long long)session->stats.tx_errors,
- (unsigned long long)session->stats.rx_packets,
- (unsigned long long)session->stats.rx_bytes,
- (unsigned long long)session->stats.rx_errors);
+ if (!l2tp_stats_copy(session->cpustats, &tmp)) {
+ seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
+ session->nr, session->ns,
+ (unsigned long long)tmp.tx.packets,
+ (unsigned long long)tmp.tx.bytes,
+ (unsigned long long)tmp.tx.errors,
+ (unsigned long long)tmp.rx.packets,
+ (unsigned long long)tmp.rx.bytes,
+ (unsigned long long)tmp.rx.errors);
+ } else {
+ seq_printf(m, " stats lookup failure\n");
+ }
if (po)
seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan));
--
1.7.9.5
^ permalink raw reply related
* Re: BUG: No init found on NFSROOT
From: Fengguang Wu @ 2012-06-27 12:23 UTC (permalink / raw)
To: Christoph Lameter
Cc: Trond Myklebust, J. Bruce Fields, linux-nfs, LKML, netdev,
Pekka Enberg, Linux Memory Management List
In-Reply-To: <20120626172918.GA16446@localhost>
Hi Christoph,
It's a surprise that it bisects down to this commit. I confirmed
that it boots reliably if reverting this commit on top of linux-next.
8c138bc00925521c4e764269db3a903bd2a51592 is the first bad commit
commit 8c138bc00925521c4e764269db3a903bd2a51592
Author: Christoph Lameter <cl@linux.com>
Date: Wed Jun 13 10:24:58 2012 -0500
slab: Get rid of obj_size macro
The size of the slab object is frequently needed. Since we now
have a size field directly in the kmem_cache structure there is no
need anymore of the obj_size macro/function.
Signed-off-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
:040000 040000 e0418be654b66b2364add59bb469024fd6958791 f6be0da4d4740844ab8a4c561dbe3815a3f9b8b4 M mm
bisect run success
> > [ 133.909702] =========================
> > [ 133.910694] [ BUG: held lock freed! ]
> > [ 133.911700] 3.5.0-rc4+ #5 Not tainted
> > [ 133.912672] -------------------------
> > [ 133.912969] swapper/0/0 is freeing memory ffff88001233ce08-ffff88001233de07, with a lock still held there!
> > [ 133.912969] (slock-AF_INET-RPC/1){+.-...}, at: [<ffffffff82ae84ee>] tcp_v4_rcv+0x28b/0x6fc
> > [ 133.912969] 3 locks held by swapper/0/0:
> > [ 133.912969] #0: (rcu_read_lock){.+.+..}, at: [<ffffffff82a1ea8a>] rcu_lock_acquire+0x0/0x29
> > [ 133.912969] #1: (rcu_read_lock){.+.+..}, at: [<ffffffff82aca483>] rcu_lock_acquire.constprop.14+0x0/0x30
> > [ 133.912969] #2: (slock-AF_INET-RPC/1){+.-...}, at: [<ffffffff82ae84ee>] tcp_v4_rcv+0x28b/0x6fc
> > [ 133.912969]
> > [ 133.912969] stack backtrace:
> > [ 133.912969] Pid: 0, comm: swapper/0 Not tainted 3.5.0-rc4+ #5
> > [ 133.912969] Call Trace:
> > [ 133.912969] <IRQ> [<ffffffff810e09ae>] debug_check_no_locks_freed+0x109/0x14b
> > [ 133.912969] [<ffffffff811774e0>] kmem_cache_free+0x2e/0xa7
> > [ 133.912969] [<ffffffff82a191e5>] __kfree_skb+0x7f/0x83
> > [ 133.912969] [<ffffffff82adeccd>] tcp_ack+0x45d/0xc6a
> > [ 133.912969] [<ffffffff810c22ae>] ? local_clock+0x3b/0x52
> > [ 133.912969] [<ffffffff82adff44>] tcp_rcv_state_process+0x15a/0x7c6
> > [ 133.912969] [<ffffffff82ae79e7>] tcp_v4_do_rcv+0x341/0x390
> > [ 133.912969] [<ffffffff82ae88db>] tcp_v4_rcv+0x678/0x6fc
> > [ 133.912969] [<ffffffff82aca618>] ip_local_deliver_finish+0x165/0x1e4
> > [ 133.912969] [<ffffffff82acab4a>] ip_local_deliver+0x53/0x84
> > [ 133.912969] [<ffffffff810c228c>] ? local_clock+0x19/0x52
> > [ 133.912969] [<ffffffff82aca9c6>] ip_rcv_finish+0x32f/0x367
> > [ 133.912969] [<ffffffff82acad8b>] ip_rcv+0x210/0x269
> > [ 133.912969] [<ffffffff82a1eab1>] ? rcu_lock_acquire+0x27/0x29
> > [ 133.912969] [<ffffffff82a1ea8a>] ? softnet_seq_show+0x68/0x68
> > [ 133.912969] [<ffffffff82a21ede>] __netif_receive_skb+0x3cd/0x464
> > [ 133.912969] [<ffffffff82a21fda>] netif_receive_skb+0x65/0x9c
> > [ 133.912969] [<ffffffff82a227c5>] ? __napi_gro_receive+0xf2/0xff
> > [ 133.912969] [<ffffffff82a2209e>] napi_skb_finish+0x26/0x58
> > [ 133.912969] [<ffffffff810c228c>] ? local_clock+0x19/0x52
> > [ 133.912969] [<ffffffff82a228c5>] napi_gro_receive+0x2f/0x34
> > [ 133.912969] [<ffffffff81e36d12>] e1000_receive_skb+0x57/0x60
> > [ 133.912969] [<ffffffff81e39b23>] e1000_clean_rx_irq+0x2f2/0x387
> > [ 133.912969] [<ffffffff81e390f3>] e1000_clean+0x541/0x695
> > [ 133.912969] [<ffffffff8106c57b>] ? kvm_clock_read+0x2e/0x36
> > [ 133.912969] [<ffffffff82a22402>] ? net_rx_action+0x1b3/0x1f8
> > [ 133.912969] [<ffffffff82a22302>] net_rx_action+0xb3/0x1f8
> > [ 133.912969] [<ffffffff810984ab>] ? __do_softirq+0x76/0x1e8
> > [ 133.912969] [<ffffffff81098515>] __do_softirq+0xe0/0x1e8
> > [ 133.912969] [<ffffffff81122190>] ? time_hardirqs_off+0x26/0x2a
> > [ 133.912969] [<ffffffff82ea7fec>] call_softirq+0x1c/0x30
> > [ 133.912969] [<ffffffff81049cc8>] do_softirq+0x4a/0xa2
> > [ 133.912969] [<ffffffff8109888e>] irq_exit+0x51/0xbc
> > [ 133.912969] [<ffffffff82ea88ae>] do_IRQ+0x8e/0xa5
> > [ 133.912969] [<ffffffff82ea002f>] common_interrupt+0x6f/0x6f
> > [ 133.912969] <EOI> [<ffffffff8106c76b>] ? native_safe_halt+0x6/0x8
> > [ 133.912969] [<ffffffff810e08a3>] ? trace_hardirqs_on+0xd/0xf
> > [ 133.912969] [<ffffffff8104f384>] default_idle+0x53/0x90
> > [ 133.912969] [<ffffffff8104fc09>] cpu_idle+0xcc/0x123
> > [ 133.912969] [<ffffffff82d1d8dd>] rest_init+0xd1/0xda
> > [ 133.912969] [<ffffffff82d1d80c>] ? csum_partial_copy_generic+0x16c/0x16c
> > [ 133.912969] [<ffffffff8460dbbc>] start_kernel+0x3da/0x3e7
> > [ 133.912969] [<ffffffff8460d5ea>] ? repair_env_string+0x5a/0x5a
> > [ 133.912969] [<ffffffff8460d2d6>] x86_64_start_reservations+0xb1/0xb5
> > [ 133.912969] [<ffffffff8460d3d8>] x86_64_start_kernel+0xfe/0x10b
> > [ 134.024230] VFS: Mounted root (nfs filesystem) on device 0:14.
Thanks,
Fengguang
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* RE: [net-next patch] bnx2x: Define bnx2x_tests_str_arr as const
From: Merav Sicron @ 2012-06-27 12:45 UTC (permalink / raw)
To: David Laight; +Cc: davem, netdev, eilong
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B6F68@saturn3.aculab.com>
On Wed, 2012-06-27 at 12:59 +0100, David Laight wrote:
> > -static char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
> > +static const char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = {
> > "register_test (offline) ",
> > "memory_test (offline) ",
> > "int_loopback_test (offline)",
>
> You are still missing a 'const'.
> You probably want:
> static const char *const bnx2x_tests_str_arr[] ...
>
> However if you are going to pad the strings to [28]
> you might as well remove the layer of indirection - ie:
> static const char bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF][28] = { ...
> }
> Or pad to 32 chars to (probably) remove some code bytes.
>
> David
>
Thanks David, let me think about it.
Dave, please ignore this patch for now.
Thanks,
Merav
^ permalink raw reply
* Re: [PATCH] sctp: be mroe restrictive in transport selection on bundled sacks
From: Vlad Yasevich @ 2012-06-27 13:20 UTC (permalink / raw)
To: Neil Horman; +Cc: David Miller, netdev, linux-sctp
In-Reply-To: <20120627102419.GA19313@hmsreliant.think-freely.org>
On 06/27/2012 06:24 AM, Neil Horman wrote:
> On Tue, Jun 26, 2012 at 09:05:04PM -0700, David Miller wrote:
>> From: Neil Horman<nhorman@tuxdriver.com>
>> Date: Tue, 26 Jun 2012 16:31:44 -0400
>>
>>> @@ -240,15 +240,20 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
>>> */
>>> if (sctp_chunk_is_data(chunk)&& !pkt->has_sack&&
>>> !pkt->has_cookie_echo) {
>>> - struct sctp_association *asoc;
>>> struct timer_list *timer;
>>> - asoc = pkt->transport->asoc;
>>> + struct sctp_association *asoc = pkt->transport->asoc;
>>> + struct sctp_transport *trans;
>>> +
>>> timer =&asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
>>>
>>> /* If the SACK timer is running, we have a pending SACK */
>>> if (timer_pending(timer)) {
>>> struct sctp_chunk *sack;
>>> asoc->a_rwnd = asoc->rwnd;
>>> +
>>> + if (chunk->transport&& !chunk->transport->moved_ctsn)
>>> + return retval;
>>> +
>>> sack = sctp_make_sack(asoc);
>>> if (sack) {
>>> retval = sctp_packet_append_chunk(pkt, sack);
>>
>> The new local variable 'trans' seems to be unused.
>>
> Crap, thank you Dave, that was a holdover from an initial pass I had made in
> writing this. I'll repost with that removed once Vald has a chance to look this
> over
> Neil
>
Also, may want to move a_rwnd adjustment to after the new if clause. No
sense adjusting it if we are just going to bail.
-vlad
^ permalink raw reply
* Re: [PATCH] sctp: be mroe restrictive in transport selection on bundled sacks
From: Neil Horman @ 2012-06-27 13:22 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: David Miller, netdev, linux-sctp
In-Reply-To: <4FEB08B9.7030907@gmail.com>
On Wed, Jun 27, 2012 at 09:20:57AM -0400, Vlad Yasevich wrote:
> On 06/27/2012 06:24 AM, Neil Horman wrote:
> >On Tue, Jun 26, 2012 at 09:05:04PM -0700, David Miller wrote:
> >>From: Neil Horman<nhorman@tuxdriver.com>
> >>Date: Tue, 26 Jun 2012 16:31:44 -0400
> >>
> >>>@@ -240,15 +240,20 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
> >>> */
> >>> if (sctp_chunk_is_data(chunk)&& !pkt->has_sack&&
> >>> !pkt->has_cookie_echo) {
> >>>- struct sctp_association *asoc;
> >>> struct timer_list *timer;
> >>>- asoc = pkt->transport->asoc;
> >>>+ struct sctp_association *asoc = pkt->transport->asoc;
> >>>+ struct sctp_transport *trans;
> >>>+
> >>> timer =&asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
> >>>
> >>> /* If the SACK timer is running, we have a pending SACK */
> >>> if (timer_pending(timer)) {
> >>> struct sctp_chunk *sack;
> >>> asoc->a_rwnd = asoc->rwnd;
> >>>+
> >>>+ if (chunk->transport&& !chunk->transport->moved_ctsn)
> >>>+ return retval;
> >>>+
> >>> sack = sctp_make_sack(asoc);
> >>> if (sack) {
> >>> retval = sctp_packet_append_chunk(pkt, sack);
> >>
> >>The new local variable 'trans' seems to be unused.
> >>
> >Crap, thank you Dave, that was a holdover from an initial pass I had made in
> >writing this. I'll repost with that removed once Vald has a chance to look this
> >over
> >Neil
> >
>
> Also, may want to move a_rwnd adjustment to after the new if clause.
> No sense adjusting it if we are just going to bail.
>
> -vlad
>
copy that, I'll make both changes and repost. Thanks!
Neil
^ permalink raw reply
* Re: [RFC] tcp demux used to signal ip_route_input_noref to not cache dst
From: Hans Schillstrom @ 2012-06-27 13:25 UTC (permalink / raw)
To: Eric Dumazet, David Miller; +Cc: netdev
In-Reply-To: <1340783533.26242.2.camel@edumazet-glaptop>
On Wednesday 27 June 2012 09:52:13 Eric Dumazet wrote:
> On Wed, 2012-06-27 at 09:19 +0200, Eric Dumazet wrote:
> > In case tcp_v{4|6}_early_demux() doesnt find an ESTABLISHED socket, and
> > SYN flag is set, and an "atomic_t listener_under_synflood" counter is
> > not 0, we could :
> >
> > - instruct make ip_rcv_finish() to not cache the input dst into route
> > cache (if dst is not found in the hash table)
> >
> > This would make synflood attacks having minimal impact on route cache
> >
> > (We did this for the output dst of SYN-cookie-ACK messages)
> >
> >
>
> I'll test the following patch in a moment.
>
> For the moment, set nocache to true for all frames not associated to an
> ESTABLISHED socket. Not sure we want to test SYN flag after all.
Nice work,
I have been runing the patch for almost 4 hours now
not a single message about the routing cache !
BTW
I also use the "tcp: avoid tx starvation by SYNACK packets" patch
and jhash patch for syn cookies.
Not a packet single packet is dropped now.
I even works nice in a KVM I have never been close to this results with KVM.
^ permalink raw reply
* [PATCH v2 0/5] fec driver updates
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
Changes since v1:
* Add one patch to use devm_gpio_request_one
* Have a separate patch to fix phy-reset-gpios property in binding
document
* Change phy-reset-interval to phy-reset-duration
* Add a sanity check on phy-reset-duration value
Shawn Guo (5):
net: fec: reset phy after pinctrl setup
net: fec: enable regulator for fec phy
net: fec: use managed function devm_gpio_request_one
net: fec: phy-reset-gpios is optional
net: fec: add phy-reset-duration for device tree probe
Documentation/devicetree/bindings/net/fsl-fec.txt | 6 +++-
drivers/net/ethernet/freescale/fec.c | 28 ++++++++++++++++++---
2 files changed, 29 insertions(+), 5 deletions(-)
--
1.7.5.4
^ permalink raw reply
* [PATCH v2 1/5] net: fec: reset phy after pinctrl setup
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
In-Reply-To: <1340804724-29410-1-git-send-email-shawn.guo@linaro.org>
In case that bootloader or platform initialization does not set up
fec pins, the fec_reset_phy will not be able to succeed, because
fec_reset_phy is currently called before devm_pinctrl_get_select_default.
Move fec_reset_phy call to the place between devm_pinctrl_get_select_default
and fec_enet_init to have above case be taken care.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/net/ethernet/freescale/fec.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index ff7f4c5..e868a37 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1593,8 +1593,6 @@ fec_probe(struct platform_device *pdev)
fep->phy_interface = ret;
}
- fec_reset_phy(pdev);
-
for (i = 0; i < FEC_IRQ_NUM; i++) {
irq = platform_get_irq(pdev, i);
if (irq < 0) {
@@ -1634,6 +1632,8 @@ fec_probe(struct platform_device *pdev)
clk_prepare_enable(fep->clk_ahb);
clk_prepare_enable(fep->clk_ipg);
+ fec_reset_phy(pdev);
+
ret = fec_enet_init(ndev);
if (ret)
goto failed_init;
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 2/5] net: fec: enable regulator for fec phy
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
In-Reply-To: <1340804724-29410-1-git-send-email-shawn.guo@linaro.org>
If bootloader or platform initialization code does not enable the
power supply to fec phy, we need to do it in fec driver before calling
fec_reset_phy to have the phy powered on.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/net/ethernet/freescale/fec.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index e868a37..4dce9e3 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -49,6 +49,7 @@
#include <linux/of_gpio.h>
#include <linux/of_net.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
#include <asm/cacheflush.h>
@@ -1546,6 +1547,7 @@ fec_probe(struct platform_device *pdev)
const struct of_device_id *of_id;
static int dev_id;
struct pinctrl *pinctrl;
+ struct regulator *reg_phy;
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
@@ -1632,6 +1634,16 @@ fec_probe(struct platform_device *pdev)
clk_prepare_enable(fep->clk_ahb);
clk_prepare_enable(fep->clk_ipg);
+ reg_phy = devm_regulator_get(&pdev->dev, "phy");
+ if (!IS_ERR(reg_phy)) {
+ ret = regulator_enable(reg_phy);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to enable phy regulator: %d\n", ret);
+ goto failed_regulator;
+ }
+ }
+
fec_reset_phy(pdev);
ret = fec_enet_init(ndev);
@@ -1655,6 +1667,7 @@ failed_register:
fec_enet_mii_remove(fep);
failed_mii_init:
failed_init:
+failed_regulator:
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
failed_pin:
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 3/5] net: fec: use managed function devm_gpio_request_one
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
In-Reply-To: <1340804724-29410-1-git-send-email-shawn.guo@linaro.org>
Using gpio_request_one will require the probe fail-out call gpio_free,
which is missing currently. Change to use devm_gpio_request_one to
fix the problem.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/net/ethernet/freescale/fec.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 4dce9e3..f174070 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1513,7 +1513,8 @@ static void __devinit fec_reset_phy(struct platform_device *pdev)
return;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
- err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
+ err = devm_gpio_request_one(&pdev->dev, phy_reset,
+ GPIOF_OUT_INIT_LOW, "phy-reset");
if (err) {
pr_debug("FEC: failed to get gpio phy-reset: %d\n", err);
return;
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 4/5] net: fec: phy-reset-gpios is optional
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
In-Reply-To: <1340804724-29410-1-git-send-email-shawn.guo@linaro.org>
The phy-reset-gpios is an optional property for fec device tree boot.
Change the binding document to match the driver code.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
Documentation/devicetree/bindings/net/fsl-fec.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 7ab9e1a..0428920 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -7,10 +7,10 @@ Required properties:
- phy-mode : String, operation mode of the PHY interface.
Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
"rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
-- phy-reset-gpios : Should specify the gpio for phy reset
Optional properties:
- local-mac-address : 6 bytes, mac address
+- phy-reset-gpios : Should specify the gpio for phy reset
Example:
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 5/5] net: fec: add phy-reset-duration for device tree probe
From: Shawn Guo @ 2012-06-27 13:45 UTC (permalink / raw)
To: David S. Miller
Cc: Lothar Waßmann, Florian Fainelli, netdev, linux-arm-kernel,
devicetree-discuss, Shawn Guo
In-Reply-To: <1340804724-29410-1-git-send-email-shawn.guo@linaro.org>
Different boards may require different phy reset duration. Add property
phy-reset-duration for device tree probe, so that the boards that need
a longer reset duration can specify it in their device tree.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
Documentation/devicetree/bindings/net/fsl-fec.txt | 4 ++++
drivers/net/ethernet/freescale/fec.c | 8 +++++++-
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 0428920..f7a2fef 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -11,6 +11,10 @@ Required properties:
Optional properties:
- local-mac-address : 6 bytes, mac address
- phy-reset-gpios : Should specify the gpio for phy reset
+- phy-reset-duration : Reset duration in milliseconds. Should present
+ only if property "phy-reset-gpios" is available. Missing the property
+ will have the duration be 1 millisecond. Numbers greater than 1000 are
+ invalid and 1 millisecond will be used instead.
Example:
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index f174070..dafd797 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1507,11 +1507,17 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
static void __devinit fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
+ int msec = 1;
struct device_node *np = pdev->dev.of_node;
if (!np)
return;
+ of_property_read_u32(np, "phy-reset-duration", &msec);
+ /* A sane reset duration should not be longer than 1s */
+ if (msec > 1000)
+ msec = 1;
+
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
err = devm_gpio_request_one(&pdev->dev, phy_reset,
GPIOF_OUT_INIT_LOW, "phy-reset");
@@ -1519,7 +1525,7 @@ static void __devinit fec_reset_phy(struct platform_device *pdev)
pr_debug("FEC: failed to get gpio phy-reset: %d\n", err);
return;
}
- msleep(1);
+ msleep(msec);
gpio_set_value(phy_reset, 1);
}
#else /* CONFIG_OF */
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2] sctp: be more restrictive in transport selection on bundled sacks
From: Neil Horman @ 2012-06-27 14:23 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, Vlad Yaseivch, David S. Miller
In-Reply-To: <1340742704-2192-1-git-send-email-nhorman@tuxdriver.com>
It was noticed recently that when we send data on a transport, its possible that
we might bundle a sack that arrived on a different transport. While this isn't
a major problem, it does go against the SHOULD requirement in section 6.4 of RFC
2960:
An endpoint SHOULD transmit reply chunks (e.g., SACK, HEARTBEAT ACK,
etc.) to the same destination transport address from which it
received the DATA or control chunk to which it is replying. This
rule should also be followed if the endpoint is bundling DATA chunks
together with the reply chunk.
This patch seeks to correct that. It restricts the bundling of sack operations
to only those transports which have moved the ctsn of the association forward
since the last sack. By doing this we guarantee that we only bundle outbound
saks on a transport that has received a chunk since the last sack. This brings
us into stricter compliance with the RFC.
Vlad had initially suggested that we strictly allow only sack bundling on the
transport that last moved the ctsn forward. While this makes sense, I was
concerned that doing so prevented us from bundling in the case where we had
received chunks that moved the ctsn on multiple transports. In those cases, the
RFC allows us to select any of the transports having received chunks to bundle
the sack on. so I've modified the approach to allow for that, by adding a state
variable to each transport that tracks weather it has moved the ctsn since the
last sack. This I think keeps our behavior (and performance), close enough to
our current profile that I think we can do this without a sysctl knob to
enable/disable it.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Vlad Yaseivch <vyasevich@gmail.com>
CC: David S. Miller <davem@davemloft.net>
Reported-by: Michele Baldessari <michele@redhat.com>
Reported-by: sorin serban <sserban@redhat.com>
---
Change Notes:
V2)
* Removed unused variable as per Dave M. Request
* Delayed rwnd adjustment until we are sure we will sack (Vlad Y.)
---
include/net/sctp/structs.h | 5 ++++-
include/net/sctp/tsnmap.h | 3 ++-
net/sctp/output.c | 10 +++++++---
net/sctp/sm_make_chunk.c | 7 +++++++
net/sctp/sm_sideeffect.c | 2 +-
net/sctp/tsnmap.c | 5 ++++-
net/sctp/ulpevent.c | 3 ++-
net/sctp/ulpqueue.c | 2 +-
8 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index e4652fe..712bf09 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -910,7 +910,10 @@ struct sctp_transport {
pmtu_pending:1,
/* Is this structure kfree()able? */
- malloced:1;
+ malloced:1,
+
+ /* Has this transport moved the ctsn since we last sacked */
+ moved_ctsn:1;
struct flowi fl;
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index e7728bc..2c5d2b4 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map);
int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
/* Mark this TSN as seen. */
-int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
+int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn,
+ struct sctp_transport *trans);
/* Mark this TSN and all lower as seen. */
void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
diff --git a/net/sctp/output.c b/net/sctp/output.c
index f1b7d4b..6c8cb9e 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -240,17 +240,21 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
*/
if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
!pkt->has_cookie_echo) {
- struct sctp_association *asoc;
struct timer_list *timer;
- asoc = pkt->transport->asoc;
+ struct sctp_association *asoc = pkt->transport->asoc;
+
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
/* If the SACK timer is running, we have a pending SACK */
if (timer_pending(timer)) {
struct sctp_chunk *sack;
- asoc->a_rwnd = asoc->rwnd;
+
+ if (chunk->transport && !chunk->transport->moved_ctsn)
+ return retval;
+
sack = sctp_make_sack(asoc);
if (sack) {
+ asoc->a_rwnd = asoc->rwnd;
retval = sctp_packet_append_chunk(pkt, sack);
asoc->peer.sack_needed = 0;
if (del_timer(timer))
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index a85eeeb..805babe 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -736,6 +736,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
__u16 num_gabs, num_dup_tsns;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
+ struct sctp_transport *trans;
memset(gabs, 0, sizeof(gabs));
ctsn = sctp_tsnmap_get_ctsn(map);
@@ -805,6 +806,12 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
sctp_tsnmap_get_dups(map));
+ /*
+ * Once we have a sack generated, clear the moved_tsn information
+ * from all the transports
+ */
+ list_for_each_entry(trans, &asoc->peer.transport_addr_list, transports)
+ trans->moved_ctsn = 0;
nodata:
return retval;
}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c96d1a8..8716da1 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1268,7 +1268,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_REPORT_TSN:
/* Record the arrival of a TSN. */
error = sctp_tsnmap_mark(&asoc->peer.tsn_map,
- cmd->obj.u32);
+ cmd->obj.u32, NULL);
break;
case SCTP_CMD_REPORT_FWDTSN:
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index f1e40ceb..619c638 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
/* Mark this TSN as seen. */
-int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
+int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
+ struct sctp_transport *trans)
{
u16 gap;
@@ -133,6 +134,8 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
*/
map->max_tsn_seen++;
map->cumulative_tsn_ack_point++;
+ if (trans)
+ trans->moved_ctsn = 1;
map->base_tsn++;
} else {
/* Either we already have a gap, or about to record a gap, so
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 8a84017..33d8947 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -715,7 +715,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
* can mark it as received so the tsn_map is updated correctly.
*/
if (sctp_tsnmap_mark(&asoc->peer.tsn_map,
- ntohl(chunk->subh.data_hdr->tsn)))
+ ntohl(chunk->subh.data_hdr->tsn),
+ chunk->transport))
goto fail_mark;
/* First calculate the padding, so we don't inadvertently
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index f2d1de7..f5a6a4f 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -1051,7 +1051,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
if (chunk && (freed >= needed)) {
__u32 tsn;
tsn = ntohl(chunk->subh.data_hdr->tsn);
- sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
+ sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
sctp_ulpq_tail_data(ulpq, chunk, gfp);
sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH v2] sctp: be more restrictive in transport selection on bundled sacks
From: Vlad Yasevich @ 2012-06-27 15:10 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, David S. Miller
In-Reply-To: <1340807003-23139-1-git-send-email-nhorman@tuxdriver.com>
On 06/27/2012 10:23 AM, Neil Horman wrote:
> It was noticed recently that when we send data on a transport, its possible that
> we might bundle a sack that arrived on a different transport. While this isn't
> a major problem, it does go against the SHOULD requirement in section 6.4 of RFC
> 2960:
>
> An endpoint SHOULD transmit reply chunks (e.g., SACK, HEARTBEAT ACK,
> etc.) to the same destination transport address from which it
> received the DATA or control chunk to which it is replying. This
> rule should also be followed if the endpoint is bundling DATA chunks
> together with the reply chunk.
>
> This patch seeks to correct that. It restricts the bundling of sack operations
> to only those transports which have moved the ctsn of the association forward
> since the last sack. By doing this we guarantee that we only bundle outbound
> saks on a transport that has received a chunk since the last sack. This brings
> us into stricter compliance with the RFC.
>
> Vlad had initially suggested that we strictly allow only sack bundling on the
> transport that last moved the ctsn forward. While this makes sense, I was
> concerned that doing so prevented us from bundling in the case where we had
> received chunks that moved the ctsn on multiple transports. In those cases, the
> RFC allows us to select any of the transports having received chunks to bundle
> the sack on. so I've modified the approach to allow for that, by adding a state
> variable to each transport that tracks weather it has moved the ctsn since the
> last sack. This I think keeps our behavior (and performance), close enough to
> our current profile that I think we can do this without a sysctl knob to
> enable/disable it.
>
> Signed-off-by: Neil Horman<nhorman@tuxdriver.com>
> CC: Vlad Yaseivch<vyasevich@gmail.com>
> CC: David S. Miller<davem@davemloft.net>
> Reported-by: Michele Baldessari<michele@redhat.com>
> Reported-by: sorin serban<sserban@redhat.com>
>
> ---
> Change Notes:
> V2)
> * Removed unused variable as per Dave M. Request
> * Delayed rwnd adjustment until we are sure we will sack (Vlad Y.)
> ---
> include/net/sctp/structs.h | 5 ++++-
> include/net/sctp/tsnmap.h | 3 ++-
> net/sctp/output.c | 10 +++++++---
> net/sctp/sm_make_chunk.c | 7 +++++++
> net/sctp/sm_sideeffect.c | 2 +-
> net/sctp/tsnmap.c | 5 ++++-
> net/sctp/ulpevent.c | 3 ++-
> net/sctp/ulpqueue.c | 2 +-
> 8 files changed, 28 insertions(+), 9 deletions(-)
>
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index e4652fe..712bf09 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -910,7 +910,10 @@ struct sctp_transport {
> pmtu_pending:1,
>
> /* Is this structure kfree()able? */
> - malloced:1;
> + malloced:1,
> +
> + /* Has this transport moved the ctsn since we last sacked */
> + moved_ctsn:1;
>
> struct flowi fl;
>
> diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
> index e7728bc..2c5d2b4 100644
> --- a/include/net/sctp/tsnmap.h
> +++ b/include/net/sctp/tsnmap.h
> @@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map);
> int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
>
> /* Mark this TSN as seen. */
> -int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
> +int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn,
> + struct sctp_transport *trans);
>
> /* Mark this TSN and all lower as seen. */
> void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index f1b7d4b..6c8cb9e 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -240,17 +240,21 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
> */
> if (sctp_chunk_is_data(chunk)&& !pkt->has_sack&&
> !pkt->has_cookie_echo) {
> - struct sctp_association *asoc;
> struct timer_list *timer;
> - asoc = pkt->transport->asoc;
> + struct sctp_association *asoc = pkt->transport->asoc;
> +
> timer =&asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
>
> /* If the SACK timer is running, we have a pending SACK */
> if (timer_pending(timer)) {
> struct sctp_chunk *sack;
> - asoc->a_rwnd = asoc->rwnd;
> +
> + if (chunk->transport&& !chunk->transport->moved_ctsn)
> + return retval;
> +
I didn't think of this yesterday, but I think it would be much better to
use pkt->transport here since you are adding the chunk to the packet and
it will go out on the transport of the packet. You are also guaranteed
that pkt->transport is set.
> sack = sctp_make_sack(asoc);
> if (sack) {
> + asoc->a_rwnd = asoc->rwnd;
> retval = sctp_packet_append_chunk(pkt, sack);
> asoc->peer.sack_needed = 0;
> if (del_timer(timer))
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index a85eeeb..805babe 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -736,6 +736,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
> __u16 num_gabs, num_dup_tsns;
> struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
> struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
> + struct sctp_transport *trans;
>
> memset(gabs, 0, sizeof(gabs));
> ctsn = sctp_tsnmap_get_ctsn(map);
> @@ -805,6 +806,12 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
> sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
> sctp_tsnmap_get_dups(map));
>
> + /*
> + * Once we have a sack generated, clear the moved_tsn information
> + * from all the transports
> + */
> + list_for_each_entry(trans,&asoc->peer.transport_addr_list, transports)
> + trans->moved_ctsn = 0;
> nodata:
> return retval;
> }
> diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
> index c96d1a8..8716da1 100644
> --- a/net/sctp/sm_sideeffect.c
> +++ b/net/sctp/sm_sideeffect.c
> @@ -1268,7 +1268,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
> case SCTP_CMD_REPORT_TSN:
> /* Record the arrival of a TSN. */
> error = sctp_tsnmap_mark(&asoc->peer.tsn_map,
> - cmd->obj.u32);
> + cmd->obj.u32, NULL);
> break;
>
> case SCTP_CMD_REPORT_FWDTSN:
> diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
> index f1e40ceb..619c638 100644
> --- a/net/sctp/tsnmap.c
> +++ b/net/sctp/tsnmap.c
> @@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
>
>
> /* Mark this TSN as seen. */
> -int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
> +int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
> + struct sctp_transport *trans)
> {
> u16 gap;
>
> @@ -133,6 +134,8 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
> */
> map->max_tsn_seen++;
> map->cumulative_tsn_ack_point++;
> + if (trans)
> + trans->moved_ctsn = 1;
> map->base_tsn++;
> } else {
> /* Either we already have a gap, or about to record a gap, so
> diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
> index 8a84017..33d8947 100644
> --- a/net/sctp/ulpevent.c
> +++ b/net/sctp/ulpevent.c
> @@ -715,7 +715,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
> * can mark it as received so the tsn_map is updated correctly.
> */
> if (sctp_tsnmap_mark(&asoc->peer.tsn_map,
> - ntohl(chunk->subh.data_hdr->tsn)))
> + ntohl(chunk->subh.data_hdr->tsn),
> + chunk->transport))
> goto fail_mark;
>
> /* First calculate the padding, so we don't inadvertently
> diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
> index f2d1de7..f5a6a4f 100644
> --- a/net/sctp/ulpqueue.c
> +++ b/net/sctp/ulpqueue.c
> @@ -1051,7 +1051,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
> if (chunk&& (freed>= needed)) {
> __u32 tsn;
> tsn = ntohl(chunk->subh.data_hdr->tsn);
> - sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
> + sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
> sctp_ulpq_tail_data(ulpq, chunk, gfp);
>
> sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
Also, I think you need to reset this bit in sctp_transport_reset().
Consider a potential association restart after SACKs have been received.
-vlad
^ permalink raw reply
* [patch net-next] virtio_net: allow to change mac when iface is running
From: Jiri Pirko @ 2012-06-27 15:27 UTC (permalink / raw)
To: netdev; +Cc: davem, rusty, mst, virtualization, brouer
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/virtio_net.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f18149a..36a16d5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -679,11 +679,12 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
{
struct virtnet_info *vi = netdev_priv(dev);
struct virtio_device *vdev = vi->vdev;
- int ret;
+ struct sockaddr *addr = p;
- ret = eth_mac_addr(dev, p);
- if (ret)
- return ret;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
--
1.7.10.4
^ permalink raw reply related
* Fw: [Bug 43901] New: Packet Dropping when attach TBF to PRIO qdisc
From: Stephen Hemminger @ 2012-06-27 15:27 UTC (permalink / raw)
To: netdev
Begin forwarded message:
Date: Wed, 27 Jun 2012 12:14:28 +0000 (UTC)
From: bugzilla-daemon@bugzilla.kernel.org
To: shemminger@linux-foundation.org
Subject: [Bug 43901] New: Packet Dropping when attach TBF to PRIO qdisc
https://bugzilla.kernel.org/show_bug.cgi?id=43901
Summary: Packet Dropping when attach TBF to PRIO qdisc
Product: Networking
Version: 2.5
Kernel Version: 3.4.4
Platform: All
OS/Version: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: IPV4
AssignedTo: shemminger@linux-foundation.org
ReportedBy: lucas.bocchi@gmail.com
Regression: No
Created an attachment (id=74371)
--> (https://bugzilla.kernel.org/attachment.cgi?id=74371)
Kernel config file
Friends
When I do a upgrade in one server kernel with 2.6.32.5 kernel to actual 3.4.4
kernel, my TBF qdisc attached to a PRIO qdisc stops to work.
The first classes won't have any heavy traffic to justify the starvation of
another classes, but packets are dropped with
See some information about the bug
Gnu C 4.7
Gnu make 3.81
binutils 2.22
util-linux 2.20.1
mount support
module-init-tools 8
e2fsprogs 1.42.4
PPP 2.4.5
Linux C Library 2.13
Dynamic linker (ldd) 2.13
Procps 3.3.2
Net-tools 1.60
Kbd 1.15.3
Sh-utils 8.13
Modules Loaded sch_tbf xt_mark xt_mac xt_state xt_connmark cls_fw
cls_u32 sch_prio sha1_ssse3 sha1_generic arc4 ecb ppp_mppe ppp_async crc_ccitt
ppp_generic slhc xt_tcpudp ipt_MASQUERADE iptable_mangle iptable_nat nf_nat
nf_conntrack_ipv4 nf_defrag_ipv4 nf_conntrack iptable_filter ip_tables x_tables
nfsd exportfs nfs nfs_acl auth_rpcgss lockd sunrpc ipv6 loop snd_hda_codec_via
iTCO_wdt snd_hda_intel snd_hda_codec acpi_cpufreq mperf freq_table coretemp
intel_agp intel_gtt rng_core snd_pcm evdev rtc_cmos i2c_i801 snd_page_alloc
i2c_core pcspkr snd_timer processor snd microcode soundcore button ext3 mbcache
jbd sr_mod cdrom ata_generic sd_mod pata_acpi usb_storage uas ata_piix thermal
thermal_sys uhci_hcd libata scsi_mod r8169 mii piix ide_pci_generic ide_core
ehci_hcd
The TC commands
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 01:0 prio bands 5 priomap 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4
tc qdisc add dev eth0 parent 01:01 handle 11:0 pfifo limit 100
tc qdisc add dev eth0 parent 01:02 handle 12:0 pfifo limit 100
tc qdisc add dev eth0 parent 01:03 handle 13:0 pfifo limit 100
tc qdisc add dev eth0 parent 01:04 handle 14:0 tbf rate 3Mbit latency 2s burst
10k
tc qdisc add dev eth0 parent 01:05 handle 15:0 tbf rate 3Mbit latency 2s burst
10k
tc filter add dev eth0 parent 01:00 prio 1 u32 match u8 64 0xff at 8 flowid 1:1
tc filter add dev eth0 parent 01:00 prio 1 u32 match ip protocol 6 0xff match
u8 0x10 0xff at nexthdr+13 flowid 1:1
tc filter add dev eth0 parent 01:00 prio 1 u32 match ip protocol 6 0xff match
u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid
1:1
tc filter add dev eth0 parent 01:00 prio 2 protocol ip u32 match ip protocol 1
0xff flowid 1:1
tc filter add dev eth0 parent 01:00 prio 3 protocol ip u32 match ip dst
172.16.0.250 flowid 1:2
tc filter add dev eth0 parent 01:00 prio 3 protocol ip u32 match ip dst
172.16.0.58 flowid 1:2
tc filter add dev eth0 parent 01:00 prio 4 protocol ip u32 match ip sport 8291
0xffff flowid 1:3
tc filter add dev eth0 parent 01:00 prio 5 protocol ip handle 1 fw flowid 1:4
--
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.
^ permalink raw reply
* Re: [PATCH 7/7] netlink: Get rid of obsolete rtnetlink macros
From: Stephen Hemminger @ 2012-06-27 15:35 UTC (permalink / raw)
To: Thomas Graf; +Cc: davem, netdev
In-Reply-To: <a10752bf3eb27e13e61b817664d58a69f9179fc9.1340788373.git.tgraf@suug.ch>
On Wed, 27 Jun 2012 11:36:16 +0200
Thomas Graf <tgraf@suug.ch> wrote:
> Removes all RTA_GET*() and RTA_PUT*() variations, as well as the
> the unused rtattr_strcmp(). Get rid of rtm_get_table() by moving
> it to its only user decnet.
>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> ---
Nack. The RTA_ macros are exported to user space through kernel
headers process. If you do this it will break iproute2 build.
^ permalink raw reply
* Re: HSR: How to set IF_OPER_LOWERLAYERDOWN?
From: Stephen Hemminger @ 2012-06-27 15:40 UTC (permalink / raw)
To: Arvid Brodin; +Cc: netdev@vger.kernel.org, Javier Boticario, Bruno Ferreira
In-Reply-To: <4FEA64F3.8000400@xdin.com>
On Wed, 27 Jun 2012 01:42:12 +0000
Arvid Brodin <Arvid.Brodin@xdin.com> wrote:
> On 2012-06-27 00:33, Stephen Hemminger wrote:
> > On Tue, 26 Jun 2012 22:28:51 +0000
> > Arvid Brodin <Arvid.Brodin@xdin.com> wrote:
> >
> >> Hi,
> >>
> >> According to Documentation/networking/operstates.txt a network interface have an
> >> operational state and an administrative state.
> >>
> >> If I understand things correctly the administrative state is the desired state set by
> >> userspace, and the operational state is the actual state which depends on things like the
> >> administrative state, whether a carrier is present, or (for virtual interfaces lite VLAN)
> >> whether the lower interface is available.
> >>
> >>
> >> In the driver I'm writing (for the "HSR" redundancy protocol) a hsr (virtual) interface is
> >> useable as long as any of its (physical) slaves are useable. I.e. the operstate of a hsr
> >> device might be set like this:
> >>
> >> void hsr_set_operstate()
> >> {
> >> if (!is_admin_up(hsr_dev)) /* Check IFF_UP */ {
> >> set_operstate(hsr_dev, IF_OPER_DOWN);
> >> return;
> >> }
> >>
> >> if (is_operstate_up(slave1) || is_operstate_up(slave2)) /* Check IF_OPER_UP */
> >> set_operstate(hsr_dev, IF_OPER_UP);
> >> else
> >> set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
> >> }
> >
> >
> > According to 802.1X example in documentation to set it down you need to set IF_OPER_DORMANT
> > not IF_OPER_LOWERLAYERDOWN. Probably a kernel bug in there somwhere.
> >
>
> Hmm... if you're referring to the example in Documentation/networking/operstates.txt it
> seems to me that the usage of IF_OPER_DORMANT there is in compliance with RFC2863 - i.e.
> the device is waiting for some kind of handshake to finish. I don't think it has anything
> to do with taking the device down?
>
> Oh, and I see now that set_operstate() is called from do_setlink() in
> net/core/rtnetlink.c, which means this function is used to set operstate from userspace.
> The limitations then fits with the description in operstates.txt, and this function is
> probably not meant to set an interface's operational state from within the kernel. I wrote
> my own hsr_set_operstate that accepts any values, and it seems to work... (?)
>
>
> Is there a way to get notifications when an interface's operational state change?
> NETDEV_CHANGE seems to trigger on carrier change, and NETDEV_UP/DOWN triggers when the
> administrative state changes - is there something similar for operational state?
>
> (Unfortunately NETDEV_UP/DOWN triggers before the operational state for the interface in
> question changes accordingly, so it's not possible to just check dev->operstate in the
> handler for these messages. NETDEV_CHANGE seems to trigger after the interface's
> operational state has been changed, though.)
>
I think the original intention was for kernel drivers to use
netif_carrier_on/off rather than manipulating operstate directly.
^ permalink raw reply
* Re: [PATCHv1] net: added support for 40GbE link.
From: Ben Hutchings @ 2012-06-27 16:03 UTC (permalink / raw)
To: Parav Pandit; +Cc: netdev
In-Reply-To: <054018eb-a85c-4401-a010-7479aa38d2ef@exht1.ad.emulex.com>
On Wed, 2012-06-27 at 19:26 +0530, Parav Pandit wrote:
> 1. removed code replication for tov calculation for 1G, 10G and
> made is common for speed > 1G (1G, 10G, 40G, 100G).
> 2. defines values for #4 different 40G Phys (KR4, LF4, SR4, CR4)
>
> Signed-off-by: Parav Pandit <parav.pandit@emulex.com>
Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [net-next.git 4/4 (v8)] phy: add the EEE support and the way to access to the MMD registers.
From: Ben Hutchings @ 2012-06-27 16:15 UTC (permalink / raw)
To: Giuseppe CAVALLARO; +Cc: netdev, eric.dumazet, rayagond, davem, yuvalmin
In-Reply-To: <1340258599-3083-5-git-send-email-peppe.cavallaro@st.com>
On Thu, 2012-06-21 at 08:03 +0200, Giuseppe CAVALLARO wrote:
[...]
> v8: fixed a problem in the phy_init_eee return value erroneously added
> when included the phy_read_status call.
Almost there. :-/
[...]
> +int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
> +{
> + int ret = -EPROTONOSUPPORT;
> +
> + /* According to 802.3az,the EEE is supported only in full duplex-mode.
> + * Also EEE feature is active when core is operating with MII, GMII
> + * or RGMII.
> + */
> + if ((phydev->duplex == DUPLEX_FULL) &&
> + ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
> + (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
> + (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
> + u16 eee_lp, eee_cap, eee_adv;
> + u32 lp, cap, adv;
> + int idx, status;
> +
> + /* Read phy status to properly get the right settings */
> + status = phy_read_status(phydev);
> + if (status)
> + return status;
> +
> + /* First check if the EEE ability is supported */
> + eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
> + MDIO_MMD_PCS, phydev->addr);
> + if (eee_cap < 0)
> + return eee_cap;
> +
> + cap = phy_eee_to_supported(eee_cap);
> + if (!cap)
> + goto eee_exit;
> +
> + /* Check which link settings negotiated and verify it in
> + * the EEE advertising registers.
> + */
> + eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
> + MDIO_MMD_AN, phydev->addr);
> + if (eee_lp < 0)
> + return eee_lp;
> +
> + eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
> + MDIO_MMD_AN, phydev->addr);
> + if (eee_adv < 0)
> + return eee_adv;
You check for eee_{cap,lp,adv} < 0 but that's impossible since the
variables are declared unsigned (u16). (I wonder what compiler you are
using, as I would expect this to result in a warning.) I think they
need to be declared int.
> + adv = phy_eee_to_adv(eee_adv);
> + lp = phy_eee_to_adv(eee_lp);
> + idx = phy_find_setting(phydev->speed, phydev->duplex);
> + if ((lp & adv & settings[idx].setting))
> + goto eee_exit;
> +
> + if (clk_stop_enable) {
> + /* Configure the PHY to stop receiving xMII
> + * clock while it is signaling LPI.
> + */
> + u32 val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
> + MDIO_MMD_PCS,
> + phydev->addr);
> + if (val < 0)
> + return val;
Same problem here.
[...]
> --- a/include/linux/mdio.h
> +++ b/include/linux/mdio.h
[...]
> @@ -237,9 +241,18 @@
> #define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */
> #define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */
>
> -/* AN EEE Advertisement register. */
> -#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
> -#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
[...]
This header is exported to userland so I don't think these definitions
can be removed. But you could comment that they're redundant with the
following MDIO_EEE_* definitions.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 7/18] netfilter: nfnetlink_log: Move away from NLMSG_PUT().
From: Ben Hutchings @ 2012-06-27 16:49 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120626.220223.1090653207727010874.davem@davemloft.net>
On Tue, 2012-06-26 at 22:02 -0700, David Miller wrote:
> And use nlmsg_data() while we're here too.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> ---
> net/netfilter/nfnetlink_log.c | 29 ++++++++++++++++-------------
> 1 file changed, 16 insertions(+), 13 deletions(-)
>
> diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
> index 3c3cfc0..169ab59 100644
> --- a/net/netfilter/nfnetlink_log.c
> +++ b/net/netfilter/nfnetlink_log.c
> @@ -326,18 +326,20 @@ __nfulnl_send(struct nfulnl_instance *inst)
> {
> int status = -1;
>
> - if (inst->qlen > 1)
> - NLMSG_PUT(inst->skb, 0, 0,
> - NLMSG_DONE,
> - sizeof(struct nfgenmsg));
> -
> + if (inst->qlen > 1) {
> + struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
> + NLMSG_DONE,
> + sizeof(struct nfgenmsg),
> + 0);
> + if (!nlh)
> + goto out;
> + }
> status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_pid,
> MSG_DONTWAIT);
>
> inst->qlen = 0;
> inst->skb = NULL;
> -
> -nlmsg_failure:
> +out:
> return status;
> }
[...]
It looks like this also leaks the skb on failure. At least,
__nfulnl_flush(inst) is expected to dipose of inst->skb.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ 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