* [PATCH 4/4] ipip: follow state of lower device
From: Stephen Hemminger @ 2012-04-12 16:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120412163115.076119065@vyatta.com>
[-- Attachment #1: ipip-lowerup.patch --]
[-- Type: text/plain, Size: 2365 bytes --]
Same as other tunnels propogate
carrier and RFC2863 state from lower device to tunnel.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/ipip.c 2012-04-12 08:07:39.000000000 -0700
+++ b/net/ipv4/ipip.c 2012-04-12 08:14:37.776589029 -0700
@@ -304,6 +304,8 @@ static struct ip_tunnel * ipip_tunnel_lo
dev_hold(dev);
ipip_tunnel_link(ipn, nt);
+ linkwatch_fire_event(dev);
+
return nt;
failed_free:
@@ -614,6 +616,7 @@ static void ipip_tunnel_bind_dev(struct
if (tdev) {
dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
dev->mtu = tdev->mtu - sizeof(struct iphdr);
+ netif_stacked_transfer_operstate(tdev, dev);
}
dev->iflink = tunnel->parms.link;
}
@@ -897,6 +900,36 @@ static struct pernet_operations ipip_net
.size = sizeof(struct ipip_net),
};
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipip_notify(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ struct ip_tunnel *t;
+ unsigned int prio, h;
+
+ if (event == NETDEV_CHANGE)
+ return NOTIFY_DONE;
+
+ for (prio = 0; prio < 4; prio++)
+ for (h = 0; h < HASH_SIZE; h++) {
+ for (t = rtnl_dereference(ipn->tunnels[prio][h]); t;
+ t = rtnl_dereference(t->next)) {
+ if (dev->ifindex != t->dev->iflink)
+ continue;
+ netif_stacked_transfer_operstate(dev, t->dev);
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ipip_notifier = {
+ .notifier_call = ipip_notify,
+};
+
static int __init ipip_init(void)
{
int err;
@@ -906,12 +939,24 @@ static int __init ipip_init(void)
err = register_pernet_device(&ipip_net_ops);
if (err < 0)
return err;
+
+ err = register_netdevice_notifier(&ipip_notifier);
+ if (err < 0)
+ goto notify_failed;
+
err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
- if (err < 0) {
- unregister_pernet_device(&ipip_net_ops);
- pr_info("%s: can't register tunnel\n", __func__);
- }
+ if (err < 0)
+ goto xfrm4_tunnel_failed;
+out:
return err;
+
+xfrm4_tunnel_failed:
+ pr_info("%s: can't register tunnel\n", __func__);
+ unregister_netdevice_notifier(&ipip_notifier);
+
+notify_failed:
+ unregister_pernet_device(&ipip_net_ops);
+ goto out;
}
static void __exit ipip_fini(void)
^ permalink raw reply
* [PATCH 1/4] tunnel: implement 64 bits statistics
From: Stephen Hemminger @ 2012-04-12 16:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120412163115.076119065@vyatta.com>
[-- Attachment #1: tunnel-64bit-stats.patch --]
[-- Type: text/plain, Size: 9277 bytes --]
Convert the per-cpu statistics kept for GRE, IPIP, and SIT tunnels
to use 64 bit statistics.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
include/net/ipip.h | 2 +
net/ipv4/ip_gre.c | 59 +++++++++++++++++++++++++++++++++++------------------
net/ipv4/ipip.c | 53 +++++++++++++++++++++++++++++++----------------
net/ipv6/sit.c | 52 ++++++++++++++++++++++++++++++----------------
4 files changed, 111 insertions(+), 55 deletions(-)
--- a/include/net/ipip.h 2012-03-14 09:51:26.511060845 -0700
+++ b/include/net/ipip.h 2012-04-11 11:46:20.338815164 -0700
@@ -54,8 +54,10 @@ struct ip_tunnel_prl_entry {
\
err = ip_local_out(skb); \
if (likely(net_xmit_eval(err) == 0)) { \
+ u64_stats_update_begin(&(stats1)->syncp); \
(stats1)->tx_bytes += pkt_len; \
(stats1)->tx_packets++; \
+ u64_stats_update_end(&(stats1)->syncp); \
} else { \
(stats2)->tx_errors++; \
(stats2)->tx_aborted_errors++; \
--- a/net/ipv4/ip_gre.c 2012-04-09 11:18:09.000000000 -0700
+++ b/net/ipv4/ip_gre.c 2012-04-11 11:46:20.338815164 -0700
@@ -169,30 +169,49 @@ struct ipgre_net {
/* often modified stats are per cpu, other are shared (netdev->stats) */
struct pcpu_tstats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long tx_bytes;
-} __attribute__((aligned(4*sizeof(unsigned long))));
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
-static struct net_device_stats *ipgre_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
{
- struct pcpu_tstats sum = { 0 };
int i;
for_each_possible_cpu(i) {
const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&tstats->syncp);
+ rx_packets = tstats->rx_packets;
+ tx_packets = tstats->tx_packets;
+ rx_bytes = tstats->rx_bytes;
+ tx_bytes = tstats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ }
+
+ tot->multicast = dev->stats.multicast;
+ tot->rx_crc_errors = dev->stats.rx_crc_errors;
+ tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
+ tot->rx_length_errors = dev->stats.rx_length_errors;
+ tot->rx_errors = dev->stats.rx_errors;
+ tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
+ tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
+ tot->tx_dropped = dev->stats.tx_dropped;
+ tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
+ tot->tx_errors = dev->stats.tx_errors;
- sum.rx_packets += tstats->rx_packets;
- sum.rx_bytes += tstats->rx_bytes;
- sum.tx_packets += tstats->tx_packets;
- sum.tx_bytes += tstats->tx_bytes;
- }
- dev->stats.rx_packets = sum.rx_packets;
- dev->stats.rx_bytes = sum.rx_bytes;
- dev->stats.tx_packets = sum.tx_packets;
- dev->stats.tx_bytes = sum.tx_bytes;
- return &dev->stats;
+ return tot;
}
/* Given src, dst and key, find appropriate for input tunnel. */
@@ -672,8 +691,10 @@ static int ipgre_rcv(struct sk_buff *skb
}
tstats = this_cpu_ptr(tunnel->dev->tstats);
+ u64_stats_update_begin(&tstats->syncp);
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
+ u64_stats_update_end(&tstats->syncp);
__skb_tunnel_rx(skb, tunnel->dev);
@@ -1253,7 +1274,7 @@ static const struct net_device_ops ipgre
.ndo_start_xmit = ipgre_tunnel_xmit,
.ndo_do_ioctl = ipgre_tunnel_ioctl,
.ndo_change_mtu = ipgre_tunnel_change_mtu,
- .ndo_get_stats = ipgre_get_stats,
+ .ndo_get_stats64 = ipgre_get_stats64,
};
static void ipgre_dev_free(struct net_device *dev)
@@ -1507,7 +1528,7 @@ static const struct net_device_ops ipgre
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ipgre_tunnel_change_mtu,
- .ndo_get_stats = ipgre_get_stats,
+ .ndo_get_stats64 = ipgre_get_stats64,
};
static void ipgre_tap_setup(struct net_device *dev)
--- a/net/ipv4/ipip.c 2012-03-14 08:47:00.034845540 -0700
+++ b/net/ipv4/ipip.c 2012-04-11 11:46:20.338815164 -0700
@@ -144,30 +144,45 @@ static void ipip_dev_free(struct net_dev
/* often modified stats are per cpu, other are shared (netdev->stats) */
struct pcpu_tstats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long tx_bytes;
-} __attribute__((aligned(4*sizeof(unsigned long))));
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
-static struct net_device_stats *ipip_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *ipip_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
{
- struct pcpu_tstats sum = { 0 };
int i;
for_each_possible_cpu(i) {
const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&tstats->syncp);
+ rx_packets = tstats->rx_packets;
+ tx_packets = tstats->tx_packets;
+ rx_bytes = tstats->rx_bytes;
+ tx_bytes = tstats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ }
+
+ tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
+ tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
+ tot->tx_dropped = dev->stats.tx_dropped;
+ tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
+ tot->tx_errors = dev->stats.tx_errors;
+ tot->collisions = dev->stats.collisions;
- sum.rx_packets += tstats->rx_packets;
- sum.rx_bytes += tstats->rx_bytes;
- sum.tx_packets += tstats->tx_packets;
- sum.tx_bytes += tstats->tx_bytes;
- }
- dev->stats.rx_packets = sum.rx_packets;
- dev->stats.rx_bytes = sum.rx_bytes;
- dev->stats.tx_packets = sum.tx_packets;
- dev->stats.tx_bytes = sum.tx_bytes;
- return &dev->stats;
+ return tot;
}
static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
@@ -404,8 +419,10 @@ static int ipip_rcv(struct sk_buff *skb)
skb->pkt_type = PACKET_HOST;
tstats = this_cpu_ptr(tunnel->dev->tstats);
+ u64_stats_update_begin(&tstats->syncp);
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
+ u64_stats_update_end(&tstats->syncp);
__skb_tunnel_rx(skb, tunnel->dev);
@@ -730,7 +747,7 @@ static const struct net_device_ops ipip_
.ndo_start_xmit = ipip_tunnel_xmit,
.ndo_do_ioctl = ipip_tunnel_ioctl,
.ndo_change_mtu = ipip_tunnel_change_mtu,
- .ndo_get_stats = ipip_get_stats,
+ .ndo_get_stats64 = ipip_get_stats64,
};
static void ipip_dev_free(struct net_device *dev)
--- a/net/ipv6/sit.c 2012-04-09 11:18:09.685154426 -0700
+++ b/net/ipv6/sit.c 2012-04-11 11:46:20.338815164 -0700
@@ -87,31 +87,47 @@ struct sit_net {
/* often modified stats are per cpu, other are shared (netdev->stats) */
struct pcpu_tstats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long tx_bytes;
-} __attribute__((aligned(4*sizeof(unsigned long))));
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
-static struct net_device_stats *ipip6_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
{
- struct pcpu_tstats sum = { 0 };
int i;
for_each_possible_cpu(i) {
const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&tstats->syncp);
+ rx_packets = tstats->rx_packets;
+ tx_packets = tstats->tx_packets;
+ rx_bytes = tstats->rx_bytes;
+ tx_bytes = tstats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ }
+
+ tot->rx_errors = dev->stats.rx_errors;
+ tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
+ tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
+ tot->tx_dropped = dev->stats.tx_dropped;
+ tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
+ tot->tx_errors = dev->stats.tx_errors;
- sum.rx_packets += tstats->rx_packets;
- sum.rx_bytes += tstats->rx_bytes;
- sum.tx_packets += tstats->tx_packets;
- sum.tx_bytes += tstats->tx_bytes;
- }
- dev->stats.rx_packets = sum.rx_packets;
- dev->stats.rx_bytes = sum.rx_bytes;
- dev->stats.tx_packets = sum.tx_packets;
- dev->stats.tx_bytes = sum.tx_bytes;
- return &dev->stats;
+ return tot;
}
+
/*
* Must be invoked with rcu_read_lock
*/
@@ -1126,7 +1142,7 @@ static const struct net_device_ops ipip6
.ndo_start_xmit = ipip6_tunnel_xmit,
.ndo_do_ioctl = ipip6_tunnel_ioctl,
.ndo_change_mtu = ipip6_tunnel_change_mtu,
- .ndo_get_stats = ipip6_get_stats,
+ .ndo_get_stats64= ipip6_get_stats64,
};
static void ipip6_dev_free(struct net_device *dev)
^ permalink raw reply
* [PATCH 0/4] Tunneling related patches
From: Stephen Hemminger @ 2012-04-12 16:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Implement operational state and 64 bit stats on tunnels.
^ permalink raw reply
* [PATCH 3/4] sit: follow state of lower device
From: Stephen Hemminger @ 2012-04-12 16:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120412163115.076119065@vyatta.com>
[-- Attachment #1: sit-lowerup.patch --]
[-- Type: text/plain, Size: 2515 bytes --]
SIT tunnels like other layered devices should propogate
carrier and RFC2863 state from lower device to tunnel.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv6/sit.c 2012-04-12 08:31:05.249059443 -0700
+++ b/net/ipv6/sit.c 2012-04-12 08:34:44.093009537 -0700
@@ -284,6 +284,7 @@ static struct ip_tunnel *ipip6_tunnel_lo
dev_hold(dev);
ipip6_tunnel_link(sitn, nt);
+ linkwatch_fire_event(dev);
return nt;
failed_free:
@@ -901,6 +902,7 @@ static void ipip6_tunnel_bind_dev(struct
dev->mtu = tdev->mtu - sizeof(struct iphdr);
if (dev->mtu < IPV6_MIN_MTU)
dev->mtu = IPV6_MIN_MTU;
+ netif_stacked_transfer_operstate(tdev, dev);
}
dev->iflink = tunnel->parms.link;
}
@@ -1231,6 +1233,36 @@ static void __net_exit sit_destroy_tunne
}
}
+/* If lower device changes state, reflect that to the tunnel. */
+static int sit_notify(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
+ struct sit_net *sitn = net_generic(net, sit_net_id);
+ unsigned int prio, h;
+ struct ip_tunnel *t;
+
+ if (event == NETDEV_CHANGE)
+ return NOTIFY_DONE;
+
+ for (prio = 0; prio < 4; prio++)
+ for (h = 0; h < HASH_SIZE; h++) {
+ for (t = rtnl_dereference(sitn->tunnels[prio][h]);
+ t; t = rtnl_dereference(t->next)) {
+ if (dev->ifindex != t->dev->iflink)
+ continue;
+ netif_stacked_transfer_operstate(dev, t->dev);
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sit_notifier = {
+ .notifier_call = sit_notify,
+};
+
static int __net_init sit_init_net(struct net *net)
{
struct sit_net *sitn = net_generic(net, sit_net_id);
@@ -1293,6 +1325,7 @@ static struct pernet_operations sit_net_
static void __exit sit_cleanup(void)
{
+ unregister_netdevice_notifier(&sit_notifier);
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
unregister_pernet_device(&sit_net_ops);
@@ -1309,11 +1342,21 @@ static int __init sit_init(void)
if (err < 0)
return err;
err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
- if (err < 0) {
- unregister_pernet_device(&sit_net_ops);
- printk(KERN_INFO "sit init: Can't add protocol\n");
- }
+ if (err < 0)
+ goto xfrm4_failed;
+
+ err = register_netdevice_notifier(&sit_notifier);
+ if (err < 0)
+ goto notify_failed;
+
+out:
return err;
+
+notify_failed:
+ xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+xfrm4_failed:
+ unregister_pernet_device(&sit_net_ops);
+ goto out;
}
module_init(sit_init);
^ permalink raw reply
* [PATCH 2/4] ipgre: follow state of lower device
From: Stephen Hemminger @ 2012-04-12 16:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120412163115.076119065@vyatta.com>
[-- Attachment #1: ipgre-lowerup.patch --]
[-- Type: text/plain, Size: 2275 bytes --]
GRE tunnels like other layered devices should propogate
carrier and RFC2863 state from lower device to tunnel.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/ip_gre.c 2012-04-12 08:07:39.508107847 -0700
+++ b/net/ipv4/ip_gre.c 2012-04-12 08:10:14.177499183 -0700
@@ -991,6 +991,7 @@ static int ipgre_tunnel_bind_dev(struct
if (tdev) {
hlen = tdev->hard_header_len + tdev->needed_headroom;
mtu = tdev->mtu;
+ netif_stacked_transfer_operstate(tdev, dev);
}
dev->iflink = tunnel->parms.link;
@@ -1575,6 +1576,7 @@ static int ipgre_newlink(struct net *src
dev_hold(dev);
ipgre_tunnel_link(ign, nt);
+ linkwatch_fire_event(dev);
out:
return err;
@@ -1732,6 +1734,36 @@ static struct rtnl_link_ops ipgre_tap_op
.fill_info = ipgre_fill_info,
};
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipgre_notify(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
+ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+ unsigned int prio, h;
+ struct ip_tunnel *t;
+
+ if (event == NETDEV_CHANGE)
+ return NOTIFY_DONE;
+
+ for (prio = 0; prio < 4; prio++)
+ for (h = 0; h < HASH_SIZE; h++) {
+ for (t = rtnl_dereference(ign->tunnels[prio][h]);
+ t; t = rtnl_dereference(t->next)) {
+ if (dev->ifindex != t->dev->iflink)
+ continue;
+ netif_stacked_transfer_operstate(dev, t->dev);
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ipgre_notifier = {
+ .notifier_call = ipgre_notify,
+};
+
/*
* And now the modules code and kernel interface.
*/
@@ -1760,9 +1792,15 @@ static int __init ipgre_init(void)
if (err < 0)
goto tap_ops_failed;
+ err = register_netdevice_notifier(&ipgre_notifier);
+ if (err < 0)
+ goto notify_failed;
+
out:
return err;
+notify_failed:
+ rtnl_link_unregister(&ipgre_tap_ops);
tap_ops_failed:
rtnl_link_unregister(&ipgre_link_ops);
rtnl_link_failed:
@@ -1774,6 +1812,7 @@ add_proto_failed:
static void __exit ipgre_fini(void)
{
+ unregister_netdevice_notifier(&ipgre_notifier);
rtnl_link_unregister(&ipgre_tap_ops);
rtnl_link_unregister(&ipgre_link_ops);
if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
^ permalink raw reply
* [PATCH v3] mac80211: Support on-channel scan option.
From: greearb @ 2012-04-12 16:38 UTC (permalink / raw)
To: linux-wireless; +Cc: netdev, Ben Greear
From: Ben Greear <greearb@candelatech.com>
This based on an idea posted by Stanislaw Gruszka,
though I accept full blame for the implementation!
This is compile-tested only at this point.
The idea is to let users scan on the current operating
channel without interrupting normal traffic more than
absolutely necessary (changing power level might reset
some hardware, for instance).
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v3: Fix up formatting as requested.
Add call to notify driver scan is starting
(Scan complete logic notifies scan is complete already.)
:100644 100644 4be11ea... f71a8d6... M net/mac80211/ieee80211_i.h
:100644 100644 ac79d5e... b70f7f0... M net/mac80211/main.c
:100644 100644 54a0491... dd2fbec... M net/mac80211/rx.c
:100644 100644 c70e176... c33afa8... M net/mac80211/scan.c
net/mac80211/ieee80211_i.h | 3 +
net/mac80211/main.c | 4 +-
net/mac80211/rx.c | 2 +
net/mac80211/scan.c | 89 +++++++++++++++++++++++++++++++-------------
4 files changed, 71 insertions(+), 27 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4be11ea..f71a8d6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -803,6 +803,8 @@ struct tpt_led_trigger {
* well be on the operating channel
* @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
* determine if we are on the operating channel or not
+ * @SCAN_ONCHANNEL_SCANNING: Do a software scan on only the current operating
+ * channel. This should not interrupt normal traffic.
* @SCAN_COMPLETED: Set for our scan work function when the driver reported
* that the scan completed.
* @SCAN_ABORTED: Set for our scan work function when the driver reported
@@ -811,6 +813,7 @@ struct tpt_led_trigger {
enum {
SCAN_SW_SCANNING,
SCAN_HW_SCANNING,
+ SCAN_ONCHANNEL_SCANNING,
SCAN_COMPLETED,
SCAN_ABORTED,
};
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ac79d5e..b70f7f0 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -47,7 +47,8 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
if (atomic_read(&local->iff_allmultis))
new_flags |= FIF_ALLMULTI;
- if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning))
+ if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning))
new_flags |= FIF_BCN_PRBRESP_PROMISC;
if (local->fif_probe_req || local->probe_req_reg)
@@ -148,6 +149,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
}
if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
test_bit(SCAN_HW_SCANNING, &local->scanning))
power = chan->max_power;
else
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 54a0491..dd2fbec 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -425,6 +425,7 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
local->sched_scanning)
return ieee80211_scan_rx(rx->sdata, skb);
@@ -2915,6 +2916,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
local->dot11ReceivedFragmentCount++;
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
test_bit(SCAN_SW_SCANNING, &local->scanning)))
status->rx_flags |= IEEE80211_RX_IN_SCAN;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index c70e176..c33afa8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -387,6 +387,29 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
return 0;
}
+static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int i;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+ enum ieee80211_band band = local->hw.conf.channel->band;
+
+ for (i = 0; i < local->scan_req->n_ssids; i++)
+ ieee80211_send_probe_req(
+ sdata, NULL,
+ local->scan_req->ssids[i].ssid,
+ local->scan_req->ssids[i].ssid_len,
+ local->scan_req->ie, local->scan_req->ie_len,
+ local->scan_req->rates[band], false,
+ local->scan_req->no_cck);
+
+ /*
+ * After sending probe requests, wait for probe responses
+ * on the channel.
+ */
+ *next_delay = IEEE80211_CHANNEL_TIME;
+ local->next_scan_state = SCAN_DECISION;
+}
static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req)
@@ -438,10 +461,42 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
local->scan_req = req;
local->scan_sdata = sdata;
- if (local->ops->hw_scan)
+ if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
- else
+ } else if ((req->n_channels == 1) &&
+ (req->channels[0]->center_freq ==
+ local->hw.conf.channel->center_freq)) {
+ /* If we are scanning only on the current channel, then
+ * we do not need to stop normal activities
+ */
+ unsigned long next_delay;
+
+ __set_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
+ ieee80211_recalc_idle(local);
+ /* Notify driver scan is starting, keep order of operations
+ * same as normal software scan, in case that matters. */
+ drv_sw_scan_start(local);
+ ieee80211_configure_filter(local); /* accept probe-responses */
+ /* We need to ensure power level is at max for scanning. */
+ ieee80211_hw_config(local, 0);
+
+ if ((req->channels[0]->flags &
+ IEEE80211_CHAN_PASSIVE_SCAN) ||
+ !local->scan_req->n_ssids) {
+ next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ } else {
+ ieee80211_scan_state_send_probe(local, &next_delay);
+ next_delay = IEEE80211_CHANNEL_TIME;
+ }
+
+ /* Now, just wait a bit and we are all done! */
+ ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
+ next_delay);
+ return 0;
+ } else {
+ /* Do normal software scan */
__set_bit(SCAN_SW_SCANNING, &local->scanning);
+ }
ieee80211_recalc_idle(local);
@@ -598,30 +653,6 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
local->next_scan_state = SCAN_SEND_PROBE;
}
-static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
- unsigned long *next_delay)
-{
- int i;
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
- enum ieee80211_band band = local->hw.conf.channel->band;
-
- for (i = 0; i < local->scan_req->n_ssids; i++)
- ieee80211_send_probe_req(
- sdata, NULL,
- local->scan_req->ssids[i].ssid,
- local->scan_req->ssids[i].ssid_len,
- local->scan_req->ie, local->scan_req->ie_len,
- local->scan_req->rates[band], false,
- local->scan_req->no_cck);
-
- /*
- * After sending probe requests, wait for probe responses
- * on the channel.
- */
- *next_delay = IEEE80211_CHANNEL_TIME;
- local->next_scan_state = SCAN_DECISION;
-}
-
static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
unsigned long *next_delay)
{
@@ -672,6 +703,12 @@ void ieee80211_scan_work(struct work_struct *work)
sdata = local->scan_sdata;
+ /* When scanning on-channel, the first-callback means completed. */
+ if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
+ aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
+ goto out_complete;
+ }
+
if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
goto out_complete;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 3/5] mac80211: Framework to get wifi-driver stats via ethtool.
From: greearb @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless; +Cc: netdev, Ben Greear
In-Reply-To: <1334248375-22967-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
This adds hooks to call into the driver to get additional
stats for the ethtool API.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 32cd517... af61f3a... M include/net/mac80211.h
:100644 100644 420b6eb... b37fb0d... M net/mac80211/cfg.c
:100644 100644 4a0e559... 6d33a0c... M net/mac80211/driver-ops.h
:100644 100644 7c0754b... 6de00b2... M net/mac80211/driver-trace.h
include/net/mac80211.h | 17 +++++++++++++++++
net/mac80211/cfg.c | 19 ++++++++++++++++---
net/mac80211/driver-ops.h | 37 +++++++++++++++++++++++++++++++++++++
net/mac80211/driver-trace.h | 15 +++++++++++++++
4 files changed, 85 insertions(+), 3 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 32cd517..af61f3a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2223,6 +2223,14 @@ enum ieee80211_rate_control_changed {
* The @tids parameter is a bitmap and tells the driver which TIDs the
* frames will be on; it will at most have two bits set.
* This callback must be atomic.
+ *
+ * @get_et_sset_count: Ethtool API to get string-set count.
+ *
+ * @get_et_stats: Ethtool API to get a set of u64 stats.
+ *
+ * @get_et_strings: Ethtool API to get a set of strings to describe stats
+ * and perhaps other supported types of ethtool data-sets.
+ *
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2353,6 +2361,15 @@ struct ieee80211_ops {
u16 tids, int num_frames,
enum ieee80211_frame_release_type reason,
bool more_data);
+
+ int (*get_et_sset_count)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, int sset);
+ void (*get_et_stats)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ethtool_stats *stats, u64 *data);
+ void (*get_et_strings)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u32 sset, u8 *data);
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 420b6eb..b37fb0d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -125,10 +125,17 @@ static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
struct net_device *dev,
int sset)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ int rv = 0;
+
if (sset == ETH_SS_STATS)
- return STA_STATS_LEN;
+ rv += STA_STATS_LEN;
- return -EOPNOTSUPP;
+ rv += drv_get_et_sset_count(sdata, sset);
+
+ if (rv == 0)
+ return -EOPNOTSUPP;
+ return rv;
}
static void ieee80211_get_et_stats(struct wiphy *wiphy,
@@ -167,16 +174,22 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
BUG_ON(i != STA_STATS_LEN);
}
rcu_read_unlock();
+
+ drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
}
static void ieee80211_get_et_strings(struct wiphy *wiphy,
struct net_device *dev,
u32 sset, u8 *data)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ int sz_sta_stats = 0;
+
if (sset == ETH_SS_STATS) {
- int sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
+ sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
}
+ drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4a0e559..6d33a0c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -35,6 +35,43 @@ static inline void drv_tx_frags(struct ieee80211_local *local,
local->ops->tx_frags(&local->hw, vif, sta, skbs);
}
+static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
+ u32 sset, u8 *data)
+{
+ struct ieee80211_local *local = sdata->local;
+ if (local->ops->get_et_strings) {
+ trace_drv_get_et_strings(local, sset);
+ local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
+ trace_drv_return_void(local);
+ }
+}
+
+static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct ieee80211_local *local = sdata->local;
+ if (local->ops->get_et_stats) {
+ trace_drv_get_et_stats(local);
+ local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
+ trace_drv_return_void(local);
+ }
+}
+
+static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
+ int sset)
+{
+ struct ieee80211_local *local = sdata->local;
+ int rv = 0;
+ if (local->ops->get_et_sset_count) {
+ trace_drv_get_et_sset_count(local, sset);
+ rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
+ sset);
+ trace_drv_return_int(local, rv);
+ }
+ return rv;
+}
+
static inline int drv_start(struct ieee80211_local *local)
{
int ret;
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 7c0754b..6de00b2 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -161,6 +161,21 @@ DEFINE_EVENT(local_only_evt, drv_start,
TP_ARGS(local)
);
+DEFINE_EVENT(local_u32_evt, drv_get_et_strings,
+ TP_PROTO(struct ieee80211_local *local, u32 sset),
+ TP_ARGS(local, sset)
+);
+
+DEFINE_EVENT(local_u32_evt, drv_get_et_sset_count,
+ TP_PROTO(struct ieee80211_local *local, u32 sset),
+ TP_ARGS(local, sset)
+);
+
+DEFINE_EVENT(local_only_evt, drv_get_et_stats,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
+);
+
DEFINE_EVENT(local_only_evt, drv_suspend,
TP_PROTO(struct ieee80211_local *local),
TP_ARGS(local)
--
1.7.3.4
^ permalink raw reply related
* [PATCH 5/5] mac80211: Add sta_state to ethtool stats.
From: greearb @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless; +Cc: netdev, Ben Greear
In-Reply-To: <1334248375-22967-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Helps to know how the station is doing in it's association
attempt.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 99e3597... 8375168... M net/mac80211/cfg.c
net/mac80211/cfg.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 99e3597..8375168 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -117,7 +117,7 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
"rx_duplicates", "rx_fragments", "rx_dropped",
"tx_packets", "tx_bytes", "tx_fragments",
"tx_filtered", "tx_retry_failed", "tx_retries",
- "beacon_loss", "txrate", "rxrate", "signal",
+ "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
"channel", "noise", "ch_time", "ch_time_busy",
"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
};
@@ -533,10 +533,12 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
data[i++] += sta->beacon_loss_count;
if (!do_once) {
- i += 3;
+ i += 4;
goto after_once;
}
+ data[i++] = sta->sta_state;
+
do_once = false;
sinfo.filled = 0;
sta_set_sinfo(sta, &sinfo);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 2/5] mac80211: Support getting sta_info stats via ethtool.
From: greearb @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless; +Cc: netdev, Ben Greear
In-Reply-To: <1334248375-22967-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
This lets ethtool print out stats related to stations
connected to the interface. Does not yet get stats
from the underlying driver.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 3557354... 420b6eb... M net/mac80211/cfg.c
net/mac80211/cfg.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3557354..420b6eb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -112,6 +112,74 @@ static int ieee80211_set_noack_map(struct wiphy *wiphy,
return 0;
}
+static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
+ "rx_packets", "rx_bytes", "wep_weak_iv_count",
+ "rx_duplicates", "rx_fragments", "rx_dropped",
+ "tx_packets", "tx_bytes", "tx_fragments",
+ "tx_filtered", "tx_retry_failed", "tx_retries",
+ "beacon_loss"
+};
+#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
+
+static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
+ struct net_device *dev,
+ int sset)
+{
+ if (sset == ETH_SS_STATS)
+ return STA_STATS_LEN;
+
+ return -EOPNOTSUPP;
+}
+
+static void ieee80211_get_et_stats(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+ struct ieee80211_local *local = sdata->local;
+
+ memset(data, 0, sizeof(u64) * STA_STATS_LEN);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ int i = 0;
+
+ /* Make sure this station belongs to the proper dev */
+ if (sta->sdata->dev != dev)
+ continue;
+
+ data[i++] += sta->rx_packets;
+ data[i++] += sta->rx_bytes;
+ data[i++] += sta->wep_weak_iv_count;
+ data[i++] += sta->num_duplicates;
+ data[i++] += sta->rx_fragments;
+ data[i++] += sta->rx_dropped;
+
+ data[i++] += sta->tx_packets;
+ data[i++] += sta->tx_bytes;
+ data[i++] += sta->tx_fragments;
+ data[i++] += sta->tx_filtered_count;
+ data[i++] += sta->tx_retry_failed;
+ data[i++] += sta->tx_retry_count;
+ data[i++] += sta->beacon_loss_count;
+ BUG_ON(i != STA_STATS_LEN);
+ }
+ rcu_read_unlock();
+}
+
+static void ieee80211_get_et_strings(struct wiphy *wiphy,
+ struct net_device *dev,
+ u32 sset, u8 *data)
+{
+ if (sset == ETH_SS_STATS) {
+ int sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
+ memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
+ }
+}
+
+
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
@@ -2773,4 +2841,7 @@ struct cfg80211_ops mac80211_config_ops = {
#ifdef CONFIG_PM
.set_wakeup = ieee80211_set_wakeup,
#endif
+ .get_et_sset_count = ieee80211_get_et_sset_count,
+ .get_et_stats = ieee80211_get_et_stats,
+ .get_et_strings = ieee80211_get_et_strings,
};
--
1.7.3.4
^ permalink raw reply related
* [PATCH 1/5] cfg80211: Add framework to support ethtool stats.
From: greearb @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless; +Cc: netdev, Ben Greear
In-Reply-To: <1334248375-22967-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 a587867... a3a635c... M include/net/cfg80211.h
:100644 100644 9bde4d1... 7eecdf4... M net/wireless/ethtool.c
include/net/cfg80211.h | 17 +++++++++++++++++
net/wireless/ethtool.c | 29 +++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a587867..a3a635c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1514,6 +1514,16 @@ struct cfg80211_gtk_rekey_data {
* later passes to cfg80211_probe_status().
*
* @set_noack_map: Set the NoAck Map for the TIDs.
+ *
+ * @get_et_sset_count: Ethtool API to get string-set count.
+ * See @ethtool_ops.get_sset_count
+ *
+ * @get_et_stats: Ethtool API to get a set of u64 stats.
+ * See @ethtool_ops.get_ethtool_stats
+ *
+ * @get_et_strings: Ethtool API to get a set of strings to describe stats
+ * and perhaps other supported types of ethtool data-sets.
+ * See @ethtool_ops.get_strings
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1711,6 +1721,13 @@ struct cfg80211_ops {
u16 noack_map);
struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
+
+ int (*get_et_sset_count)(struct wiphy *wiphy,
+ struct net_device *dev, int sset);
+ void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data);
+ void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
+ u32 sset, u8 *data);
};
/*
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index 9bde4d1..7eecdf4 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -68,6 +68,32 @@ static int cfg80211_set_ringparam(struct net_device *dev,
return -ENOTSUPP;
}
+static int cfg80211_get_sset_count(struct net_device *dev, int sset)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ if (rdev->ops->get_et_sset_count)
+ return rdev->ops->get_et_sset_count(wdev->wiphy, dev, sset);
+ return -EOPNOTSUPP;
+}
+
+static void cfg80211_get_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ if (rdev->ops->get_et_stats)
+ rdev->ops->get_et_stats(wdev->wiphy, dev, stats, data);
+}
+
+static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ if (rdev->ops->get_et_strings)
+ rdev->ops->get_et_strings(wdev->wiphy, dev, sset, data);
+}
+
const struct ethtool_ops cfg80211_ethtool_ops = {
.get_drvinfo = cfg80211_get_drvinfo,
.get_regs_len = cfg80211_get_regs_len,
@@ -75,4 +101,7 @@ const struct ethtool_ops cfg80211_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_ringparam = cfg80211_get_ringparam,
.set_ringparam = cfg80211_set_ringparam,
+ .get_strings = cfg80211_get_strings,
+ .get_ethtool_stats = cfg80211_get_stats,
+ .get_sset_count = cfg80211_get_sset_count,
};
--
1.7.3.4
^ permalink raw reply related
* [PATCH 4/5] mac80211: Add more ethtools stats: survey, rates, etc
From: greearb-my8/4N5VtI7c+919tysfdA @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Ben Greear
In-Reply-To: <1334248375-22967-1-git-send-email-greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
From: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
The signal and noise are forced to be positive since ethtool
deals in unsigned 64-bit values and this number should be human
readable. This gives easy access to some of the data formerly
exposed in the deprecated /proc/net/wireless file.
Signed-off-by: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
---
:100644 100644 b37fb0d... 99e3597... M net/mac80211/cfg.c
net/mac80211/cfg.c | 155 ++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 114 insertions(+), 41 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b37fb0d..99e3597 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -117,7 +117,9 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
"rx_duplicates", "rx_fragments", "rx_dropped",
"tx_packets", "tx_bytes", "tx_fragments",
"tx_filtered", "tx_retry_failed", "tx_retries",
- "beacon_loss"
+ "beacon_loss", "txrate", "rxrate", "signal",
+ "channel", "noise", "ch_time", "ch_time_busy",
+ "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
};
#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
@@ -138,46 +140,6 @@ static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
return rv;
}
-static void ieee80211_get_et_stats(struct wiphy *wiphy,
- struct net_device *dev,
- struct ethtool_stats *stats,
- u64 *data)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sta_info *sta;
- struct ieee80211_local *local = sdata->local;
-
- memset(data, 0, sizeof(u64) * STA_STATS_LEN);
-
- rcu_read_lock();
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
- int i = 0;
-
- /* Make sure this station belongs to the proper dev */
- if (sta->sdata->dev != dev)
- continue;
-
- data[i++] += sta->rx_packets;
- data[i++] += sta->rx_bytes;
- data[i++] += sta->wep_weak_iv_count;
- data[i++] += sta->num_duplicates;
- data[i++] += sta->rx_fragments;
- data[i++] += sta->rx_dropped;
-
- data[i++] += sta->tx_packets;
- data[i++] += sta->tx_bytes;
- data[i++] += sta->tx_fragments;
- data[i++] += sta->tx_filtered_count;
- data[i++] += sta->tx_retry_failed;
- data[i++] += sta->tx_retry_count;
- data[i++] += sta->beacon_loss_count;
- BUG_ON(i != STA_STATS_LEN);
- }
- rcu_read_unlock();
-
- drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
-}
-
static void ieee80211_get_et_strings(struct wiphy *wiphy,
struct net_device *dev,
u32 sset, u8 *data)
@@ -531,6 +493,117 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
}
+static void ieee80211_get_et_stats(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+ struct ieee80211_local *local = sdata->local;
+ struct station_info sinfo;
+ struct survey_info survey;
+ bool do_once = true;
+ int i;
+#define STA_STATS_SURVEY_LEN 7
+
+ memset(data, 0, sizeof(u64) * STA_STATS_LEN);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ i = 0;
+
+ /* Make sure this station belongs to the proper dev */
+ if (sta->sdata->dev != dev)
+ continue;
+
+ data[i++] += sta->rx_packets;
+ data[i++] += sta->rx_bytes;
+ data[i++] += sta->wep_weak_iv_count;
+ data[i++] += sta->num_duplicates;
+ data[i++] += sta->rx_fragments;
+ data[i++] += sta->rx_dropped;
+
+ data[i++] += sta->tx_packets;
+ data[i++] += sta->tx_bytes;
+ data[i++] += sta->tx_fragments;
+ data[i++] += sta->tx_filtered_count;
+ data[i++] += sta->tx_retry_failed;
+ data[i++] += sta->tx_retry_count;
+ data[i++] += sta->beacon_loss_count;
+
+ if (!do_once) {
+ i += 3;
+ goto after_once;
+ }
+
+ do_once = false;
+ sinfo.filled = 0;
+ sta_set_sinfo(sta, &sinfo);
+
+ if (sinfo.filled | STATION_INFO_TX_BITRATE)
+ data[i] = 100000 *
+ cfg80211_calculate_bitrate(&sinfo.txrate);
+ i++;
+ if (sinfo.filled | STATION_INFO_RX_BITRATE)
+ data[i] = 100000 *
+ cfg80211_calculate_bitrate(&sinfo.rxrate);
+ i++;
+
+ if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
+ data[i] = abs(sinfo.signal_avg);
+ i++;
+
+after_once:
+ if (WARN_ON(i != (STA_STATS_LEN - STA_STATS_SURVEY_LEN))) {
+ rcu_read_unlock();
+ return;
+ }
+ }
+
+ i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
+ /* Get survey stats for current channel only */
+ survey.filled = 0;
+ if (drv_get_survey(local, 0, &survey) != 0) {
+ survey.filled = 0;
+ data[i++] = 0;
+ } else {
+ data[i++] = survey.channel->center_freq;
+ }
+
+ if (survey.filled & SURVEY_INFO_NOISE_DBM)
+ data[i++] = abs(survey.noise);
+ else
+ data[i++] = -1LL;
+ if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
+ data[i++] = survey.channel_time;
+ else
+ data[i++] = -1LL;
+ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
+ data[i++] = survey.channel_time_busy;
+ else
+ data[i++] = -1LL;
+ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
+ data[i++] = survey.channel_time_ext_busy;
+ else
+ data[i++] = -1LL;
+ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
+ data[i++] = survey.channel_time_rx;
+ else
+ data[i++] = -1LL;
+ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
+ data[i++] = survey.channel_time_tx;
+ else
+ data[i++] = -1LL;
+
+ rcu_read_unlock();
+
+ if (WARN_ON(i != STA_STATS_LEN))
+ return;
+
+ drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
+}
+
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo)
--
1.7.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/5] Add ethtool stats support for Wireless Devices.
From: greearb-my8/4N5VtI7c+919tysfdA @ 2012-04-12 16:32 UTC (permalink / raw)
To: linux-wireless-u79uwXL29TY76Z2rM5mHXA
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Ben Greear
From: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
This enables ethtool stats for mac80211 devices. It also
adds hooks to call down into mac80211 drivers for additional
stats. Patches to enable this hook in ath9k will be posted
in a different series.
There was a review question about how to make the ethtool
strings line up with the data in a less error prone manner.
This patch series does NOT address that. I think it may
be more work than it's worth to try to do this, but we
can always retro-fit such behaviour later if desired.
Many drivers have this issue, so perhaps some support
code in the ethtool core is the way to go.
Ben Greear (5):
cfg80211: Add framework to support ethtool stats.
mac80211: Support getting sta_info stats via ethtool.
mac80211: Framework to get wifi-driver stats via ethtool.
mac80211: Add more ethtools stats: survey, rates, etc
mac80211: Add sta_state to ethtool stats.
include/net/cfg80211.h | 17 +++++
include/net/mac80211.h | 17 +++++
net/mac80211/cfg.c | 159 +++++++++++++++++++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 37 ++++++++++
net/mac80211/driver-trace.h | 15 ++++
net/wireless/ethtool.c | 29 ++++++++
6 files changed, 274 insertions(+), 0 deletions(-)
--
1.7.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] net: smsc911x: fix RX FIFO fastforwarding when dropping packets
From: Eric Dumazet @ 2012-04-12 16:08 UTC (permalink / raw)
To: Will Deacon; +Cc: netdev@vger.kernel.org, Steve Glendinning
In-Reply-To: <20120412155409.GA28204@mudshark.cambridge.arm.com>
On Thu, 2012-04-12 at 16:54 +0100, Will Deacon wrote:
> Gotcha, so I can lose the pull too. Here's an updated patch with log, thanks
> for the help.
>
> Will
>
>
> Author: Will Deacon <will.deacon@arm.com>
> Date: Thu Apr 12 13:54:17 2012 +0100
>
> net: smsc911x: fix skb handling in receive path
>
> The SMSC911x driver resets the ->head, ->data and ->tail pointers in the
> skb on the reset path in order to avoid buffer overflow due to packet
> padding performed by the hardware.
>
> This patch fixes the receive path so that the skb pointers are fixed up
> after the data has been read from the device, The error path is also
> fixed to use number of words consistently and prevent erroneous FIFO
> fastforwarding when skipping over bad data.
>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
>
> diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
> index 4a69710..5aa2dbe 100644
> --- a/drivers/net/ethernet/smsc/smsc911x.c
> +++ b/drivers/net/ethernet/smsc/smsc911x.c
> @@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
>
> /* Quickly dumps bad packets */
> static void
> -smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
> +smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
> {
> - unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
> -
> if (likely(pktwords >= 4)) {
> unsigned int timeout = 500;
> unsigned int val;
> @@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
> continue;
> }
>
> - skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
> + skb = netdev_alloc_skb(dev, pktwords << 2);
> if (unlikely(!skb)) {
> SMSC_WARN(pdata, rx_err,
> "Unable to allocate skb for rx packet");
> @@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
> break;
> }
>
> - skb->data = skb->head;
> - skb_reset_tail_pointer(skb);
> + pdata->ops->rx_readfifo(pdata,
> + (unsigned int *)skb->data, pktwords);
>
> /* Align IP on 16B boundary */
> skb_reserve(skb, NET_IP_ALIGN);
> skb_put(skb, pktlength - 4);
> - pdata->ops->rx_readfifo(pdata,
> - (unsigned int *)skb->head, pktwords);
> skb->protocol = eth_type_trans(skb, dev);
> skb_checksum_none_assert(skb);
> netif_receive_skb(skb);
> @@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev)
> smsc911x_reg_write(pdata, FIFO_INT, temp);
>
> /* set RX Data offset to 2 bytes for alignment */
> - smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
> + smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
>
> /* enable NAPI polling before enabling RX interrupts */
> napi_enable(&pdata->napi);
Seems fine to me
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: [v11 PATCH 2/3] NETFILTER module xt_hmark, new target for HASH based fwmark
From: Pablo Neira Ayuso @ 2012-04-12 15:54 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: kaber, jengelh, netfilter-devel, netdev, hans
In-Reply-To: <1332417593-26232-3-git-send-email-hans.schillstrom@ericsson.com>
Hi Hans,
On Thu, Mar 22, 2012 at 12:59:52PM +0100, Hans Schillstrom wrote:
> The target allows you to create rules in the "raw" and "mangle" tables
> which alter the netfilter mark (nfmark) field within a given range.
> First a 32 bit hash value is generated then modulus by <limit> and
> finally an offset is added before it's written to nfmark.
> Prior to routing, the nfmark can influence the routing method (see
> "Use netfilter MARK value as routing key") and can also be used by
> other subsystems to change their behavior.
>
> man page
> HMARK
> This module does the same as MARK, i.e. set an fwmark, but the mark
> is based on a hash value. The hash is based on saddr, daddr, sport,
> dport and proto. The same mark will be produced independent of direction
> if no masks is set or the same masks is used for src and dest.
> The hash mark could be adjusted by modulus and finally an offset could
> be added, i.e the final mark will be within a range. ICMP error will use
> the the original message for hash calculation not the icmp it self.
>
> Note: IPv4 packets with nf_defrag_ipv4 loaded will be defragmented before they reach hmark,
> IPv6 nf_defrag is not implemented this way, hence fragmented ipv6 packets will reach hmark.
> Default behavior is to completely ignore any fragment if it reach hmark.
> --hmark-method L3 is fragment safe since neither ports or L4 protocol field is used.
> None of the parameters effect the packet it self only the calculated hash value.
>
> Parameters: Short hand methods
>
> --hmark-method L3
> Do not use L4 protocol field, ports or spi, only Layer 3 addresses,
> mask length of L3 addresses can still be used. Fragment or not
> does not matter in this case since only L3 address can be used in
> calc. of hash value.
>
> --hmark-method L3-4 (Default)
> Include L4 in calculation. of hash value i.e. all masks below are valid.
> Fragments will be ignored. (i.e no hash value produced)
>
> For all masks default is all "1:s", to disable a field use mask 0
>
> --hmark-src-mask length
> The length of the mask to AND the source address with (saddr & value).
>
> --hmark-dst-mask length
> The length of the mask to AND the dest. address with (daddr & value).
>
> --hmark-sport-mask value
> A 16 bit value to AND the src port with (sport & value).
>
> --hmark-dport-mask value
> A 16 bit value to AND the dest port with (dport & value).
>
> --hmark-sport-set value
> A 16 bit value to OR the src port with (sport | value).
>
> --hmark-dport-set value
> A 16 bit value to OR the dest port with (dport | value).
>
> --hmark-spi-mask value
> Value to AND the spi field with (spi & value) valid for proto esp or ah.
>
> --hmark-spi-set value
> Value to OR the spi field with (spi | value) valid for proto esp or ah.
>
> --hmark-proto-mask value
> An 8 bit value to AND the L4 proto field with (proto & value).
>
> --hmark-ct
> When flag is set, conntrack data should be used. Useful when NAT internal
> addressed should be used in calculation. Be careful when using DNAT
> since mangle table is handled before nat table. I.e it will not work as
> expected to put HMARK in table mangle and PREROUTING chain. The initial
> packet will have it's hash based on the original address,
> while the rest of the flow will use the NAT:ed address.
>
> --hmark-rnd value
> A 32 bit initial value for hash calc, default is 0xc175a3b8.
>
> Final processing of the mark in order of execution.
>
> --hmark-mod value (must be > 0)
> The easiest way to describe this is: hash = hash mod <value>
>
> --hmark-offset value
> The easiest way to describe this is: hash = hash + <value>
>
> Examples:
>
> Default rule handles all TCP, UDP, SCTP, ESP & AH
>
> iptables -t mangle -A PREROUTING -m state --state NEW,ESTABLISHED,RELATED
> -j HMARK --hmark-offset 10000 --hmark-mod 10
>
> Handle SCTP and hash dest port only and produce a nfmark between 100-119.
>
> iptables -t mangle -A PREROUTING -p SCTP -j HMARK --src-mask 0 --dst-mask 0
> --sp-mask 0 --offset 100 --mod 20
>
> Fragment safe Layer 3 only, that keep a class C network flow together
>
> iptables -t mangle -A PREROUTING -j HMARK --method L3 --src-mask 24 --mod 20 --offset 100
>
> Rev 11
> Two comments changed
> Rev 10
> Even more simplified NAT handling just one switch --hmark-ct
> some renaming and some minor changes.
> Changes are based on Pablos review.
>
> Rev 9
> Simplified NAT selections, cleanup of comments, added checkentry()
> change of #ifdef to #if IS_ENABLED and dependency.
> Some minor formating.
> Most changes are based on Pablos review.
>
> Rev 8
> method L3 / L3-4 added i.e. Fragment handling changed to
> don't handle in "method L3-4"
> Syntax change in user mode more NF compatible.
> Most changes are based on Pablos review.
>
> Rev 7
> IPv6 descending into icmp error hdr didn't work as expected
> with ipv6_find_hdr() Now it works as expected.
>
> Rev 6
> Compile options with or without conntrack fixed.
> __ipv6_find_hdr() replaced by ipv6_find_hdr()
>
> Rev 5
> IPv6 rewritten uses __ipv6_find_hdr() (P. Mc Hardy)
> Full mask and address used for IPv6 smask and dmask (J.Engelhart)
> Changes due to comments by Pablo Neira Ayuso and Eric Dumazet
> i.e uses of skb_header_pointer() and Null check of info->hmod
> Man page changes
>
> Rev 4
> different targets for IPv4 and IPv6
> Changes based on review by Pablo.
>
> Rev 3
> Support added to SCTP for IPv6
> Rev 2
> IPv6 header scan changed to follow RFC 2640
> IPv4 icmp echo fragmented does now use proto as ipv6
> IPv6 pskb_may_pull() check is done in every time in header loop.
> IPv4 nat support added.
> default added in IPv6 loop and null check of hp
>
> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> ---
> include/linux/netfilter/xt_HMARK.h | 62 +++++++
> net/netfilter/Kconfig | 18 ++
> net/netfilter/Makefile | 1 +
> net/netfilter/xt_HMARK.c | 319 ++++++++++++++++++++++++++++++++++++
> 4 files changed, 400 insertions(+), 0 deletions(-)
> create mode 100644 include/linux/netfilter/xt_HMARK.h
> create mode 100644 net/netfilter/xt_HMARK.c
>
> diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h
> new file mode 100644
> index 0000000..cdf4a8f
> --- /dev/null
> +++ b/include/linux/netfilter/xt_HMARK.h
> @@ -0,0 +1,62 @@
> +#ifndef XT_HMARK_H_
> +#define XT_HMARK_H_
> +
> +#include <linux/types.h>
> +
> +enum {
> + XT_HMARK_NONE,
> + XT_HMARK_SADR_AND,
> + XT_HMARK_DADR_AND,
> + XT_HMARK_SPI_AND,
> + XT_HMARK_SPI_OR,
> + XT_HMARK_SPORT_AND,
> + XT_HMARK_DPORT_AND,
> + XT_HMARK_SPORT_OR,
> + XT_HMARK_DPORT_OR,
> + XT_HMARK_PROTO_AND,
> + XT_HMARK_RND,
> + XT_HMARK_MODULUS,
> + XT_HMARK_OFFSET,
> + XT_HMARK_CT,
> + XT_HMARK_METHOD_L3,
> + XT_HMARK_METHOD_L3_4,
> + XT_F_HMARK_SADR_AND = 1 << XT_HMARK_SADR_AND,
> + XT_F_HMARK_DADR_AND = 1 << XT_HMARK_DADR_AND,
> + XT_F_HMARK_SPI_AND = 1 << XT_HMARK_SPI_AND,
> + XT_F_HMARK_SPI_OR = 1 << XT_HMARK_SPI_OR,
> + XT_F_HMARK_SPORT_AND = 1 << XT_HMARK_SPORT_AND,
> + XT_F_HMARK_DPORT_AND = 1 << XT_HMARK_DPORT_AND,
> + XT_F_HMARK_SPORT_OR = 1 << XT_HMARK_SPORT_OR,
> + XT_F_HMARK_DPORT_OR = 1 << XT_HMARK_DPORT_OR,
> + XT_F_HMARK_PROTO_AND = 1 << XT_HMARK_PROTO_AND,
> + XT_F_HMARK_RND = 1 << XT_HMARK_RND,
> + XT_F_HMARK_MODULUS = 1 << XT_HMARK_MODULUS,
> + XT_F_HMARK_OFFSET = 1 << XT_HMARK_OFFSET,
> + XT_F_HMARK_CT = 1 << XT_HMARK_CT,
> + XT_F_HMARK_METHOD_L3 = 1 << XT_HMARK_METHOD_L3,
> + XT_F_HMARK_METHOD_L3_4 = 1 << XT_HMARK_METHOD_L3_4,
> +};
> +
> +union hmark_ports {
> + struct {
> + __u16 src;
> + __u16 dst;
> + } p16;
> + __u32 v32;
> +};
> +
> +struct xt_hmark_info {
> + union nf_inet_addr src_mask; /* Source address mask */
> + union nf_inet_addr dst_mask; /* Dest address mask */
> + union hmark_ports port_mask;
> + union hmark_ports port_set;
> + __u32 spi_mask;
> + __u32 spi_set;
> + __u32 flags; /* Print out only */
> + __u16 proto_mask; /* L4 Proto mask */
> + __u32 hashrnd;
> + __u32 hmodulus; /* Modulus */
> + __u32 hoffset; /* Offset */
> +};
> +
> +#endif /* XT_HMARK_H_ */
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index f8ac4ef..a775804 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -488,6 +488,24 @@ config NETFILTER_XT_TARGET_HL
> since you can easily create immortal packets that loop
> forever on the network.
>
> +config NETFILTER_XT_TARGET_HMARK
> + tristate '"HMARK" target support'
> + depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
do we really need this dependency above?
> + depends on NETFILTER_ADVANCED
> + ---help---
> + This option adds the "HMARK" target.
> +
> + The target allows you to create rules in the "raw" and "mangle" tables
> + which alter the netfilter mark (nfmark) field within a given range.
> + First a 32 bit hash value is generated then modulus by <limit> and
> + finally an offset is added before it's written to nfmark.
> +
> + Prior to routing, the nfmark can influence the routing method (see
> + "Use netfilter MARK value as routing key") and can also be used by
> + other subsystems to change their behavior.
> +
> + The mark match can also be used to match nfmark produced by this module.
> +
> config NETFILTER_XT_TARGET_IDLETIMER
> tristate "IDLETIMER target support"
> depends on NETFILTER_ADVANCED
> diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
> index 40f4c3d..2712ba0 100644
> --- a/net/netfilter/Makefile
> +++ b/net/netfilter/Makefile
> @@ -57,6 +57,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
> +obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
> diff --git a/net/netfilter/xt_HMARK.c b/net/netfilter/xt_HMARK.c
> new file mode 100644
> index 0000000..d90549d
> --- /dev/null
> +++ b/net/netfilter/xt_HMARK.c
> @@ -0,0 +1,319 @@
> +/*
> + * xt_hmark - Netfilter module to set mark as hash value
> + *
> + * (C) 2012 Hans Schillstrom <hans.schillstrom@ericsson.com>
> + *
> + *Description:
> + * This module calculates a hash value that can be modified by modulus
> + * and an offset, i.e. it is possible to produce a skb->mark within a range
> + * The hash value is based on a direction independent five tuple:
> + * src & dst addr src & dst ports and protocol.
> + * There is two distinct modes for hash calculation:
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/skbuff.h>
> +#include <net/ip.h>
> +#include <linux/icmp.h>
> +
> +#include <linux/netfilter/xt_HMARK.h>
> +#include <linux/netfilter/x_tables.h>
> +#include <net/netfilter/nf_conntrack.h>
> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> +#include <net/ipv6.h>
> +#include <linux/netfilter_ipv6/ip6_tables.h>
> +#endif
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Hans Schillstrom <hans.schillstrom@ericsson.com>");
> +MODULE_DESCRIPTION("Xtables: Packet range mark operations by Hash value");
> +MODULE_ALIAS("ipt_HMARK");
> +MODULE_ALIAS("ip6t_HMARK");
> +
> +/*
> + * ICMP, get header offset if icmp error
> + */
> +static int get_inner_hdr(struct sk_buff *skb, int iphsz, int *nhoff)
> +{
> + const struct icmphdr *icmph;
> + struct icmphdr _ih;
> +
> + /* Not enough header? */
> + icmph = skb_header_pointer(skb, *nhoff + iphsz, sizeof(_ih), &_ih);
> + if (icmph == NULL && icmph->type > NR_ICMP_TYPES)
> + return 0;
> +
> + /* Error message? */
> + if (icmph->type != ICMP_DEST_UNREACH &&
> + icmph->type != ICMP_SOURCE_QUENCH &&
> + icmph->type != ICMP_TIME_EXCEEDED &&
> + icmph->type != ICMP_PARAMETERPROB &&
> + icmph->type != ICMP_REDIRECT)
> + return 0;
> +
> + *nhoff += iphsz + sizeof(_ih);
> + return 1;
> +}
> +
> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> +/*
> + * Get ipv6 header offset if icmp error
> + */
> +static int get_inner6_hdr(struct sk_buff *skb, int *offset)
> +{
> + struct icmp6hdr *icmp6h, _ih6;
> +
> + icmp6h = skb_header_pointer(skb, *offset, sizeof(_ih6), &_ih6);
> + if (icmp6h == NULL)
> + return 0;
> +
> + if (icmp6h->icmp6_type && icmp6h->icmp6_type < 128) {
> + *offset += sizeof(struct icmp6hdr);
> + return 1;
> + }
> + return 0;
> +}
> +/*
> + * Calculate hash based fw-mark, on the five tuple if possible.
> + * special cases :
> + * - Fragments do not use ports not even on the first fragment,
> + * nf_defrag_ipv6.ko don't defrag for us like it do in ipv4.
> + * This might be changed in the future.
> + * - On ICMP errors the inner header will be used.
> + * - Tunnels no ports
> + * - ESP & AH uses SPI
> + * @returns XT_CONTINUE
> + */
> +static unsigned int
> +hmark_v6(struct sk_buff *skb, const struct xt_action_param *par)
> +{
> + const struct xt_hmark_info *info = par->targinfo;
> + struct ipv6hdr *ip6, _ip6;
> + int poff, flag = IP6T_FH_F_AUTH; /* Ports offset, find_hdr flags */
> + union hmark_ports uports;
> + u32 addr_src, addr_dst, hash, nhoffs = 0;
> + u16 fragoff = 0;
> + u8 nexthdr;
> +
> + ip6 = (struct ipv6hdr *) (skb->data + skb_network_offset(skb));
> + nexthdr = ipv6_find_hdr(skb, &nhoffs, -1, &fragoff, &flag);
> + if (nexthdr < 0)
> + return XT_CONTINUE;
> + /* No need to check for icmp errors on fragments */
> + if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
> + goto noicmp;
> + /* if an icmp error, use the inner header */
> + if (get_inner6_hdr(skb, &nhoffs)) {
> + ip6 = skb_header_pointer(skb, nhoffs, sizeof(_ip6), &_ip6);
> + if (!ip6)
> + return XT_CONTINUE;
> + /* Treat AH as ESP, use SPI nothing else. */
> + flag = IP6T_FH_F_AUTH;
> + nexthdr = ipv6_find_hdr(skb, &nhoffs, -1, &fragoff, &flag);
> + if (nexthdr < 0)
> + return XT_CONTINUE;
> + }
> +noicmp:
> + addr_src = (__force u32)
> + (ip6->saddr.s6_addr32[0] & info->src_mask.in6.s6_addr32[0]) ^
> + (ip6->saddr.s6_addr32[1] & info->src_mask.in6.s6_addr32[1]) ^
> + (ip6->saddr.s6_addr32[2] & info->src_mask.in6.s6_addr32[2]) ^
> + (ip6->saddr.s6_addr32[3] & info->src_mask.in6.s6_addr32[3]);
> + addr_dst = (__force u32)
> + (ip6->daddr.s6_addr32[0] & info->dst_mask.in6.s6_addr32[0]) ^
> + (ip6->daddr.s6_addr32[1] & info->dst_mask.in6.s6_addr32[1]) ^
> + (ip6->daddr.s6_addr32[2] & info->dst_mask.in6.s6_addr32[2]) ^
> + (ip6->daddr.s6_addr32[3] & info->dst_mask.in6.s6_addr32[3]);
> +
> + uports.v32 = 0;
> + if ((info->flags & XT_F_HMARK_METHOD_L3) ||
> + (nexthdr == IPPROTO_ICMPV6))
> + goto no_ports;
> + /* Is next header valid for port or SPI calculation ? */
> + poff = proto_ports_offset(nexthdr);
> + if ((flag & IP6T_FH_F_FRAG) || poff < 0)
> + return XT_CONTINUE;
> +
> + nhoffs += poff;
> + if (skb_copy_bits(skb, nhoffs, &uports, sizeof(uports)) < 0)
> + return XT_CONTINUE;
> +
> + if ((nexthdr == IPPROTO_ESP) || (nexthdr == IPPROTO_AH))
> + uports.v32 = (uports.v32 & info->spi_mask) | info->spi_set;
> + else {
> + uports.v32 = (uports.v32 & info->port_mask.v32) |
> + info->port_set.v32;
> + /* get a consistent hash (same value in any flow dirs.) */
> + if (uports.p16.dst < uports.p16.src)
> + swap(uports.p16.dst, uports.p16.src);
> + }
> +
> +no_ports:
> + nexthdr &= info->proto_mask;
> + /* get a consistent hash (same value in any flow direction) */
> + if (addr_dst < addr_src)
> + swap(addr_src, addr_dst);
> +
> + hash = jhash_3words(addr_src, addr_dst, uports.v32, info->hashrnd) ^ nexthdr;
> + skb->mark = (hash % info->hmodulus) + info->hoffset;
> + return XT_CONTINUE;
> +}
> +#endif
> +/*
> + * Calculate hash based fw-mark, on the five tuple if possible.
> + * special cases :
> + * - Fragments do not use ports not even on the first fragment,
> + * unless nf_defrag_xx.ko is used.
> + * - On ICMP errors the inner header will be used.
> + * - Tunnels no ports
> + * - ESP & AH uses SPI
> + * @returns XT_CONTINUE
> + */
> +static unsigned int
> +hmark_v4(struct sk_buff *skb, const struct xt_action_param *par)
> +{
> + const struct xt_hmark_info *info = par->targinfo;
> + struct iphdr *ip, _ip;
> + int nhoff, poff, frag = 0;
> + union hmark_ports uports;
> + u32 addr_src, addr_dst, hash;
> + u8 ip_proto;
> +
> + nhoff = skb_network_offset(skb);
> + ip = (struct iphdr *) (skb->data + nhoff);
> + if (ip->protocol == IPPROTO_ICMP) {
> + /* if an icmp error, calc hash on inner header */
> + if (get_inner_hdr(skb, ip->ihl * 4, &nhoff)) {
> + ip = skb_header_pointer(skb, nhoff, sizeof(_ip), &_ip);
> + if (!ip)
> + return XT_CONTINUE;
> + }
> + }
> +
> + ip_proto = ip->protocol;
> + if (ip->frag_off & htons(IP_MF | IP_OFFSET))
> + frag = 1;
> +
> + addr_src = (__force u32) ip->saddr;
> + addr_dst = (__force u32) ip->daddr;
> + uports.v32 = 0;
> +/* conntrack take care of ICMP relation */
> +#if IS_ENABLED(CONFIG_NF_CONNTRACK)
> + if (info->flags & XT_F_HMARK_CT) {
> + struct nf_conntrack_tuple *otuple;
> + struct nf_conntrack_tuple *rtuple;
> + enum ip_conntrack_info ctinfo;
> + struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
> +
> + if (!ct || nf_ct_is_untracked(ct))
> + return XT_CONTINUE;
> +
> + otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
> + rtuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
> +
> + addr_src = (__force u32)otuple->src.u3.in.s_addr;
> + uports.p16.src = otuple->src.u.udp.port;
> + addr_dst = (__force u32)rtuple->src.u3.in.s_addr;
> + uports.p16.dst = rtuple->src.u.udp.port;
> + }
There's an inconsistency here. No conntrack support for IPv6.
I'd suggest to split hmark_v4 into two functions by checking:
... hmark_v4(...)
{
if (info->flags & XT_F_HMARK_CT)
ret = hmark_tg_ct_v4(...)
else
ret = hmark_tg_v4(...)
return ret;
}
Same thing for IPv6. Those function will look smaller, and that's good
to make the code more maintainable.
You can define some hmark_hash_v4 and hmark_hash_v6 function that you
may want to inline.
Another suggestion in case you may need to extend HMARK in
the future. I think some info->type field to specify the
info->type can be HMARK_T_PKT or HMARK_T_CT.
Thus, the code above would look like:
... hmark_v4(...)
{
switch(info->type) {
case HMARK_T_PKT:
ret = hmark_tg_ct_v4(...)
break;
case HMARK_T_CT:
ret = hmark_tg_v4(...)
break;
}
}
But *this is only a suggestion*, of course.
> +#endif
> + addr_src &= info->src_mask.ip;
> + addr_dst &= info->dst_mask.ip;
> +
> + if ((info->flags & XT_F_HMARK_METHOD_L3) ||
> + (ip_proto == IPPROTO_ICMP)) {
> + uports.v32 = 0;
> + goto noports;
> + }
> + /* Check if ports can be used in hash calculation. */
> + poff = proto_ports_offset(ip_proto);
> + if (frag || poff < 0)
> + return XT_CONTINUE;
> +
> + /* if --ct not given, get ports from skb */
> + if (!uports.v32) {
> + nhoff += (ip->ihl * 4) + poff;
> + if (skb_copy_bits(skb, nhoff, &uports, sizeof(uports)) < 0)
> + return XT_CONTINUE;
> + }
> +
> + if (ip_proto == IPPROTO_ESP || ip_proto == IPPROTO_AH)
> + uports.v32 = (uports.v32 & info->spi_mask) | info->spi_set;
> + else {
> + uports.v32 = (uports.v32 & info->port_mask.v32) |
> + info->port_set.v32;
> + /* get a consistent hash (same value in any flow dirs.) */
> + if (uports.p16.dst < uports.p16.src)
> + swap(uports.p16.src, uports.p16.dst);
> + }
> +
> +noports:
> + /* get a consistent hash (same value in any flow direction) */
> + if (addr_dst < addr_src)
> + swap(addr_src, addr_dst);
> +
> + hash = jhash_3words(addr_src, addr_dst, uports.v32, info->hashrnd);
> + hash = hash ^ (ip_proto & info->proto_mask);
> + skb->mark = (hash % info->hmodulus) + info->hoffset;
> + return XT_CONTINUE;
> +}
> +
> +static int hmark_check(const struct xt_tgchk_param *par)
> +{
> + const struct xt_hmark_info *info = par->targinfo;
> +
> + if (!info->hmodulus) {
> + pr_info("HMARK: hmark-mod can't be zero\n");
> + return -EINVAL;
> + }
> + if (info->proto_mask && (info->flags & XT_F_HMARK_METHOD_L3)) {
> + pr_info("HMARK: When method L3 proto mask must be zero\n");
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static struct xt_target hmark_tg_reg[] __read_mostly = {
> + {
> + .name = "HMARK",
> + .revision = 0,
> + .family = NFPROTO_IPV4,
> + .target = hmark_v4,
> + .targetsize = sizeof(struct xt_hmark_info),
> + .checkentry = hmark_check,
> + .me = THIS_MODULE,
> + },
> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
> + {
> + .name = "HMARK",
> + .revision = 0,
> + .family = NFPROTO_IPV6,
> + .target = hmark_v6,
> + .targetsize = sizeof(struct xt_hmark_info),
> + .checkentry = hmark_check,
> + .me = THIS_MODULE,
> + },
> +#endif
> +};
> +
> +static int __init hmark_mt_init(void)
> +{
> + int ret;
> +
> + ret = xt_register_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
> + if (ret < 0)
> + return ret;
> + return 0;
> +}
> +
> +static void __exit hmark_mt_exit(void)
> +{
> + xt_unregister_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
> +}
> +
> +module_init(hmark_mt_init);
> +module_exit(hmark_mt_exit);
> --
> 1.7.2.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" 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] net: smsc911x: fix RX FIFO fastforwarding when dropping packets
From: Will Deacon @ 2012-04-12 15:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev@vger.kernel.org, Steve Glendinning
In-Reply-To: <1334239299.5300.6478.camel@edumazet-glaptop>
On Thu, Apr 12, 2012 at 03:01:39PM +0100, Eric Dumazet wrote:
> On Thu, 2012-04-12 at 14:47 +0100, Will Deacon wrote:
>
> >
> > I don't think we want an skb_reserve at all, since the hardware shifts the
> > data in the RX FIFO, meaning that we will read two bytes of 0 anyway before
> > valid data.
> >
> > > skb_put(skb, pktlength - 4);
> >
> > I can move the put here if you like, but we need to use pktwords << 2 to
> > make sure that we read the leading and trailing zeroes inserted by the
> > hardware.
>
> before calling linux stack, you'll have to skip those 2 bytes.
>
> This is skb_reserve() purpose.
Gotcha, so I can lose the pull too. Here's an updated patch with log, thanks
for the help.
Will
Author: Will Deacon <will.deacon@arm.com>
Date: Thu Apr 12 13:54:17 2012 +0100
net: smsc911x: fix skb handling in receive path
The SMSC911x driver resets the ->head, ->data and ->tail pointers in the
skb on the reset path in order to avoid buffer overflow due to packet
padding performed by the hardware.
This patch fixes the receive path so that the skb pointers are fixed up
after the data has been read from the device, The error path is also
fixed to use number of words consistently and prevent erroneous FIFO
fastforwarding when skipping over bad data.
Signed-off-by: Will Deacon <will.deacon@arm.com>
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 4a69710..5aa2dbe 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
/* Quickly dumps bad packets */
static void
-smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
{
- unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
-
if (likely(pktwords >= 4)) {
unsigned int timeout = 500;
unsigned int val;
@@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
continue;
}
- skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(dev, pktwords << 2);
if (unlikely(!skb)) {
SMSC_WARN(pdata, rx_err,
"Unable to allocate skb for rx packet");
@@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
break;
}
- skb->data = skb->head;
- skb_reset_tail_pointer(skb);
+ pdata->ops->rx_readfifo(pdata,
+ (unsigned int *)skb->data, pktwords);
/* Align IP on 16B boundary */
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pktlength - 4);
- pdata->ops->rx_readfifo(pdata,
- (unsigned int *)skb->head, pktwords);
skb->protocol = eth_type_trans(skb, dev);
skb_checksum_none_assert(skb);
netif_receive_skb(skb);
@@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev)
smsc911x_reg_write(pdata, FIFO_INT, temp);
/* set RX Data offset to 2 bytes for alignment */
- smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+ smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
/* enable NAPI polling before enabling RX interrupts */
napi_enable(&pdata->napi);
^ permalink raw reply related
* [PATCH] Fix missing mutex_lock/unlock
From: mjr @ 2012-04-12 15:26 UTC (permalink / raw)
To: davem; +Cc: sboyd, ben, netdev, Matt Renzelmann
From: Matt Renzelmann <mjr@cs.wisc.edu>
All calls to ks8851_rdreg* and ks8851_wrreg* should be protected
with the driver's lock mutex. A spurious interrupt may otherwise cause a
crash.
Signed-off-by: Matt Renzelmann <mjr@cs.wisc.edu>
---
Hello,
I'm new to the kernel development process so I hope I've not screwed
this up with this extra text. We found a potential issue using a new
driver testing tool called SymDrive. It looks legitimate to me, so
I'm reporting it. We hope to make this tool available in the future.
Please let me know if I should modify the patch or re-send without
this commentary. Thanks in advance for your patience.
drivers/net/ethernet/micrel/ks8851.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index c722aa6..fa2001a 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1515,11 +1515,15 @@ static int __devinit ks8851_probe(struct spi_device *spi)
goto err_netdev;
}
+ mutex_lock(&ks->lock);
+
netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
ndev->dev_addr, ndev->irq,
ks->rc_ccr & CCR_EEPROM ? "has" : "no");
+ mutex_unlock(&ks->lock);
+
return 0;
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 05/10] mac80211: Add more ethtools stats: survey, rates, etc
From: Ben Greear @ 2012-04-12 15:23 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, netdev
In-Reply-To: <1334202406.3788.8.camel@jlt3.sipsolutions.net>
On 04/11/2012 08:46 PM, Johannes Berg wrote:
> On Wed, 2012-04-11 at 10:52 -0700, greearb@candelatech.com wrote:
>
>> --- a/net/mac80211/cfg.c
>> +++ b/net/mac80211/cfg.c
>> @@ -19,6 +19,7 @@
>> #include "cfg.h"
>> #include "rate.h"
>> #include "mesh.h"
>> +#include "../wireless/core.h"
>
> NACK. Don't do that.
Looks like whatever I needed has already been moved somewhere
proper...I can just delete that line and it compiles fine.
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH 08/10] mac80211: Support on-channel scan option.
From: Ben Greear @ 2012-04-12 15:03 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, netdev
In-Reply-To: <1334202356.3788.7.camel@jlt3.sipsolutions.net>
On 04/11/2012 08:45 PM, Johannes Berg wrote:
> On Wed, 2012-04-11 at 10:52 -0700, greearb@candelatech.com wrote:
>
>> static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
>> struct cfg80211_scan_request *req)
>> @@ -438,10 +461,43 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
>> local->scan_req = req;
>> local->scan_sdata = sdata;
>>
>> - if (local->ops->hw_scan)
>> + if (local->ops->hw_scan) {
>> __set_bit(SCAN_HW_SCANNING,&local->scanning);
>> - else
>> - __set_bit(SCAN_SW_SCANNING,&local->scanning);
>> + } else {
>> + /* If we are scanning only on the current channel, then
>> + * we do not need to stop normal activities
>> + */
>> + if ((req->n_channels == 1)&&
>> + (req->channels[0]->center_freq ==
>> + local->hw.conf.channel->center_freq)) {
>
> how about "else if {", then the indentation isn't so deep and you can
> have much nicer code in the entire block :)
>
>> + unsigned long next_delay;
>
> please add a blank line after variable declarations.
>
>> + }
>> + else {
>
> please read the coding style documentation
>
>> @@ -672,6 +704,12 @@ void ieee80211_scan_work(struct work_struct *work)
>>
>> sdata = local->scan_sdata;
>>
>> + /* When scanning on-channel, the first-callback means completeed. */
>
> typo "completed"
Ok, will fix all of that.
>> + if (test_bit(SCAN_ONCHANNEL_SCANNING,&local->scanning)) {
>> + aborted = test_and_clear_bit(SCAN_ABORTED,&local->scanning);
>> + goto out_complete;
>> + }
>
> how does the onchannel bit get cleared?
__ieee80211_scan_completed sets local->scanning to 0, and it
will WARN_ON if local->scanning is NOT zero when entering
the method, so I don't think I should clear it earlier.
> Shouldn't you be calling pre/post scan hooks?
Probably so...I'll add that. Doesn't look like ath9k uses
it, but maybe some other NIC does need it.
> I'm a bit divided over this. On the one hand, it seems like a mildly
> useful optimisation, on the other though it adds a bunch of complexity
> for multi-channel we've been thinking about... Not that we want to
> support multi-channel with SW scan anyway, but still.
It's just an optimization...maybe just add a check and do a regular scan
if multi-channel is active if it's difficult to just make it work with
multi-channel?
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: Kernel panic with bridge networking
From: Massimo cetra @ 2012-04-12 14:57 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Peter Huang (Peng)
In-Reply-To: <1334235175.5300.6329.camel@edumazet-glaptop>
On 12/04/2012 14:52, Eric Dumazet wrote:
> On Thu, 2012-04-12 at 14:30 +0200, Massimo Cetra wrote:
>> Hello,
>>
>> i am experiencing a panic whose logs are attached (grabbed with netconsole).
>>
> Known issue, and we are waiting from a fix from Peter.
>
> https://lkml.org/lkml/2012/3/31/17
>
> Peter, any progress on your side ?
>
Thanks Eric,
is there a way to prvent those panics, meanwhile ?
I mean: i don't understand if it depends strictly on IPv6 or it has
other causes.
The same kernel with ipv6 enabled but without ipv6 is not actually
panic-ing ...
And thanks to Peter as well.
Massimo
^ permalink raw reply
* Re: [PATCH 05/10] mac80211: Add more ethtools stats: survey, rates, etc
From: Ben Greear @ 2012-04-12 14:50 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1334202406.3788.8.camel-8upI4CBIZJIJvtFkdXX2HixXY32XiHfO@public.gmane.org>
On 04/11/2012 08:46 PM, Johannes Berg wrote:
> On Wed, 2012-04-11 at 10:52 -0700, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
>
>> --- a/net/mac80211/cfg.c
>> +++ b/net/mac80211/cfg.c
>> @@ -19,6 +19,7 @@
>> #include "cfg.h"
>> #include "rate.h"
>> #include "mesh.h"
>> +#include "../wireless/core.h"
>
> NACK. Don't do that.
So, move the pertinent header stuff to linux/include/ieee80211.h ??
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
Candela Technologies Inc http://www.candelatech.com
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 06/10] mac80211: Add sta_state to ethtool stats.
From: Ben Greear @ 2012-04-12 14:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, netdev
In-Reply-To: <1334202554.3788.9.camel@jlt3.sipsolutions.net>
On 04/11/2012 08:49 PM, Johannes Berg wrote:
> On Wed, 2012-04-11 at 10:52 -0700, greearb@candelatech.com wrote:
>> From: Ben Greear<greearb@candelatech.com>
>>
>> Helps to know how the station is doing in it's association
>> attempt.
>>
>> Signed-off-by: Ben Greear<greearb@candelatech.com>
>> ---
>> :100644 100644 bbaf564... a63834d... M net/mac80211/cfg.c
>> net/mac80211/cfg.c | 6 ++++--
>> 1 files changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
>> index bbaf564..a63834d 100644
>> --- a/net/mac80211/cfg.c
>> +++ b/net/mac80211/cfg.c
>> @@ -118,7 +118,7 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
>> "rx_duplicates", "rx_fragments", "rx_dropped",
>> "tx_packets", "tx_bytes", "tx_fragments",
>> "tx_filtered", "tx_retry_failed", "tx_retries",
>> - "beacon_loss", "txrate", "rxrate", "signal",
>> + "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
>> "channel", "noise", "ch_time", "ch_time_busy",
>> "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
>> };
>> @@ -534,10 +534,12 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
>> data[i++] += sta->beacon_loss_count;
>>
>> if (!do_once) {
>> - i += 3;
>> + i += 4;
>> goto after_once;
>> }
>>
>> + data[i++] = sta->sta_state;
>> +
>
> Gee, I wish it was easier to tell if you were adding it to the right
> spot in the list ... any way that could be made easier?
It would be nice, but I haven't thought of an easy way to do this,
and I haven't noticed any other drivers
that found a way.
I *could* add a lot of #defines and do something like: data[STA_STATE_IDX] = sta->state,
and maybe create the strings array at run-time using macros to map string to
an idx define instead of have a static array of char*. But, I'm not sure if
it's worth the effort.
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [RFC v4] Add TCP encap_rcv hook
From: Simon Horman @ 2012-04-12 14:40 UTC (permalink / raw)
To: Eric Dumazet
Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
David Miller
In-Reply-To: <20120412143552.GA8730-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>
This hook is based on a hook of the same name provided by UDP. It provides
a way for to receive packets that have a TCP header and treat them in some
alternate way.
It is intended to be used by an implementation of the STT tunneling
protocol within Open vSwtich's datapath. A prototype of such an
implementation has been made.
The STT draft is available at
http://tools.ietf.org/html/draft-davie-stt-01
My prototype STT implementation has been posted to the dev-UOEtcQmXneFl884UGnbwIQ@public.gmane.org
The second version can be found at:
http://www.mail-archive.com/dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org/msg09001.html
It needs to be updated to call tcp_encap_enable()
Cc: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>
---
v4
* Make use of static_key,
a tonic for insanity suggested by Eric Dumazet
v3
* Replace more UDP references with TCP
* Move socket accesses to inside socket lock
and release lock on return.
v2
* Fix comment to refer to TCP rather than UDP
* Allow skb to continue traversing the stack if
the encap_rcv callback returns a positive value.
This is the same behaviour as the UDP hook.
---
include/linux/tcp.h | 3 +++
include/net/tcp.h | 1 +
net/ipv4/tcp_ipv4.c | 34 +++++++++++++++++++++++++++++++++-
3 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index b6c62d2..7210b23 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -472,6 +472,9 @@ struct tcp_sock {
* contains related tcp_cookie_transactions fields.
*/
struct tcp_cookie_values *cookie_values;
+
+ /* For encapsulation sockets. */
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
};
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index f75a04d..f2c4ac0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1575,5 +1575,6 @@ static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp)
extern void tcp_v4_init(void);
extern void tcp_init(void);
+extern void tcp_encap_enable(void);
#endif /* _TCP_H */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3a25cf7..dadcec6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -62,6 +62,7 @@
#include <linux/init.h>
#include <linux/times.h>
#include <linux/slab.h>
+#include <linux/static_key.h>
#include <net/net_namespace.h>
#include <net/icmp.h>
@@ -1657,6 +1658,14 @@ csum_err:
}
EXPORT_SYMBOL(tcp_v4_do_rcv);
+static struct static_key tcp_encap_needed __read_mostly;
+void tcp_encap_enable(void)
+{
+ if (!static_key_enabled(&tcp_encap_needed))
+ static_key_slow_inc(&tcp_encap_needed);
+}
+EXPORT_SYMBOL(tcp_encap_enable);
+
/*
* From tcp_input.c
*/
@@ -1666,6 +1675,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
const struct iphdr *iph;
const struct tcphdr *th;
struct sock *sk;
+ struct tcp_sock *tp;
int ret;
struct net *net = dev_net(skb->dev);
@@ -1726,9 +1736,30 @@ process:
bh_lock_sock_nested(sk);
ret = 0;
+
+ tp = tcp_sk(sk);
+ if (static_key_false(&tcp_encap_needed)) {
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
+ encap_rcv = ACCESS_ONCE(tp->encap_rcv);
+ if (encap_rcv != NULL) {
+ /*
+ * This is an encapsulation socket so pass the skb to
+ * the socket's tcp_encap_rcv() hook. Otherwise, just
+ * fall through and pass this up the TCP socket.
+ * up->encap_rcv() returns the following value:
+ * <=0 if skb was successfully passed to the encap
+ * handler or was discarded by it.
+ * >0 if skb should be passed on to TCP.
+ */
+ if (encap_rcv(sk, skb) <= 0) {
+ ret = 0;
+ goto unlock_sock;
+ }
+ }
+ }
+
if (!sock_owned_by_user(sk)) {
#ifdef CONFIG_NET_DMA
- struct tcp_sock *tp = tcp_sk(sk);
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
if (tp->ucopy.dma_chan)
@@ -1744,6 +1775,7 @@ process:
NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
goto discard_and_relse;
}
+unlock_sock:
bh_unlock_sock(sk);
sock_put(sk);
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH net-next] udp: intoduce udp_encap_needed static_key
From: Simon Horman @ 2012-04-12 14:35 UTC (permalink / raw)
To: Eric Dumazet
Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
David Miller
In-Reply-To: <1334221528.5300.6008.camel@edumazet-glaptop>
On Thu, Apr 12, 2012 at 11:05:28AM +0200, Eric Dumazet wrote:
> Most machines dont use UDP encapsulation (L2TP)
>
> Adds a static_key so that udp_queue_rcv_skb() doesnt have to perform a
> test if L2TP never setup the encap_rcv on a socket.
>
> Idea of this patch came after Simon Horman proposal to add a hook on TCP
> as well.
>
> If static_key is not yet enabled, the fast path does a single JMP .
>
> When static_key is enabled, JMP destination is patched to reach the real
> encap_type/encap_rcv logic, possibly adding cache misses.
Thanks Eric,
I have not had a chance to test your code, though it should be easy enough
to do so in the context of Open vSwitch as its CAPWAP implementation makes
use of UDP's encap_rcv (which is how I arrived at adding hook to TCP to
implement STT for Open vSwtich).
I have incorporated your static_key code into a new version of my TCP
encap_rcv patch and that does appear to work. I will post it ASAP.
>
> Signed-off-by: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>
> Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org
> ---
> include/net/udp.h | 1 +
> net/ipv4/udp.c | 12 +++++++++++-
> net/l2tp/l2tp_core.c | 1 +
> 3 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/udp.h b/include/net/udp.h
> index 5d606d9..9671f5f 100644
> --- a/include/net/udp.h
> +++ b/include/net/udp.h
> @@ -267,4 +267,5 @@ extern void udp_init(void);
> extern int udp4_ufo_send_check(struct sk_buff *skb);
> extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
> netdev_features_t features);
> +extern void udp_encap_enable(void);
> #endif /* _UDP_H */
> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index fe14105..ad1e0dd 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
> @@ -107,6 +107,7 @@
> #include <net/checksum.h>
> #include <net/xfrm.h>
> #include <trace/events/udp.h>
> +#include <linux/static_key.h>
> #include "udp_impl.h"
>
> struct udp_table udp_table __read_mostly;
> @@ -1379,6 +1380,14 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
>
> }
>
> +static struct static_key udp_encap_needed __read_mostly;
> +void udp_encap_enable(void)
> +{
> + if (!static_key_enabled(&udp_encap_needed))
> + static_key_slow_inc(&udp_encap_needed);
> +}
> +EXPORT_SYMBOL(udp_encap_enable);
> +
> /* returns:
> * -1: error
> * 0: success
> @@ -1400,7 +1409,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
> goto drop;
> nf_reset(skb);
>
> - if (up->encap_type) {
> + if (static_key_false(&udp_encap_needed) && up->encap_type) {
> int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
>
> /*
> @@ -1760,6 +1769,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
> /* FALLTHROUGH */
> case UDP_ENCAP_L2TPINUDP:
> up->encap_type = val;
> + udp_encap_enable();
> break;
> default:
> err = -ENOPROTOOPT;
> diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
> index 89ff8c6..f6732b6 100644
> --- a/net/l2tp/l2tp_core.c
> +++ b/net/l2tp/l2tp_core.c
> @@ -1424,6 +1424,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
> /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
> udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP;
> udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
> + udp_encap_enable();
> }
>
> sk->sk_user_data = tunnel;
>
>
^ permalink raw reply
* pull request: wireless 2012-04-12
From: John W. Linville @ 2012-04-12 14:28 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 30364 bytes --]
commit 5d949944229b0a08e218723be231731cd86b94f3
Dave,
This is a flurry of fixes intended for 3.4...
Many of these are Bluetooth fixes. Gustavo says:
"This is a batch of fixes for 3.4. We have added support to 3 new
devices, fixes some NULL-pointer dereferences, memory leaks, memory
corruption and endian bugs. There was also a userspace compatibility
fix reported by Keith Packard on lkml. The fixes are all simple."
On top of the Bluetooths bits, we have a number of wireless fixes.
One is an rt2x00 fix from Chien-Chia Chen which fixes the rfkill
registration so that it still works even if the box is booted with the
device already blocked. Johannes Berg gives us a pair of fixes, one
that corrects a macro parameter when setting a beacon wait timeout, and
another that ensures that the proper interface state is used throughout
nl80211 so as to avoid warnings and unintended driver behavior.
Julia Lawall gives us a fix for a memory leak in an error handling
case. Larry Finger is the star performer for this round, giving us a
fix for firmware initialization in rtl8192de, a mac80211 fix to quiet
some log spam, a fix to avoid a NULL pointer dereference in rtlwifi, an
rtlwifi fix to avoid a "sleeping function called from invalid context"
BUG, and another rtlwifi fix to avoid "Out of SW-IOMMU space" errors.
Paul Gortmaker gives us a fix to avoid bcma build breakage on MIPS.
Samuel Ortiz fixes a loop in NFC's LLCP Tx frame fragmentation loop.
And finally, Sujith Manoharan reverts an earlier patch in order to
fix a regression reported by a number of ath9k users.
Please let me know if there are problems!
Thanks,
John
---
The following changes since commit a21d45726acacc963d8baddf74607d9b74e2b723:
tcp: avoid order-1 allocations on wifi and tx path (2012-04-11 10:11:12 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
AceLan Kao (1):
Bluetooth: Add support for Atheros [04ca:3005]
Andrei Emeltchenko (3):
Bluetooth: Fix memory leaks due to chan refcnt
Bluetooth: mgmt: Add missing endian conversion
Bluetooth: mgmt: Fix timeout type
Brian Gix (1):
Bluetooth: mgmt: Fix corruption of device_connected pkt
Chen, Chien-Chia (1):
rt2x00: Fix rfkill_polling register function.
Cho, Yu-Chen (1):
Bluetooth: Add Atheros maryann PIDVID support
Don Zickus (1):
Bluetooth: btusb: typo in Broadcom SoftSailing id
Gustavo Padovan (1):
Bluetooth: Fix userspace compatibility issue with mgmt interface
Hemant Gupta (1):
Bluetooth: Use correct flags for checking HCI_SSP_ENABLED bit
Johan Hedberg (2):
Bluetooth: Don't increment twice in eir_has_data_type()
Bluetooth: Check for minimum data length in eir_has_data_type()
Johan Hovold (2):
Bluetooth: hci_ldisc: fix NULL-pointer dereference on tty_close
Bluetooth: hci_core: fix NULL-pointer dereference at unregister
Johannes Berg (2):
mac80211: fix association beacon wait timeout
nl80211: ensure interface is up in various APIs
John W. Linville (2):
Merge branch 'master' of git://git.kernel.org/.../bluetooth/bluetooth
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
João Paulo Rechi Vita (1):
Bluetooth: btusb: Add USB device ID "0a5c 21e8"
Julia Lawall (1):
net/wireless/wext-core.c: add missing kfree
Larry Finger (5):
rtlwifi: rtl8192de: Fix firmware initialization
mac80211: Convert WARN_ON to WARN_ON_ONCE
rtlwifi: Fix oops on rate-control failure
rtlwifi: Preallocate USB read buffers and eliminate kalloc in read routine
rtlwifi: Add missing DMA buffer unmapping for PCI drivers
Marcel Holtmann (1):
MAINTAINERS: update Bluetooth tree locations
Paul Gortmaker (1):
bcma: fix build error on MIPS; implicit pcibios_enable_device
Samuel Ortiz (1):
NFC: Fix the LLCP Tx fragmentation loop
Santosh Nayak (1):
Bluetooth: Fix Endian Bug.
Sujith Manoharan (1):
Revert "ath9k: fix going to full-sleep on PS idle"
MAINTAINERS | 8 +++---
drivers/bcma/Kconfig | 2 +-
drivers/bcma/driver_pci_host.c | 1 +
drivers/bluetooth/ath3k.c | 4 +++
drivers/bluetooth/btusb.c | 5 +++-
drivers/bluetooth/hci_ldisc.c | 2 +-
drivers/net/wireless/ath/ath9k/main.c | 8 ++----
drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +----
drivers/net/wireless/rtlwifi/base.c | 5 +++-
drivers/net/wireless/rtlwifi/pci.c | 7 ++++-
drivers/net/wireless/rtlwifi/rtl8192de/sw.c | 6 ----
drivers/net/wireless/rtlwifi/usb.c | 34 ++++++++++++--------------
drivers/net/wireless/rtlwifi/wifi.h | 6 ++++-
include/net/bluetooth/hci.h | 3 +-
include/net/bluetooth/hci_core.h | 12 +++++----
include/net/bluetooth/mgmt.h | 2 +-
include/net/mac80211.h | 2 +-
net/bluetooth/hci_core.c | 7 +++++
net/bluetooth/l2cap_core.c | 3 ++
net/bluetooth/l2cap_sock.c | 5 ++-
net/bluetooth/mgmt.c | 13 +++++++---
net/mac80211/mlme.c | 3 +-
net/nfc/llcp/commands.c | 4 +-
net/wireless/nl80211.c | 31 ++++++++++++++----------
net/wireless/wext-core.c | 6 +++-
25 files changed, 108 insertions(+), 77 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 71b7f5c..0e2f300 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1521,8 +1521,8 @@ M: Gustavo Padovan <gustavo@padovan.org>
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
S: Maintained
F: drivers/bluetooth/
@@ -1532,8 +1532,8 @@ M: Gustavo Padovan <gustavo@padovan.org>
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
S: Maintained
F: net/bluetooth/
F: include/net/bluetooth/
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index c1172da..fb7c80f 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -29,7 +29,7 @@ config BCMA_HOST_PCI
config BCMA_DRIVER_PCI_HOSTMODE
bool "Driver for PCI core working in hostmode"
- depends on BCMA && MIPS
+ depends on BCMA && MIPS && BCMA_HOST_PCI
help
PCI core hostmode operation (external PCI bus).
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index 4e20bcf..d2097a1 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -10,6 +10,7 @@
*/
#include "bcma_private.h"
+#include <linux/pci.h>
#include <linux/export.h>
#include <linux/bcma/bcma.h>
#include <asm/paccess.h>
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 4844247..ae9edca 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -72,7 +72,9 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3004) },
+ { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) },
+ { USB_DEVICE(0x04CA, 0x3005) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -89,7 +91,9 @@ static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 480cad9..3311b81 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Broadcom SoftSailing reporting vendor specific */
- { USB_DEVICE(0x05ac, 0x21e1) },
+ { USB_DEVICE(0x0a5c, 0x21e1) },
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
@@ -103,6 +103,7 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x0a5c, 0x21e6) },
+ { USB_DEVICE(0x0a5c, 0x21e8) },
{ USB_DEVICE(0x0a5c, 0x21f3) },
{ USB_DEVICE(0x413c, 0x8197) },
@@ -129,7 +130,9 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index fd5adb4..98a8c05 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -299,11 +299,11 @@ static void hci_uart_tty_close(struct tty_struct *tty)
hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
- hu->proto->close(hu);
if (hdev) {
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
+ hu->proto->close(hu);
}
kfree(hu);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 215eb25..2504ab0 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -118,15 +118,13 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0)
goto unlock;
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
- goto unlock;
-
- if (sc->ps_idle)
+ if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)))
+ PS_WAIT_FOR_PSPOLL_DATA |
+ PS_WAIT_FOR_TX_ACK)))
mode = ATH9K_PM_NETWORK_SLEEP;
else
goto unlock;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index fc9901e..90cc5e7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1062,11 +1062,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
- /*
- * Register the extra components.
- */
- rt2x00rfkill_register(rt2x00dev);
-
return 0;
}
@@ -1210,6 +1205,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00link_register(rt2x00dev);
rt2x00leds_register(rt2x00dev);
rt2x00debug_register(rt2x00dev);
+ rt2x00rfkill_register(rt2x00dev);
return 0;
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 5100235..e54488d 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -838,7 +838,10 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
__le16 fc = hdr->frame_control;
txrate = ieee80211_get_tx_rate(hw, info);
- tcb_desc->hw_rate = txrate->hw_value;
+ if (txrate)
+ tcb_desc->hw_rate = txrate->hw_value;
+ else
+ tcb_desc->hw_rate = 0;
if (ieee80211_is_data(fc)) {
/*
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 07dd38e..288b035 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -912,8 +912,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
ring = &rtlpci->tx_ring[BEACON_QUEUE];
pskb = __skb_dequeue(&ring->queue);
- if (pskb)
+ if (pskb) {
+ struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+ pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc(
+ (u8 *) entry, true, HW_DESC_TXBUFF_ADDR),
+ pskb->len, PCI_DMA_TODEVICE);
kfree_skb(pskb);
+ }
/*NB: the beacon data buffer must be 32-bit aligned. */
pskb = ieee80211_beacon_get(hw, mac->vif);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index 4898c50..480862c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -91,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
u8 tid;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- static int header_print;
rtlpriv->dm.dm_initialgain_enable = true;
rtlpriv->dm.dm_flag = 0;
@@ -171,10 +170,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
for (tid = 0; tid < 8; tid++)
skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
- /* Only load firmware for first MAC */
- if (header_print)
- return 0;
-
/* for firmware buf */
rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
if (!rtlpriv->rtlhal.pfirmware) {
@@ -186,7 +181,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->max_fw_size = 0x8000;
pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
- header_print++;
/* request fw */
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 2e1e352..d04dbda 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
return status;
}
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
{
+ struct device *dev = rtlpriv->io.dev;
+ struct usb_device *udev = to_usb_device(dev);
u8 request;
u16 wvalue;
u16 index;
- u32 *data;
- u32 ret;
+ __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
- data = kmalloc(sizeof(u32), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)addr;
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
- ret = le32_to_cpu(*data);
- kfree(data);
- return ret;
+ if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
+ rtlpriv->usb_data_index = 0;
+ return le32_to_cpu(*data);
}
static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+ return (u8)_usb_read_sync(rtlpriv, addr, 1);
}
static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+ return (u16)_usb_read_sync(rtlpriv, addr, 2);
}
static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_read_sync(to_usb_device(dev), addr, 4);
+ return _usb_read_sync(rtlpriv, addr, 4);
}
static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -955,6 +947,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
return -ENOMEM;
}
rtlpriv = hw->priv;
+ rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+ GFP_KERNEL);
+ if (!rtlpriv->usb_data)
+ return -ENOMEM;
+ rtlpriv->usb_data_index = 0;
init_completion(&rtlpriv->firmware_loading_complete);
SET_IEEE80211_DEV(hw, &intf->dev);
udev = interface_to_usbdev(intf);
@@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf)
/* rtl_deinit_rfkill(hw); */
rtl_usb_deinit(hw);
rtl_deinit_core(hw);
+ kfree(rtlpriv->usb_data);
rtlpriv->cfg->ops->deinit_sw_leds(hw);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index b591614..28ebc69 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -67,7 +67,7 @@
#define QOS_QUEUE_NUM 4
#define RTL_MAC80211_NUM_QUEUE 5
#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254
-
+#define RTL_USB_MAX_RX_COUNT 100
#define QBSS_LOAD_SIZE 5
#define MAX_WMMELE_LENGTH 64
@@ -1629,6 +1629,10 @@ struct rtl_priv {
interface or hardware */
unsigned long status;
+ /* data buffer pointer for USB reads */
+ __le32 *usb_data;
+ int usb_data_index;
+
/*This must be the last item so
that it points to the data allocated
beyond this structure like:
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 344b0f9..d47e523 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -92,6 +92,7 @@ enum {
HCI_SERVICE_CACHE,
HCI_LINK_KEYS,
HCI_DEBUG_KEYS,
+ HCI_UNREGISTER,
HCI_LE_SCAN,
HCI_SSP_ENABLED,
@@ -1327,8 +1328,8 @@ struct sockaddr_hci {
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
-#define HCI_CHANNEL_CONTROL 1
#define HCI_CHANNEL_MONITOR 2
+#define HCI_CHANNEL_CONTROL 3
struct hci_filter {
unsigned long type_mask;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index daefaac..6822d25 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -427,7 +427,7 @@ enum {
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
- return (test_bit(HCI_SSP_ENABLED, &hdev->flags) &&
+ return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
}
@@ -907,11 +907,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
{
- u8 field_len;
- size_t parsed;
+ size_t parsed = 0;
- for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
- field_len = data[0];
+ if (data_len < 2)
+ return false;
+
+ while (parsed < data_len - 1) {
+ u8 field_len = data[0];
if (field_len == 0)
break;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ffc1377..ebfd91f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -117,7 +117,7 @@ struct mgmt_mode {
#define MGMT_OP_SET_DISCOVERABLE 0x0006
struct mgmt_cp_set_discoverable {
__u8 val;
- __u16 timeout;
+ __le16 timeout;
} __packed;
#define MGMT_SET_DISCOVERABLE_SIZE 3
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 87d203f..9210bdc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1327,7 +1327,7 @@ static inline struct ieee80211_rate *
ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
const struct ieee80211_tx_info *c)
{
- if (WARN_ON(c->control.rates[0].idx < 0))
+ if (WARN_ON_ONCE(c->control.rates[0].idx < 0))
return NULL;
return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx];
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e33af63..92a857e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -665,6 +665,11 @@ int hci_dev_open(__u16 dev)
hci_req_lock(hdev);
+ if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+ ret = -ENODEV;
+ goto done;
+ }
+
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
@@ -1849,6 +1854,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
+ set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+
write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b8e17e4..94552b3 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1308,6 +1308,7 @@ static void l2cap_monitor_timeout(struct work_struct *work)
if (chan->retry_count >= chan->remote_max_tx) {
l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
return;
}
@@ -1316,6 +1317,7 @@ static void l2cap_monitor_timeout(struct work_struct *work)
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
}
static void l2cap_retrans_timeout(struct work_struct *work)
@@ -1335,6 +1337,7 @@ static void l2cap_retrans_timeout(struct work_struct *work)
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
}
static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c4fe583..29122ed 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -82,7 +82,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
}
if (la.l2_cid)
- err = l2cap_add_scid(chan, la.l2_cid);
+ err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
else
err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
@@ -123,7 +123,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
if (la.l2_cid && la.l2_psm)
return -EINVAL;
- err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);
+ err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
+ &la.l2_bdaddr);
if (err)
return err;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7fcff88..4ef275c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2523,13 +2523,18 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
if (cp->val) {
type = PAGE_SCAN_TYPE_INTERLACED;
- acp.interval = 0x0024; /* 22.5 msec page scan interval */
+
+ /* 22.5 msec page scan interval */
+ acp.interval = __constant_cpu_to_le16(0x0024);
} else {
type = PAGE_SCAN_TYPE_STANDARD; /* default */
- acp.interval = 0x0800; /* default 1.28 sec page scan */
+
+ /* default 1.28 sec page scan */
+ acp.interval = __constant_cpu_to_le16(0x0800);
}
- acp.window = 0x0012; /* default 11.25 msec page scan window */
+ /* default 11.25 msec page scan window */
+ acp.window = __constant_cpu_to_le16(0x0012);
err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp),
&acp);
@@ -2936,7 +2941,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
name, name_len);
if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
- eir_len = eir_append_data(&ev->eir[eir_len], eir_len,
+ eir_len = eir_append_data(ev->eir, eir_len,
EIR_CLASS_OF_DEV, dev_class, 3);
put_unaligned_le16(eir_len, &ev->eir_len);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 576fb25..f76da5b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3387,8 +3387,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
*/
printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
sdata->name, ifmgd->bssid);
- assoc_data->timeout = jiffies +
- TU_TO_EXP_TIME(req->bss->beacon_interval);
+ assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
} else {
assoc_data->have_beacon = true;
assoc_data->sent_assoc = false;
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 7b76eb7..ef10ffc 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -474,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
while (remaining_len > 0) {
- frag_len = min_t(u16, local->remote_miu, remaining_len);
+ frag_len = min_t(size_t, local->remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -497,7 +497,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
release_sock(sk);
remaining_len -= frag_len;
- msg_ptr += len;
+ msg_ptr += frag_len;
}
kfree(msg_data);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e49da27..f432c57 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1294,6 +1294,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
goto bad_res;
}
+ if (!netif_running(netdev)) {
+ result = -ENETDOWN;
+ goto bad_res;
+ }
+
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
rem_txq_params) {
@@ -6384,7 +6389,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_get_key,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6416,7 +6421,7 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_set_beacon,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6424,7 +6429,7 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_start_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6432,7 +6437,7 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_stop_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6448,7 +6453,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6464,7 +6469,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6497,7 +6502,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_mpath,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6505,7 +6510,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_bss,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6531,7 +6536,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_get_mesh_config,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6664,7 +6669,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6672,7 +6677,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6680,7 +6685,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_flush_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6840,7 +6845,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_probe_client,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 0af7f54..af648e0 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -780,8 +780,10 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
if (cmd == SIOCSIWENCODEEXT) {
struct iw_encode_ext *ee = (void *) extra;
- if (iwp->length < sizeof(*ee) + ee->key_len)
- return -EFAULT;
+ if (iwp->length < sizeof(*ee) + ee->key_len) {
+ err = -EFAULT;
+ goto out;
+ }
}
}
--
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] net: smsc911x: fix RX FIFO fastforwarding when dropping packets
From: Eric Dumazet @ 2012-04-12 14:01 UTC (permalink / raw)
To: Will Deacon; +Cc: netdev@vger.kernel.org, Steve Glendinning
In-Reply-To: <20120412134757.GH16025@mudshark.cambridge.arm.com>
On Thu, 2012-04-12 at 14:47 +0100, Will Deacon wrote:
>
> I don't think we want an skb_reserve at all, since the hardware shifts the
> data in the RX FIFO, meaning that we will read two bytes of 0 anyway before
> valid data.
>
> > skb_put(skb, pktlength - 4);
>
> I can move the put here if you like, but we need to use pktwords << 2 to
> make sure that we read the leading and trailing zeroes inserted by the
> hardware.
before calling linux stack, you'll have to skip those 2 bytes.
This is skb_reserve() purpose.
^ 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