* [PATCH RFC] ethtool: add multiple queue support to {get,set}_ringparams
From: Ajit Khaparde @ 2010-03-14 1:43 UTC (permalink / raw)
To: David Miller, jeff; +Cc: netdev
With network devices and hence device drivers supporting
multiple Tx and Rx rings, currently there is no way for
ethtool to specify which Tx/Rx ring the user wants to get/set.
This patch enhances the get/set ring params option by allowing
the user to specify the Tx/Rx ring id of interest.
Please review.
Current Usage:
ethtool -g <interface name>
ethtool -G <interface name> [new parameters to set]
New Usage:
ethtool -g <interface name> [ RING-ID ]
ethtool -G <interface name> [ RING-ID ] [new parameters to set]
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
ethtool-copy.h | 1 +
ethtool.8 | 8 ++++++++
ethtool.c | 19 +++++++++++++++++--
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/ethtool-copy.h b/ethtool-copy.h
index 8681f5e..1ac6beb 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -199,6 +199,7 @@ struct ethtool_coalesce {
/* for configuring RX/TX ring parameters */
struct ethtool_ringparam {
__u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */
+ __u32 ring_id;
/* Read only attributes. These indicate the maximum number
* of pending RX/TX ring entries the driver will allow the
diff --git a/ethtool.8 b/ethtool.8
index eb6430b..14b8984 100644
--- a/ethtool.8
+++ b/ethtool.8
@@ -116,9 +116,11 @@ ethtool \- Display or change ethernet card settings
.B ethtool \-g|\-\-show\-ring
.I ethX
+.RI [ N ]
.B ethtool \-G|\-\-set\-ring
.I ethX
+.RI [ N ]
.RB [ rx
.IR N ]
.RB [ rx-mini
@@ -287,9 +289,15 @@ Changes the coalescing settings of the specified ethernet device.
.B \-g \-\-show\-ring
Queries the specified ethernet device for rx/tx ring parameter information.
.TP
+.B N
+The tx/rx ring id.
+.TP
.B \-G \-\-set\-ring
Changes the rx/tx ring parameters of the specified ethernet device.
.TP
+.B N
+The tx/rx ring id.
+.TP
.BI rx \ N
Changes the number of ring entries for the Rx ring.
.TP
diff --git a/ethtool.c b/ethtool.c
index fc9e419..650bb8c 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -156,8 +156,10 @@ static struct option {
" [tx-usecs-high N]\n"
" [tx-frames-high N]\n"
" [sample-interval N]\n" },
- { "-g", "--show-ring", MODE_GRING, "Query RX/TX ring parameters" },
+ { "-g", "--show-ring", MODE_GRING, "Query RX/TX ring parameters",
+ " [ RING ID ]\n" },
{ "-G", "--set-ring", MODE_SRING, "Set RX/TX ring parameters",
+ " [ RING ID ]\n"
" [ rx N ]\n"
" [ rx-mini N ]\n"
" [ rx-jumbo N ]\n"
@@ -265,6 +267,7 @@ static int pause_rx_wanted = -1;
static int pause_tx_wanted = -1;
static struct ethtool_ringparam ering;
+static int ring_id = 0;
static int gring_changed = 0;
static int ring_rx_wanted = -1;
static int ring_rx_mini_wanted = -1;
@@ -605,6 +608,10 @@ static void parse_cmdline(int argc, char **argp)
flash = 1;
break;
}
+ if (mode == MODE_SRING) {
+ ring_id = get_int(argp[i], 10);
+ break;
+ }
/* fallthrough */
default:
if (mode == MODE_GREGS) {
@@ -639,6 +646,10 @@ static void parse_cmdline(int argc, char **argp)
i = argc;
break;
}
+ if (mode == MODE_GRING) {
+ ring_id = get_int(argp[i], 10);
+ break;
+ }
if (mode == MODE_SRING) {
parse_generic_cmdline(argc, argp, i,
&gring_changed,
@@ -1761,6 +1772,7 @@ static int do_sring(int fd, struct ifreq *ifr)
int err, changed = 0;
ering.cmd = ETHTOOL_GRINGPARAM;
+ ering.ring_id = ring_id;
ifr->ifr_data = (caddr_t)&ering;
err = send_ioctl(fd, ifr);
if (err) {
@@ -1776,6 +1788,7 @@ static int do_sring(int fd, struct ifreq *ifr)
}
ering.cmd = ETHTOOL_SRINGPARAM;
+ ering.ring_id = ring_id;
ifr->ifr_data = (caddr_t)&ering;
err = send_ioctl(fd, ifr);
if (err) {
@@ -1790,9 +1803,11 @@ static int do_gring(int fd, struct ifreq *ifr)
{
int err;
- fprintf(stdout, "Ring parameters for %s:\n", devname);
+ fprintf(stdout, "Ring parameters for ring id %d for %s:\n",
+ ring_id, devname);
ering.cmd = ETHTOOL_GRINGPARAM;
+ ering.ring_id = ring_id;
ifr->ifr_data = (caddr_t)&ering;
err = send_ioctl(fd, ifr);
if (err == 0) {
--
1.6.3.3
^ permalink raw reply related
* Re: [RFC PATCH net-2.6] net/ethtool: add multiple queue support to {get,set}_ringparams
From: David Miller @ 2010-03-14 2:11 UTC (permalink / raw)
To: ajitk, ajitkhaparde; +Cc: jeff, netdev
In-Reply-To: <20100314014335.GA17208@serverengines.com>
From: Ajit Khaparde <ajitkhaparde@gmail.com>
Date: Sun, 14 Mar 2010 07:13:45 +0530
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index b33f316..de6a90a 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -206,6 +206,7 @@ struct ethtool_coalesce {
> /* for configuring RX/TX ring parameters */
> struct ethtool_ringparam {
> __u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */
> + __u32 ring_id;
>
> /* Read only attributes. These indicate the maximum number
> * of pending RX/TX ring entries the driver will allow the
For the millionth time, you cannot change these datastructures
like this without breaking all existing userspace applications
out there.
^ permalink raw reply
* [PATCH] BUG: unable to handle kernel NULL pointer dereference at br_multicast_leave_group
From: michael-dev @ 2010-03-14 2:28 UTC (permalink / raw)
To: netdev
[-- Attachment #1.1: Type: text/plain, Size: 8087 bytes --]
Hi,
I'm currently using linux-next and have been running into an OOPs which
I think might be caused by a patch you submitted on 2010-02-27.
It's a linux-next kernel from 2010-03-12 on an x86 system and it
OOPs in the bridge module in br_mdp_ip_get (called by
br_multicast_leave_group) because the br->mdb is null.
Digging deeper it seems that when a igmp leave packet is received, it is
not checked wether mdb has been populated yet. Though, if the group does
not exist, the code just skips leaving. So it seems the same action cna
be taken if mdb is still NULL. As far as I can see, commit
eb1d16414339a6e113d89e2cca2556005d7ce919 added multicast code to bridge
and so likely causes this crash. This crash does not happen on 2.6.33.
I've therefore modified br_multicast so that the leave is skipped if mdb
is empty.
Please don't hesitate to contact me if there are any questions.
Sincerely,
M. Braun
// gdb output //
(gdb) print *((struct net_bridge*) 0xcec68800)
$3 = {lock = {{rlock = {raw_lock = {<No data fields>}}}}, port_list =
{next = 0xcec41790, prev = 0xcfb209f8}, dev = 0xcec68520, hash_lock =
{{rlock = {raw_lock = {<No data fields>}}}}, hash = {{first = 0x0},
{first = 0x0}, {first = 0x0}, {first = 0x0}, {
first = 0xcfb4d980}, {first = 0x0} <repeats 19 times>, {first =
0xcec41200}, {first = 0x0} <repeats 119 times>, {first = 0xcf00ea80},
{first = 0x0} <repeats 29 times>, {first = 0xcfb6d680}, {first = 0x0}
<repeats 52 times>, {first = 0xcec40b00}, {first = 0x0}, {
first = 0x0}, {first = 0x0}, {first = 0x0}, {first = 0x0}, {first
= 0x0}, {first = 0x0}, {first = 0xcf00d1c0}, {first = 0x0} <repeats 20
times>}, feature_mask = 16726117, fake_rtable = {u = {dst = {rcu_head =
{next = 0x0, func = 0}, child = 0x0, dev = 0xcec68520,
error = 0, obsolete = 0, flags = 2, expires = 0, header_len = 0,
trailer_len = 0, rate_tokens = 0, rate_last = 0, path = 0xcec68c10,
neighbour = 0x0, hh = 0x0, xfrm = 0x0, input = 0, output = 0, ops =
0xd0cc2a40, metrics = {0, 1500, 0 <repeats 12 times>},
tclassid = 0, __refcnt = {counter = 2}, __use = 0, lastuse = 0,
{next = 0x0, rt_next = 0x0, rt6_next = 0x0, dn_next = 0x0}}}, fl = {oif
= 0, iif = 0, mark = 0, nl_u = {ip4_u = {daddr = 0, saddr = 0, tos = 0
'\000', scope = 0 '\000'}, ip6_u = {daddr = {in6_u = {
u6_addr8 = '\000' <repeats 15 times>, u6_addr16 = {0, 0,
0, 0, 0, 0, 0, 0}, u6_addr32 = {0, 0, 0, 0}}}, saddr = {in6_u =
{u6_addr8 = '\000' <repeats 15 times>, u6_addr16 = {0, 0, 0, 0, 0, 0, 0,
0}, u6_addr32 = {0, 0, 0, 0}}}, flowlabel = 0}, dn_u = {
daddr = 0, saddr = 0, scope = 0 '\000'}}, proto = 0 '\000',
flags = 0 '\000', uli_u = {ports = {sport = 0, dport = 0}, icmpt = {type
= 0 '\000', code = 0 '\000'}, dnports = {sport = 0, dport = 0}, spi = 0,
mht = {type = 0 '\000'}}, secid = 0}, idev = 0x0,
rt_genid = 0, rt_flags = 0, rt_type = 0, rt_dst = 0, rt_src = 0,
rt_iif = 0, rt_gateway = 0, rt_spec_dst = 0, peer = 0x0}, flags = 0,
designated_root = {prio = "\200", addr = "\000\016\216\031\356v"},
bridge_id = {prio = "\200", addr = "\000\016\216\031\356v"},
root_path_cost = 0, max_age = 20000, hello_time = 2000, forward_delay
= 15000, bridge_max_age = 20000, ageing_time = 300000, bridge_hello_time
= 2000, bridge_forward_delay = 15000, group_addr =
"\001\200\302\000\000", root_port = 0, stp_enabled = BR_KERNEL_STP,
topology_change = 0 '\000', topology_change_detected = 0 '\000',
multicast_router = 1 '\001', multicast_disabled = 0 '\000',
hash_elasticity = 4, hash_max = 512, multicast_last_member_count = 2,
multicast_startup_queries_sent = 2, multicast_startup_query_count = 2,
multicast_last_member_interval = 1000, multicast_membership_interval =
260000, multicast_querier_interval = 255000, multicast_query_interval =
125000, multicast_query_response_interval = 10000,
multicast_startup_query_interval = 31250, multicast_lock = {{rlock = {
raw_lock = {<No data fields>}}}}, mdb = 0x0, router_list =
{first = 0x0}, mglist = {first = 0x0}, multicast_router_timer = {entry =
{next = 0x0, prev = 0x0}, expires = 0, function = 0xd0cbf264
<br_multicast_local_router_expired>, data = 0, base = 0xc0579640},
multicast_querier_timer = {entry = {next = 0x0, prev = 0x0}, expires =
0, function = 0xd0cbf264 <br_multicast_local_router_expired>, data = 0,
base = 0xc0579640}, multicast_query_timer = {entry = {next = 0xd0a1f630,
prev = 0xc057a1a4}, expires = 1756782,
function = 0xd0cc01e1 <br_multicast_query_expired>, data =
3469117440, base = 0xc0579640}, hello_timer = {entry = {next =
0xc0579f14, prev = 0xcfcb6e10}, expires = 1694000, function = 0xd0cbc75b
<br_hello_timer_expired>, data = 3469117440, base = 0xc0579640},
tcn_timer = {entry = {next = 0x0, prev = 0x0}, expires = 0, function =
0xd0cbc6ce <br_tcn_timer_expired>, data = 3469117440, base =
0xc0579640}, topology_change_timer = {entry = {next = 0x0, prev =
0x200200}, expires = 225844,
function = 0xd0cbc42c <br_topology_change_timer_expired>, data =
3469117440, base = 0xc0579640}, gc_timer = {entry = {next = 0xcfcb6e10,
prev = 0xc0579f14}, expires = 1694000, function = 0xd0cb8d8f
<br_fdb_cleanup>, data = 3469117440, base = 0xc0579640},
ifobj = 0xcfca1164}
(gdb) print ((struct net_bridge*) 0xcec68800)->mdb
$4 = (struct net_bridge_mdb_htable *) 0x0
(gdb) bt
#0 jhash_3words (mdb=0x0, dst=0) at include/linux/jhash.h:128
#1 jhash_1word (mdb=0x0, dst=0) at include/linux/jhash.h:140
#2 br_ip_hash (mdb=0x0, dst=0) at net/bridge/br_multicast.c:32
#3 br_mdb_ip_get (mdb=0x0, dst=0) at net/bridge/br_multicast.c:52
#4 0xd0cc0ec8 in br_multicast_leave_group (br=0xcec68800, port=<value
optimised out>, skb=0xcf00e580) at net/bridge/br_multicast.c:902
#5 br_multicast_ipv4_rcv (br=0xcec68800, port=<value optimised out>,
skb=0xcf00e580) at net/bridge/br_multicast.c:1033
#6 br_multicast_rcv (br=0xcec68800, port=<value optimised out>,
skb=0xcf00e580) at net/bridge/br_multicast.c:1052
#7 0xd0cb9c06 in br_handle_frame_finish (skb=0xcf00e580) at
net/bridge/br_input.c:55
#8 0xd0cbea59 in NF_HOOK_THRESH (skb=0xcf00e580) at
include/linux/netfilter.h:206
#9 br_nf_pre_routing_finish (skb=0xcf00e580) at
net/bridge/br_netfilter.c:420
#10 0xd0cbf015 in NF_HOOK_THRESH (hook=<value optimised out>,
skb=0xcf00e580, in=<value optimised out>, out=0x0, okfn=0xd0cb9bad
<br_handle_frame_finish>) at include/linux/netfilter.h:206
#11 NF_HOOK (hook=<value optimised out>, skb=0xcf00e580, in=<value
optimised out>, out=0x0, okfn=0xd0cb9bad <br_handle_frame_finish>) at
include/linux/netfilter.h:228
#12 br_nf_pre_routing (hook=<value optimised out>, skb=0xcf00e580,
in=<value optimised out>, out=0x0, okfn=0xd0cb9bad
<br_handle_frame_finish>) at net/bridge/br_netfilter.c:610
#13 0xc0377247 in ?? ()
// commit //
commit eb1d16414339a6e113d89e2cca2556005d7ce919
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sat Feb 27 19:41:45 2010 +0000
bridge: Add core IGMP snooping support
This patch adds the core functionality of IGMP snooping support
without actually hooking it up. So this patch should be a no-op
as far as the bridge's external behaviour is concerned.
All the new code and data is controlled by the Kconfig option
BRIDGE_IGMP_SNOOPING. A run-time toggle is also available.
The multicast switching is done using an hash table that is
lockless on the read-side through RCU. On the write-side the
new multicast_lock is used for all operations. The hash table
supports dynamic growth/rehashing.
The hash table will be rehashed if any chain length exceeds a
preset limit. If rehashing does not reduce the maximum chain
length then snooping will be disabled.
These features may be added in future (in no particular order):
* IGMPv3 source support
* Non-querier router detection
* IPv6
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: linux-next-20100313-bridge-multicast.diff --]
[-- Type: text/x-patch; name="linux-next-20100313-bridge-multicast.diff", Size: 371 bytes --]
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 12ce1ea..85ca985 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -899,6 +899,8 @@ static void br_multicast_leave_group(struct net_bridge *br,
goto out;
mdb = br->mdb;
+ if (!mdb)
+ goto out;
mp = br_mdb_ip_get(mdb, group);
if (!mp)
goto out;
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
^ permalink raw reply related
* [PATCH] BUG: unable to handle kernel NULL pointer dereference at br_pass_frame_up
From: michael-dev @ 2010-03-14 2:30 UTC (permalink / raw)
To: netdev
[-- Attachment #1.1: Type: text/plain, Size: 5769 bytes --]
Hi,
I'm currently using linux-next and have been running into an OOPs which
I think might be caused by a patch submitted on 2010-02-27.
It's a linux-next kernel from 2010-03-12 on an x86 system and it
OOPs in the bridge module in br_pass_frame_up (called by
br_handle_frame_finish) because brdev cannot be dereferenced (its set to
a non-null value).
Adding some BUG_ON statements revealed that
BR_INPUT_SKB_CB(skb)->brdev == br-dev
(as set in br_handle_frame_finish first)
only holds until br_forward is called.
The next call to br_pass_frame_up then fails.
Digging deeper it seems that br_forward either frees the skb or passes
it to NF_HOOK which will in turn take care of freeing the skb. The same
is holds for br_pass_frame_ip. So it seems as if two independent skb
allocations are required. As far as I can see, commit
b33084be192ee1e347d98bb5c9e38a53d98d35e2 removed skb duplication and so
likely causes this crash. This crash does not happen on 2.6.33.
I've therefore modified br_forward the same way br_flood has been
modified so that the skb is not freed if skb0 is going to be used
and I can confirm that the attached patch resolves the issue for me.
Please don't hesitate to contact me if there are any questions.
Sincerely,
M. Braun
// gdb output //
(gdb) bt full
#0 br_pass_frame_up (skb=0xcf9627c0) at net/bridge/br_input.c:27
indev = <value optimised out>
brdev = 0x1012
#1 br_handle_frame_finish (skb=0xcf9627c0) at net/bridge/br_input.c:99
dest = 0xcfa59dae "ɊU", <incomplete sequence \307>
br = 0xcec46300
dst = <value optimised out>
mdst = <value optimised out>
skb2 = 0xcf9627c0
#2 0xd0cbfef8 in NF_HOOK_THRESH (p=0xcfb3b620, skb=0xcf9627c0) at
include/linux/netfilter.h:206
ret = <value optimised out>
#3 NF_HOOK (p=0xcfb3b620, skb=0xcf9627c0) at include/linux/netfilter.h:228
No locals.
#4 br_handle_frame (p=0xcfb3b620, skb=0xcf9627c0) at
net/bridge/br_input.c:177
dest = 0xcfa59dae "ɊU", <incomplete sequence \307>
#5 0xc035d70f in handle_bridge (skb=0xcf9627c0) at net/core/dev.c:2344
No locals.
#6 netif_receive_skb (skb=0xcf9627c0) at net/core/dev.c:2546
ptype = <value optimised out>
pt_prev = 0x0
orig_dev = 0xcfb65020
null_or_orig = 0x0
null_or_bond = 0x0
ret = -810209540
type = <value optimised out>
#7 0xc035d8c5 in process_backlog (napi=<value optimised out>,
quota=<value optimised out>) at net/core/dev.c:2926
skb = 0x1012
work = 1
start_time = 487863
#8 0xc035da70 in net_rx_action (h=<value optimised out>) at
net/core/dev.c:3057
n = 0xc04fea5c
work = 0
weight = 64
time_limit = 487865
budget = 300
#9 0xc0126041 in __do_softirq () at kernel/softirq.c:219
prev_count = 257
h = 0x1012
pending = 1
max_restart = 10
cpu = 0
#10 0xc01260f2 in do_softirq () at kernel/softirq.c:266
flags = 582
#11 0xc035df5f in netif_rx_ni (skb=<value optimised out>) at
net/core/dev.c:2241
err = 0
#12 0xd0cdc226 in tun_get_user (iocb=<value optimised out>,
iv=0xcfb2ff54, count=<value optimised out>, pos=0) at drivers/net/tun.c:666
len = 64
align = 2
gso = {flags = 0 '\000', gso_type = 0 '\000', hdr_len = 0,
gso_size = 0, csum_start = 0, csum_offset = 0}
pi = {flags = 0, proto = 8}
skb = 0xcf9627c0
offset = 0
#13 tun_chr_aio_write (iocb=<value optimised out>, iv=0xcfb2ff54,
count=<value optimised out>, pos=0) at drivers/net/tun.c:686
file = <value optimised out>
tun = 0xcfb10300
result = 64
#14 0xc017bb12 in do_sync_write (filp=0xcf978300, buf=<value optimised
out>, len=<value optimised out>, ppos=0xcfb2ff98) at fs/read_write.c:318
iov = {iov_base = 0xbfb4b478, iov_len = 64}
kiocb = {ki_run_list = {next = 0xcfb2fee0, prev = 0x4}, ki_flags
= 0, ki_users = 1, ki_key = 4294967295, ki_filp = 0xcf978300, ki_ctx =
0x0, ki_cancel = 0, ki_retry = 0, ki_dtor = 0, ki_obj = {user =
0xcfb089c0, tsk = 0xcfb089c0}, ki_user_data = 0, ki_pos = 0,
private = 0xc04d9e40, ki_opcode = 787, ki_nbytes = 3484614480,
ki_buf = 0xc013c430
"\203\304\024[^_]\303U\211\345WVS\203\354\020\203=\fdP\300", ki_left =
64, ki_inline_vec = {iov_base = 0xcfb2e000, iov_len = 0}, ki_iovec =
0xcfb2ff50, ki_nr_segs = 3484614336,
ki_cur_seg = 16, ki_list = {next = 0xcfb2ff5c, prev = 0x1},
ki_eventfd = 0xcf382730}
ret = <value optimised out>
#15 0xc017c43c in vfs_write (file=0xcf978300, buf=0xbfb4b478 "",
count=3484757756, pos=0xcfb2ff98) at fs/read_write.c:347
ret = <value optimised out>
#16 0xc017c561 in sys_write (fd=4, buf=0xbfb4b478 "", count=64) at
fs/read_write.c:399
pos = 0
file = 0xcf978300
ret = -9
fput_needed = 0
#17 0xc03e8471 in ?? () at arch/x86/kernel/entry_32.S:541
No locals.
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) print *brdev
**Cannot access memory at address 0x1012**
// commit //
commit b33084be192ee1e347d98bb5c9e38a53d98d35e2
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sat Feb 27 19:41:41 2010 +0000
bridge: Avoid unnecessary clone on forward path
When the packet is delivered to the local bridge device we may
end up cloning it unnecessarily if no bridge port can receive
the packet in br_flood.
This patch avoids this by moving the skb_clone into br_flood.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: linux-next-20100313-bridge-utils.diff --]
[-- Type: text/x-patch; name="linux-next-20100313-bridge-utils.diff", Size: 2243 bytes --]
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d61e6f7..8347916 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -19,6 +19,10 @@
#include <linux/netfilter_bridge.h>
#include "br_private.h"
+static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
+ void (*__packet_hook)(const struct net_bridge_port *p,
+ struct sk_buff *skb));
+
/* Don't forward packets to originating port or forwarding diasabled */
static inline int should_deliver(const struct net_bridge_port *p,
const struct sk_buff *skb)
@@ -94,14 +98,18 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
}
/* called with rcu_read_lock */
-void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
+void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
{
if (should_deliver(to, skb)) {
- __br_forward(to, skb);
+ if (skb0)
+ deliver_clone(to, skb, __br_forward);
+ else
+ __br_forward(to, skb);
return;
}
- kfree_skb(skb);
+ if (!skb0)
+ kfree_skb(skb);
}
static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 53b3985..08a72e6 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -90,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
if (skb) {
if (dst)
- br_forward(dst->dst, skb);
+ br_forward(dst->dst, skb, skb2);
else
br_flood_forward(br, skb, skb2);
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index fef0384..bfb8feb 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -252,7 +252,7 @@ extern void br_deliver(const struct net_bridge_port *to,
struct sk_buff *skb);
extern int br_dev_queue_push_xmit(struct sk_buff *skb);
extern void br_forward(const struct net_bridge_port *to,
- struct sk_buff *skb);
+ struct sk_buff *skb, struct sk_buff *skb0);
extern int br_forward_finish(struct sk_buff *skb);
extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);
extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
^ permalink raw reply related
* Re: [RFC PATCH net-2.6] net/ethtool: add multiple queue support to {get,set}_ringparams
From: Ben Hutchings @ 2010-03-14 4:21 UTC (permalink / raw)
To: Ajit Khaparde; +Cc: David Miller, jeff, netdev
In-Reply-To: <20100314014335.GA17208@serverengines.com>
On Sun, 2010-03-14 at 07:13 +0530, Ajit Khaparde wrote:
> With network devices and hence device drivers supporting
> multiple Tx and Rx rings, currently there is no way for
> ethtool to specify which Tx/Rx ring the user wants to get/set.
> This patch enhances the {get,set}_ringparams by allowing
> the user to specify the Tx/Rx ring id of interest.
> Please review.
[...]
So long as queue selection is done using a hash of the flow parameters,
there is no sense in setting different sizes for different queues. If
drivers use additional queues that are not selected in this way and
which may require different sizes, that information also needs to be
exposed through ethtool (and perhaps to the networking core).
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 00/13] TProxy IPv6 support 2nd round
From: Balazs Scheidler @ 2010-03-14 9:00 UTC (permalink / raw)
To: Amos Jeffries; +Cc: Harald Welte, netfilter-devel, netdev
In-Reply-To: <4B94C57A.5010605@treenet.co.nz>
On Mon, 2010-03-08 at 22:38 +1300, Amos Jeffries wrote:
> Balazs Scheidler wrote:
> > On Sun, 2009-10-25 at 11:16 +0100, Harald Welte wrote:
> >> Dear Balazs,
> >>
> >> as you might have read from other mails (and by the long period of silence),
> >> Patrick McHardy is currently unavailable to perform his usual maintainer
> >> role.
> >>
> >> I personally am too much out of touch with recent developments in
> >> netfitler-land to be able to confidently review your patches...
> >>
> >> So unless somebody else from the team (Jozsef?, Pablo?) feels confident in
> >> ACKing your patchset, I will have to ask for your patience until Patrick is
> >> back and can do it by himself.
> >
> > Thanks for letting me know, hopefully Patrick gets better soon. I've
> > planned another round of the TProxy patches as I got some comments at
> > the previous round I'm yet to address.
> >
> > So no need to hurry.
> >
>
> Just bumping this topic up again.
>
> What is the current status of these patches?
>
> Our release which might make use of them goes into production sites in a
> few weeks and I'm starting to see a little more interest in them from
> our users.
Well, no news ever since. I was backlogged with other stuff, so didn't
push these too much. All I got was two comments to be fixed:
1) indentation should use tabs instead of spaces
2) the IPv6 address detection should be changed to use a function
instead of relying on the first IPv6 address on the interface.
Hopefully I can give this some care in the coming weeks.
--
Bazsi
^ permalink raw reply
* Re: [PATCH 00/13] TProxy IPv6 support 2nd round
From: Amos Jeffries @ 2010-03-14 11:10 UTC (permalink / raw)
To: Balazs Scheidler; +Cc: Harald Welte, netfilter-devel, netdev
In-Reply-To: <1268557230.16066.20.camel@bzorp.balabit>
Balazs Scheidler wrote:
> On Mon, 2010-03-08 at 22:38 +1300, Amos Jeffries wrote:
>> Balazs Scheidler wrote:
>>> On Sun, 2009-10-25 at 11:16 +0100, Harald Welte wrote:
>>>> Dear Balazs,
>>>>
>>>> as you might have read from other mails (and by the long period of silence),
>>>> Patrick McHardy is currently unavailable to perform his usual maintainer
>>>> role.
>>>>
>>>> I personally am too much out of touch with recent developments in
>>>> netfitler-land to be able to confidently review your patches...
>>>>
>>>> So unless somebody else from the team (Jozsef?, Pablo?) feels confident in
>>>> ACKing your patchset, I will have to ask for your patience until Patrick is
>>>> back and can do it by himself.
>>> Thanks for letting me know, hopefully Patrick gets better soon. I've
>>> planned another round of the TProxy patches as I got some comments at
>>> the previous round I'm yet to address.
>>>
>>> So no need to hurry.
>>>
>> Just bumping this topic up again.
>>
>> What is the current status of these patches?
>>
>> Our release which might make use of them goes into production sites in a
>> few weeks and I'm starting to see a little more interest in them from
>> our users.
>
> Well, no news ever since. I was backlogged with other stuff, so didn't
> push these too much. All I got was two comments to be fixed:
>
> 1) indentation should use tabs instead of spaces
>
> 2) the IPv6 address detection should be changed to use a function
> instead of relying on the first IPv6 address on the interface.
>
> Hopefully I can give this some care in the coming weeks.
>
Thank you for that.
AYJ
^ permalink raw reply
* [PATCH] ethtool.h: Add "structs are public" disclaimer comment
From: Joe Perches @ 2010-03-14 16:17 UTC (permalink / raw)
To: David Miller; +Cc: ajitk, ajitkhaparde, jeff, netdev
In-Reply-To: <20100313.181145.211264593.davem@davemloft.net>
On Sat, 2010-03-13 at 18:11 -0800, David Miller wrote:
> For the millionth time, you cannot change these datastructures
> like this without breaking all existing userspace applications
> out there.
Maybe this might help reduce the broken record repetitiveness.
Signed-off-by: Joe Perches <joe@perches.com>
---
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index b33f316..9bd7583 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -10,6 +10,15 @@
* Portions Copyright (C) Sun Microsystems 2008
*/
+/*
+ * Do not submit patches that change the public structs not guarded by
+ * #ifdef __KERNEL__ in this file.
+ *
+ * In case the use of __u8, __u16, __u32 and other reserved types don't
+ * mean much to you, these structs are used by user-space applications
+ * and must not be changed.
+ */
+
#ifndef _LINUX_ETHTOOL_H
#define _LINUX_ETHTOOL_H
^ permalink raw reply related
* Re: [PATCH] ethtool.h: Add "structs are public" disclaimer comment
From: Ben Hutchings @ 2010-03-14 17:50 UTC (permalink / raw)
To: Joe Perches; +Cc: David Miller, ajitk, ajitkhaparde, jeff, netdev
In-Reply-To: <1268583478.30289.94.camel@Joe-Laptop.home>
On Sun, 2010-03-14 at 09:17 -0700, Joe Perches wrote:
> On Sat, 2010-03-13 at 18:11 -0800, David Miller wrote:
> > For the millionth time, you cannot change these datastructures
> > like this without breaking all existing userspace applications
> > out there.
>
> Maybe this might help reduce the broken record repetitiveness.
>
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index b33f316..9bd7583 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -10,6 +10,15 @@
> * Portions Copyright (C) Sun Microsystems 2008
> */
>
> +/*
> + * Do not submit patches that change the public structs not guarded by
> + * #ifdef __KERNEL__ in this file.
> + *
> + * In case the use of __u8, __u16, __u32 and other reserved types don't
> + * mean much to you, these structs are used by user-space applications
> + * and must not be changed.
> + */
This comment is not quite correct: reserved fields may be replaced so
long as the structure size and offsets of other fields stay the same.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH] ethtool.h: Add "structs are public" disclaimer comment
From: Jeff Garzik @ 2010-03-14 18:38 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Joe Perches, David Miller, ajitk, ajitkhaparde, netdev
In-Reply-To: <1268589034.2664.68.camel@localhost>
On 03/14/2010 01:50 PM, Ben Hutchings wrote:
> On Sun, 2010-03-14 at 09:17 -0700, Joe Perches wrote:
>> On Sat, 2010-03-13 at 18:11 -0800, David Miller wrote:
>>> For the millionth time, you cannot change these datastructures
>>> like this without breaking all existing userspace applications
>>> out there.
>>
>> Maybe this might help reduce the broken record repetitiveness.
>>
>> Signed-off-by: Joe Perches<joe@perches.com>
>> ---
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index b33f316..9bd7583 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -10,6 +10,15 @@
>> * Portions Copyright (C) Sun Microsystems 2008
>> */
>>
>> +/*
>> + * Do not submit patches that change the public structs not guarded by
>> + * #ifdef __KERNEL__ in this file.
>> + *
>> + * In case the use of __u8, __u16, __u32 and other reserved types don't
>> + * mean much to you, these structs are used by user-space applications
>> + * and must not be changed.
>> + */
>
> This comment is not quite correct: reserved fields may be replaced so
> long as the structure size and offsets of other fields stay the same.
I don't think we need this in every ABI-related header, though, do we?
Jeff
^ permalink raw reply
* Re: 2.6.34-rc1: bluetooth oops
From: Pavel Machek @ 2010-03-14 20:44 UTC (permalink / raw)
To: Marcel Holtmann, netdev-u79uwXL29TY76Z2rM5mHXA
Cc: kernel list, linux-bluetooth-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1268598500.3897.36.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
Hi!
> > I got this after trying to use bnep for few minutes... Machine locked
> > after that, not sure if it is related.
>
> I can't explain it since we haven't changed the BNEP code. So that might
> be a problem in the networking layer. So posting it to netdev might be a
> good idea.
Ok, I'll try using bnep some more. I had bad problems with cellphone
connection at that point, so maybe it is not easy to repeat, and it
the fact I have not seen it before may not mean much...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCH] ethtool.h: Add "structs are public" disclaimer comment
From: David Miller @ 2010-03-14 22:08 UTC (permalink / raw)
To: joe; +Cc: ajitk, ajitkhaparde, jeff, netdev
In-Reply-To: <1268583478.30289.94.camel@Joe-Laptop.home>
From: Joe Perches <joe@perches.com>
Date: Sun, 14 Mar 2010 09:17:58 -0700
> On Sat, 2010-03-13 at 18:11 -0800, David Miller wrote:
>> For the millionth time, you cannot change these datastructures
>> like this without breaking all existing userspace applications
>> out there.
>
> Maybe this might help reduce the broken record repetitiveness.
>
> Signed-off-by: Joe Perches <joe@perches.com>
That's rediculious. Just about every single file in
include/linux/foo.h has similar stuff.
And we already have a way to document this, the fact that a header
file appears in include/linux/Kbuild shows that it provides userland
interfaces.
And your comment wouldn't help this person at all, they _KNEW_ it
changed userspace, because in the very next patch they patch the
userland tool to change the datastructures too!
^ permalink raw reply
* [PATCH 2/3] gigaset: correct clearing of at_state strings on RING
From: Tilman Schmidt @ 2010-03-14 22:58 UTC (permalink / raw)
To: Karsten Keil, David Miller
Cc: Hansjoerg Lipp, isdn4linux, i4ldeveloper, netdev, linux-kernel,
stable
In-Reply-To: <cover.1268580322.git.tilman@imap.cc>
In RING handling, clear the table of received parameter strings in
a loop like everywhere else, instead of by enumeration which had
already gotten out of sync.
Impact: minor bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
CC: stable@kernel.org
---
Note to -stable: applies correctly to 2.6.33.
drivers/isdn/gigaset/ev-layer.c | 12 ++++--------
1 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index c8f89b7..206c380 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1258,14 +1258,10 @@ static void do_action(int action, struct cardstate *cs,
* note that bcs may be NULL if no B channel is free
*/
at_state2->ConState = 700;
- kfree(at_state2->str_var[STR_NMBR]);
- at_state2->str_var[STR_NMBR] = NULL;
- kfree(at_state2->str_var[STR_ZCPN]);
- at_state2->str_var[STR_ZCPN] = NULL;
- kfree(at_state2->str_var[STR_ZBC]);
- at_state2->str_var[STR_ZBC] = NULL;
- kfree(at_state2->str_var[STR_ZHLC]);
- at_state2->str_var[STR_ZHLC] = NULL;
+ for (i = 0; i < STR_NUM; ++i) {
+ kfree(at_state2->str_var[i]);
+ at_state2->str_var[i] = NULL;
+ }
at_state2->int_var[VAR_ZCTP] = -1;
spin_lock_irqsave(&cs->lock, flags);
--
1.6.5.3.298.g39add
^ permalink raw reply related
* [PATCH 3/3] gigaset: prune use of tty_buffer_request_room
From: Tilman Schmidt @ 2010-03-14 22:58 UTC (permalink / raw)
To: Karsten Keil, David Miller
Cc: Hansjoerg Lipp, Alan Cox, isdn4linux, i4ldeveloper, netdev,
linux-kernel, stable
In-Reply-To: <cover.1268580322.git.tilman@imap.cc>
Calling tty_buffer_request_room() before tty_insert_flip_string()
is unnecessary, costs CPU and for big buffers can mess up the
multi-page allocation avoidance.
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
CC: Alan Cox <alan@lxorguk.ukuu.org.uk>, stable@kernel.org
---
Note to -stable: applies correctly to 2.6.33 with fuzz 2.
drivers/isdn/gigaset/interface.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index a1bcbc2..f0dc6c9 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -628,7 +628,6 @@ void gigaset_if_receive(struct cardstate *cs,
if (tty == NULL)
gig_dbg(DEBUG_IF, "receive on closed device");
else {
- tty_buffer_request_room(tty, len);
tty_insert_flip_string(tty, buffer, len);
tty_flip_buffer_push(tty);
}
--
1.6.5.3.298.g39add
^ permalink raw reply related
* [PATCH 1/3] gigaset: avoid registering CAPI driver more than once
From: Tilman Schmidt @ 2010-03-14 22:58 UTC (permalink / raw)
To: Karsten Keil, David Miller
Cc: Hansjoerg Lipp, isdn4linux, i4ldeveloper, netdev, linux-kernel,
stable
In-Reply-To: <cover.1268580322.git.tilman@imap.cc>
Registering/unregistering the Gigaset CAPI driver when a device is
connected/disconnected causes an Oops when disconnecting two Gigaset
devices in a row, because the same capi_driver structure gets
unregistered twice. Fix by making driver registration/unregistration
a separate operation (empty in the ISDN4Linux case) called when the
main module is loaded/unloaded.
Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
CC: stable@kernel.org
---
Note to -stable: applies correctly to 2.6.33 with fuzz 2 in capi.c.
drivers/isdn/gigaset/capi.c | 44 ++++++++++++++++++++++-----------------
drivers/isdn/gigaset/common.c | 6 +++-
drivers/isdn/gigaset/gigaset.h | 6 +++-
drivers/isdn/gigaset/i4l.c | 28 ++++++++++++++++++-------
4 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 6643d65..4a31962 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -2191,36 +2191,24 @@ static const struct file_operations gigaset_proc_fops = {
.release = single_release,
};
-static struct capi_driver capi_driver_gigaset = {
- .name = "gigaset",
- .revision = "1.0",
-};
-
/**
- * gigaset_isdn_register() - register to LL
+ * gigaset_isdn_regdev() - register device to LL
* @cs: device descriptor structure.
* @isdnid: device name.
*
- * Called by main module to register the device with the LL.
- *
* Return value: 1 for success, 0 for failure
*/
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
struct gigaset_capi_ctr *iif;
int rc;
- pr_info("Kernel CAPI interface\n");
-
iif = kmalloc(sizeof(*iif), GFP_KERNEL);
if (!iif) {
pr_err("%s: out of memory\n", __func__);
return 0;
}
- /* register driver with CAPI (ToDo: what for?) */
- register_capi_driver(&capi_driver_gigaset);
-
/* prepare controller structure */
iif->ctr.owner = THIS_MODULE;
iif->ctr.driverdata = cs;
@@ -2241,7 +2229,6 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
rc = attach_capi_ctr(&iif->ctr);
if (rc) {
pr_err("attach_capi_ctr failed (%d)\n", rc);
- unregister_capi_driver(&capi_driver_gigaset);
kfree(iif);
return 0;
}
@@ -2252,17 +2239,36 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
}
/**
- * gigaset_isdn_unregister() - unregister from LL
+ * gigaset_isdn_unregdev() - unregister device from LL
* @cs: device descriptor structure.
- *
- * Called by main module to unregister the device from the LL.
*/
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
{
struct gigaset_capi_ctr *iif = cs->iif;
detach_capi_ctr(&iif->ctr);
kfree(iif);
cs->iif = NULL;
+}
+
+static struct capi_driver capi_driver_gigaset = {
+ .name = "gigaset",
+ .revision = "1.0",
+};
+
+/**
+ * gigaset_isdn_regdrv() - register driver to LL
+ */
+void gigaset_isdn_regdrv(void)
+{
+ pr_info("Kernel CAPI interface\n");
+ register_capi_driver(&capi_driver_gigaset);
+}
+
+/**
+ * gigaset_isdn_unregdrv() - unregister driver from LL
+ */
+void gigaset_isdn_unregdrv(void)
+{
unregister_capi_driver(&capi_driver_gigaset);
}
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 85de339..bdc01cb 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -507,7 +507,7 @@ void gigaset_freecs(struct cardstate *cs)
case 2: /* error in initcshw */
/* Deregister from LL */
make_invalid(cs, VALID_ID);
- gigaset_isdn_unregister(cs);
+ gigaset_isdn_unregdev(cs);
/* fall through */
case 1: /* error when registering to LL */
@@ -769,7 +769,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->cmdbytes = 0;
gig_dbg(DEBUG_INIT, "setting up iif");
- if (!gigaset_isdn_register(cs, modulename)) {
+ if (!gigaset_isdn_regdev(cs, modulename)) {
pr_err("error registering ISDN device\n");
goto error;
}
@@ -1205,11 +1205,13 @@ static int __init gigaset_init_module(void)
gigaset_debuglevel = DEBUG_DEFAULT;
pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
+ gigaset_isdn_regdrv();
return 0;
}
static void __exit gigaset_exit_module(void)
{
+ gigaset_isdn_unregdrv();
}
module_init(gigaset_init_module);
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 1875ab8..cdd144e 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -675,8 +675,10 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size);
*/
/* Called from common.c for setting up/shutting down with the ISDN subsystem */
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid);
-void gigaset_isdn_unregister(struct cardstate *cs);
+void gigaset_isdn_regdrv(void);
+void gigaset_isdn_unregdrv(void);
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid);
+void gigaset_isdn_unregdev(struct cardstate *cs);
/* Called from hardware module to indicate completion of an skb */
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index f0acb9d..c22e5ac 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -592,15 +592,13 @@ void gigaset_isdn_stop(struct cardstate *cs)
}
/**
- * gigaset_isdn_register() - register to LL
+ * gigaset_isdn_regdev() - register to LL
* @cs: device descriptor structure.
* @isdnid: device name.
*
- * Called by main module to register the device with the LL.
- *
* Return value: 1 for success, 0 for failure
*/
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
isdn_if *iif;
@@ -650,15 +648,29 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
}
/**
- * gigaset_isdn_unregister() - unregister from LL
+ * gigaset_isdn_unregdev() - unregister device from LL
* @cs: device descriptor structure.
- *
- * Called by main module to unregister the device from the LL.
*/
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
{
gig_dbg(DEBUG_CMD, "sending UNLOAD");
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
kfree(cs->iif);
cs->iif = NULL;
}
+
+/**
+ * gigaset_isdn_regdrv() - register driver to LL
+ */
+void gigaset_isdn_regdrv(void)
+{
+ /* nothing to do */
+}
+
+/**
+ * gigaset_isdn_unregdrv() - unregister driver from LL
+ */
+void gigaset_isdn_unregdrv(void)
+{
+ /* nothing to do */
+}
--
1.6.5.3.298.g39add
^ permalink raw reply related
* [PATCH 0/3] gigaset fixes for 2.6.34-rc1
From: Tilman Schmidt @ 2010-03-14 22:58 UTC (permalink / raw)
To: Karsten Keil, David Miller
Cc: Hansjoerg Lipp, Alan Cox, isdn4linux, i4ldeveloper, netdev,
linux-kernel
Karsten, David,
following are three bugfix patches to the Gigaset driver which should
still go into 2.6.34 if possible, and also into the 2.6.33 stable branch.
Thanks,
Tilman
Tilman Schmidt (3):
gigaset: avoid registering CAPI driver more than once
gigaset: correct clearing of at_state strings on RING
gigaset: prune use of tty_buffer_request_room
drivers/isdn/gigaset/capi.c | 44 +++++++++++++++++++++----------------
drivers/isdn/gigaset/common.c | 6 +++-
drivers/isdn/gigaset/ev-layer.c | 12 +++-------
drivers/isdn/gigaset/gigaset.h | 6 +++-
drivers/isdn/gigaset/i4l.c | 28 +++++++++++++++++-------
drivers/isdn/gigaset/interface.c | 1 -
6 files changed, 57 insertions(+), 40 deletions(-)
^ permalink raw reply
* Re: [PATCH 6/13] bridge: Add core IGMP snooping support
From: Paul E. McKenney @ 2010-03-14 23:01 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Herbert Xu, David S. Miller, netdev, Stephen Hemminger
In-Reply-To: <201003111949.52836.arnd@arndb.de>
On Thu, Mar 11, 2010 at 07:49:52PM +0100, Arnd Bergmann wrote:
> Following up on the earlier discussion,
>
> On Monday 08 March 2010, Arnd Bergmann wrote:
> > > Arnd, would it be reasonable to extend your RCU-sparse changes to have
> > > four different pointer namespaces, one for each flavor of RCU? (RCU,
> > > RCU-bh, RCU-sched, and SRCU)? Always a fan of making the computer do
> > > the auditing where reasonable. ;-)
> >
> > Yes, I guess that would be possible. I'd still leave out the rculist
> > from any annotations for now, as this would get even more complex then.
> >
> > One consequence will be the need for new rcu_assign_pointer{,_bh,_sched}
> > macros that check the address space of the first argument, otherwise
> > you'd be able to stick anything in there, including non-__rcu pointers.
>
> I've tested this out now, see the patch below. I needed to add a number
> of interfaces, but it still seems ok. Doing it for all the rculist
> functions most likely would be less so.
>
> This is currently the head of my rcu-annotate branch of playground.git.
> Paul, before I split it up and merge this with the per-subsystem patches,
> can you tell me if this is what you had in mind?
This looks extremely nice!!!
I did note a few questions and a couple of minor change below, but the
API and definitions look quite good.
Search for empty lines to find them. Summary:
o srcu_assign_pointer() should be defined in include/linux/srcu.h.
o SRCU_INIT_POINTER() should be defined in include/linux/srcu.h.
o rcu_dereference_check_sched_domain() can now rely on
rcu_dereference_sched_check() to do the srcu_read_lock_held()
check, so no longer needed at this level.
o kvm_create_vm() should be able to use a single "buses" local
variable rather than an array of them.
Again, good stuff!!! Thank you for taking this on!
> > > This could potentially catch the mismatched call_rcu()s, at least if the
> > > rcu_head could be labeled.
> > ...
> > #define rcu_exchange_call(ptr, new, member, func) \
> > ({ \
> > typeof(new) old = rcu_exchange((ptr),(new)); \
> > if (old) \
> > call_rcu(&(old)->member, (func)); \
> > old; \
> > })
>
> Unfortunately, this did not work out at all. Almost every user follows
> a slightly different pattern for call_rcu, so I did not find a way
> to match the call_rcu calls with the pointers. In particular, the functions
> calling call_rcu() sometimes no longer have access to the 'old' data,
> e.g. in case of synchronize_rcu.
>
> My current take is that static annotations won't help us here.
Thank you for checking it out -- not every idea works out well in
practice, I guess. ;-)
Thanx, Paul
> Arnd
>
> ---
>
> rcu: split up __rcu annotations
>
> This adds separate name spaces for the four distinct types of RCU
> that we use in the kernel, namely __rcu, __rcu_bh, __rcu_sched and
> __srcu.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> ---
> arch/x86/kvm/mmu.c | 6 ++--
> arch/x86/kvm/vmx.c | 2 +-
> drivers/net/macvlan.c | 8 ++--
> include/linux/compiler.h | 6 ++++
> include/linux/kvm_host.h | 4 +-
> include/linux/netdevice.h | 2 +-
> include/linux/rcupdate.h | 68 +++++++++++++++++++++++++++++++++----------
> include/linux/srcu.h | 5 ++-
> include/net/dst.h | 4 +-
> include/net/llc.h | 3 +-
> include/net/sock.h | 2 +-
> include/trace/events/kvm.h | 4 +-
> kernel/cgroup.c | 10 +++---
> kernel/perf_event.c | 8 ++--
> kernel/sched.c | 6 ++--
> kernel/sched_fair.c | 2 +-
> lib/radix-tree.c | 8 ++--
> net/core/filter.c | 4 +-
> net/core/sock.c | 6 ++--
> net/decnet/dn_route.c | 2 +-
> net/ipv4/route.c | 60 +++++++++++++++++++-------------------
> net/ipv4/tcp.c | 4 +-
> net/llc/llc_core.c | 6 ++--
> net/llc/llc_input.c | 2 +-
> virt/kvm/iommu.c | 4 +-
> virt/kvm/kvm_main.c | 56 +++++++++++++++++++-----------------
> 26 files changed, 171 insertions(+), 121 deletions(-)
>
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 741373e..45877ca 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -793,7 +793,7 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
> int retval = 0;
> struct kvm_memslots *slots;
>
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
>
> for (i = 0; i < slots->nmemslots; i++) {
> struct kvm_memory_slot *memslot = &slots->memslots[i];
> @@ -3007,7 +3007,7 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm)
> unsigned int nr_pages = 0;
> struct kvm_memslots *slots;
>
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
> for (i = 0; i < slots->nmemslots; i++)
> nr_pages += slots->memslots[i].npages;
>
> @@ -3282,7 +3282,7 @@ static int count_rmaps(struct kvm_vcpu *vcpu)
> int i, j, k, idx;
>
> idx = srcu_read_lock(&kvm->srcu);
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
> for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
> struct kvm_memory_slot *m = &slots->memslots[i];
> struct kvm_rmap_desc *d;
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 0aec1f3..d0c82ed 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -1513,7 +1513,7 @@ static gva_t rmode_tss_base(struct kvm *kvm)
> struct kvm_memslots *slots;
> gfn_t base_gfn;
>
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
> base_gfn = slots->memslots[0].base_gfn +
> slots->memslots[0].npages - 3;
> return base_gfn << PAGE_SHIFT;
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index 95e1bcc..b958d5a 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -531,15 +531,15 @@ static int macvlan_port_create(struct net_device *dev)
> INIT_LIST_HEAD(&port->vlans);
> for (i = 0; i < MACVLAN_HASH_SIZE; i++)
> INIT_HLIST_HEAD(&port->vlan_hash[i]);
> - rcu_assign_pointer(dev->macvlan_port, port);
> + rcu_assign_pointer_bh(dev->macvlan_port, port);
> return 0;
> }
>
> static void macvlan_port_destroy(struct net_device *dev)
> {
> - struct macvlan_port *port = rcu_dereference_const(dev->macvlan_port);
> + struct macvlan_port *port = rcu_dereference_bh_const(dev->macvlan_port);
>
> - rcu_assign_pointer(dev->macvlan_port, NULL);
> + rcu_assign_pointer_bh(dev->macvlan_port, NULL);
> synchronize_rcu();
> kfree(port);
> }
> @@ -624,7 +624,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
> if (err < 0)
> return err;
> }
> - port = rcu_dereference(lowerdev->macvlan_port);
> + port = rcu_dereference_bh(lowerdev->macvlan_port);
>
> vlan->lowerdev = lowerdev;
> vlan->dev = dev;
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 0ab21c2..d5756d4 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -17,6 +17,9 @@
> # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
> # define __percpu __attribute__((noderef, address_space(3)))
> # define __rcu __attribute__((noderef, address_space(4)))
> +# define __rcu_bh __attribute__((noderef, address_space(5)))
> +# define __rcu_sched __attribute__((noderef, address_space(6)))
> +# define __srcu __attribute__((noderef, address_space(7)))
> extern void __chk_user_ptr(const volatile void __user *);
> extern void __chk_io_ptr(const volatile void __iomem *);
> #else
> @@ -36,6 +39,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
> # define __cond_lock(x,c) (c)
> # define __percpu
> # define __rcu
> +# define __rcu_bh
> +# define __rcu_sched
> +# define __srcu
> #endif
>
> #ifdef __KERNEL__
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 9eb0f9c..bad1787 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -164,7 +164,7 @@ struct kvm {
> raw_spinlock_t requests_lock;
> struct mutex slots_lock;
> struct mm_struct *mm; /* userspace tied to this vm */
> - struct kvm_memslots __rcu *memslots;
> + struct kvm_memslots __srcu *memslots;
> struct srcu_struct srcu;
> #ifdef CONFIG_KVM_APIC_ARCHITECTURE
> u32 bsp_vcpu_id;
> @@ -174,7 +174,7 @@ struct kvm {
> atomic_t online_vcpus;
> struct list_head vm_list;
> struct mutex lock;
> - struct kvm_io_bus __rcu *buses[KVM_NR_BUSES];
> + struct kvm_io_bus __srcu *buses[KVM_NR_BUSES];
> #ifdef CONFIG_HAVE_KVM_EVENTFD
> struct {
> spinlock_t lock;
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index fd7e8de..1b72188 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -949,7 +949,7 @@ struct net_device {
> /* bridge stuff */
> void __rcu *br_port;
> /* macvlan */
> - struct macvlan_port __rcu *macvlan_port;
> + struct macvlan_port __rcu_bh *macvlan_port;
> /* GARP */
> struct garp_port __rcu *garp_port;
>
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> index 03702cc..b4c6f39 100644
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -183,19 +183,33 @@ static inline int rcu_read_lock_sched_held(void)
> * read-side critical section. It is also possible to check for
> * locks being held, for example, by using lockdep_is_held().
> */
> -#define rcu_dereference_check(p, c) \
> +#define __rcu_dereference_check(p, c, space) \
> ({ \
> if (debug_locks && !(c)) \
> lockdep_rcu_dereference(__FILE__, __LINE__); \
> - rcu_dereference_raw(p); \
> + __rcu_dereference_raw(p, space); \
> })
>
> +
> #else /* #ifdef CONFIG_PROVE_RCU */
>
> -#define rcu_dereference_check(p, c) rcu_dereference_raw(p)
> +#define __rcu_dereference_check(p, c, space) \
> + __rcu_dereference_raw(p, space)
>
> #endif /* #else #ifdef CONFIG_PROVE_RCU */
>
> +#define rcu_dereference_check(p, c) \
> + __rcu_dereference_check(p, c, __rcu)
> +
> +#define rcu_dereference_bh_check(p, c) \
> + __rcu_dereference_check(p, rcu_read_lock_bh_held() || (c), __rcu_bh)
> +
> +#define rcu_dereference_sched_check(p, c) \
> + __rcu_dereference_check(p, rcu_read_lock_sched_held() || (c), __rcu_sched)
> +
> +#define srcu_dereference_check(p, c) \
> + __rcu_dereference_check(p, srcu_read_lock_held() || (c), __srcu)
> +
> /**
> * rcu_read_lock - mark the beginning of an RCU read-side critical section.
> *
> @@ -341,13 +355,15 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * exactly which pointers are protected by RCU and checks that
> * the pointer is annotated as __rcu.
> */
> -#define rcu_dereference_raw(p) ({ \
> +#define __rcu_dereference_raw(p, space) ({ \
> typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
> - (void) (((typeof (*p) __rcu *)p) == p); \
> + (void) (((typeof (*p) space *)p) == p); \
> smp_read_barrier_depends(); \
> ((typeof(*p) __force __kernel *)(_________p1)); \
> })
>
> +#define rcu_dereference_raw(p) __rcu_dereference_raw(p, __rcu)
> +
> /**
> * rcu_dereference_const - fetch an __rcu pointer outside of a
> * read-side critical section.
> @@ -360,18 +376,22 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * or in an RCU call.
> */
>
> -#define rcu_dereference_const(p) ({ \
> - (void) (((typeof (*p) __rcu *)p) == p); \
> +#define __rcu_dereference_const(p, space) ({ \
> + (void) (((typeof (*p) space *)p) == p); \
> ((typeof(*p) __force __kernel *)(p)); \
> })
>
> +#define rcu_dereference_const(p) __rcu_dereference_const(p, __rcu)
> +#define rcu_dereference_bh_const(p) __rcu_dereference_const(p, __rcu_bh)
> +#define rcu_dereference_sched_const(p) __rcu_dereference_const(p, __rcu_sched)
> +
> /**
> * rcu_dereference - fetch an RCU-protected pointer, checking for RCU
> *
> * Makes rcu_dereference_check() do the dirty work.
> */
> #define rcu_dereference(p) \
> - rcu_dereference_check(p, rcu_read_lock_held())
> + __rcu_dereference_check(p, rcu_read_lock_held(), __rcu)
>
> /**
> * rcu_dereference_bh - fetch an RCU-protected pointer, checking for RCU-bh
> @@ -379,7 +399,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * Makes rcu_dereference_check() do the dirty work.
> */
> #define rcu_dereference_bh(p) \
> - rcu_dereference_check(p, rcu_read_lock_bh_held())
> + __rcu_dereference_check(p, rcu_read_lock_bh_held(), __rcu_bh)
>
> /**
> * rcu_dereference_sched - fetch RCU-protected pointer, checking for RCU-sched
> @@ -387,7 +407,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * Makes rcu_dereference_check() do the dirty work.
> */
> #define rcu_dereference_sched(p) \
> - rcu_dereference_check(p, rcu_read_lock_sched_held())
> + __rcu_dereference_check(p, rcu_read_lock_sched_held(), __rcu_sched)
>
> /**
> * rcu_assign_pointer - assign (publicize) a pointer to a newly
> @@ -402,12 +422,12 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * code.
> */
>
> -#define rcu_assign_pointer(p, v) \
> +#define __rcu_assign_pointer(p, v, space) \
> ({ \
> if (!__builtin_constant_p(v) || \
> ((v) != NULL)) \
> smp_wmb(); \
> - (p) = (typeof(*v) __force __rcu *)(v); \
> + (p) = (typeof(*v) __force space *)(v); \
> })
>
> /**
> @@ -415,10 +435,17 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> * without barriers.
> * Using this is almost always a bug.
> */
> -#define __rcu_assign_pointer(p, v) \
> - ({ \
> - (p) = (typeof(*v) __force __rcu *)(v); \
> - })
> +#define rcu_assign_pointer(p, v) \
> + __rcu_assign_pointer(p, v, __rcu)
> +
> +#define rcu_assign_pointer_bh(p, v) \
> + __rcu_assign_pointer(p, v, __rcu_bh)
> +
> +#define rcu_assign_pointer_sched(p, v) \
> + __rcu_assign_pointer(p, v, __rcu_sched)
> +
> +#define srcu_assign_pointer(p, v) \
> + __rcu_assign_pointer(p, v, __srcu)
For consistency, the definition of srcu_assign_pointer() should go into
include/linux/srcu.h.
> /**
> * RCU_INIT_POINTER - initialize an RCU protected member
> @@ -427,6 +454,15 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> #define RCU_INIT_POINTER(p, v) \
> p = (typeof(*v) __force __rcu *)(v)
>
> +#define RCU_INIT_POINTER_BH(p, v) \
> + p = (typeof(*v) __force __rcu_bh *)(v)
> +
> +#define RCU_INIT_POINTER_SCHED(p, v) \
> + p = (typeof(*v) __force __rcu_sched *)(v)
> +
> +#define SRCU_INIT_POINTER(p, v) \
> + p = (typeof(*v) __force __srcu *)(v)
> +
For consistency, the definition of SRCU_INIT_POINTER() should go into
include/linux/srcu.h.
> /* Infrastructure to implement the synchronize_() primitives. */
>
> struct rcu_synchronize {
> diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> index 4d5ecb2..feaf661 100644
> --- a/include/linux/srcu.h
> +++ b/include/linux/srcu.h
> @@ -111,7 +111,10 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)
> * Makes rcu_dereference_check() do the dirty work.
> */
> #define srcu_dereference(p, sp) \
> - rcu_dereference_check(p, srcu_read_lock_held(sp))
> + __rcu_dereference_check(p, srcu_read_lock_held(sp), __srcu)
> +
> +#define srcu_dereference_const(p) \
> + __rcu_dereference_const(p, __srcu)
>
> /**
> * srcu_read_lock - register a new reader for an SRCU-protected structure.
> diff --git a/include/net/dst.h b/include/net/dst.h
> index 5f839aa..bbeaba2 100644
> --- a/include/net/dst.h
> +++ b/include/net/dst.h
> @@ -94,9 +94,9 @@ struct dst_entry {
> unsigned long lastuse;
> union {
> struct dst_entry *next;
> - struct rtable __rcu *rt_next;
> + struct rtable __rcu_bh *rt_next;
> struct rt6_info *rt6_next;
> - struct dn_route *dn_next;
> + struct dn_route __rcu_bh *dn_next;
> };
> };
>
> diff --git a/include/net/llc.h b/include/net/llc.h
> index 8299cb2..5700082 100644
> --- a/include/net/llc.h
> +++ b/include/net/llc.h
> @@ -59,7 +59,8 @@ struct llc_sap {
> int (* rcv_func)(struct sk_buff *skb,
> struct net_device *dev,
> struct packet_type *pt,
> - struct net_device *orig_dev) __rcu;
> + struct net_device *orig_dev)
> + __rcu_bh;
> struct llc_addr laddr;
> struct list_head node;
> spinlock_t sk_lock;
> diff --git a/include/net/sock.h b/include/net/sock.h
> index e07cd78..66d5e09 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -290,7 +290,7 @@ struct sock {
> struct ucred sk_peercred;
> long sk_rcvtimeo;
> long sk_sndtimeo;
> - struct sk_filter __rcu *sk_filter;
> + struct sk_filter __rcu_bh *sk_filter;
> void *sk_protinfo;
> struct timer_list sk_timer;
> ktime_t sk_stamp;
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c
> index fc45694..db3e502 100644
> --- a/kernel/cgroup.c
> +++ b/kernel/cgroup.c
> @@ -1392,7 +1392,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
> root_count++;
>
> sb->s_root->d_fsdata = root_cgrp;
> - __rcu_assign_pointer(root->top_cgroup.dentry, sb->s_root);
> + rcu_assign_pointer(root->top_cgroup.dentry, sb->s_root);
>
> /* Link the top cgroup in this hierarchy into all
> * the css_set objects */
> @@ -3243,7 +3243,7 @@ int __init cgroup_init_early(void)
> css_set_count = 1;
> init_cgroup_root(&rootnode);
> root_count = 1;
> - __rcu_assign_pointer(init_task.cgroups, &init_css_set);
> + rcu_assign_pointer(init_task.cgroups, &init_css_set);
>
> init_css_set_link.cg = &init_css_set;
> init_css_set_link.cgrp = dummytop;
> @@ -3551,7 +3551,7 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
> /* Reassign the task to the init_css_set. */
> task_lock(tsk);
> cg = rcu_dereference_const(tsk->cgroups);
> - __rcu_assign_pointer(tsk->cgroups, &init_css_set);
> + rcu_assign_pointer(tsk->cgroups, &init_css_set);
> task_unlock(tsk);
> if (cg)
> put_css_set_taskexit(cg);
> @@ -3959,8 +3959,8 @@ static int __init cgroup_subsys_init_idr(struct cgroup_subsys *ss)
> return PTR_ERR(newid);
>
> newid->stack[0] = newid->id;
> - __rcu_assign_pointer(newid->css, rootcss);
> - __rcu_assign_pointer(rootcss->id, newid);
> + rcu_assign_pointer(newid->css, rootcss);
> + rcu_assign_pointer(rootcss->id, newid);
> return 0;
> }
>
> diff --git a/kernel/perf_event.c b/kernel/perf_event.c
> index ac8bcbd..e1b65b2 100644
> --- a/kernel/perf_event.c
> +++ b/kernel/perf_event.c
> @@ -1223,8 +1223,8 @@ void perf_event_task_sched_out(struct task_struct *task,
> * XXX do we need a memory barrier of sorts
> * wrt to rcu_dereference() of perf_event_ctxp
> */
> - __rcu_assign_pointer(task->perf_event_ctxp, next_ctx);
> - __rcu_assign_pointer(next->perf_event_ctxp, ctx);
> + rcu_assign_pointer(task->perf_event_ctxp, next_ctx);
> + rcu_assign_pointer(next->perf_event_ctxp, ctx);
> ctx->task = next;
> next_ctx->task = task;
> do_switch = 0;
> @@ -5376,10 +5376,10 @@ int perf_event_init_task(struct task_struct *child)
> */
> cloned_ctx = rcu_dereference(parent_ctx->parent_ctx);
> if (cloned_ctx) {
> - __rcu_assign_pointer(child_ctx->parent_ctx, cloned_ctx);
> + rcu_assign_pointer(child_ctx->parent_ctx, cloned_ctx);
> child_ctx->parent_gen = parent_ctx->parent_gen;
> } else {
> - __rcu_assign_pointer(child_ctx->parent_ctx, parent_ctx);
> + rcu_assign_pointer(child_ctx->parent_ctx, parent_ctx);
> child_ctx->parent_gen = parent_ctx->generation;
> }
> get_ctx(rcu_dereference_const(child_ctx->parent_ctx));
> diff --git a/kernel/sched.c b/kernel/sched.c
> index 05fd61e..83744d6 100644
> --- a/kernel/sched.c
> +++ b/kernel/sched.c
> @@ -528,7 +528,7 @@ struct rq {
>
> #ifdef CONFIG_SMP
> struct root_domain *rd;
> - struct sched_domain __rcu *sd;
> + struct sched_domain __rcu_sched *sd;
>
> unsigned char idle_at_tick;
> /* For active balancing */
> @@ -603,7 +603,7 @@ static inline int cpu_of(struct rq *rq)
> }
>
> #define rcu_dereference_check_sched_domain(p) \
> - rcu_dereference_check((p), \
> + rcu_dereference_sched_check((p), \
> rcu_read_lock_sched_held() || \
> lockdep_is_held(&sched_domains_mutex))
Given your definition, the "rcu_read_lock_sched_held() || \" should now
be able to be deleted, correct?
>
> @@ -6323,7 +6323,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
> sched_domain_debug(sd, cpu);
>
> rq_attach_root(rq, rd);
> - rcu_assign_pointer(rq->sd, sd);
> + rcu_assign_pointer_sched(rq->sd, sd);
> }
>
> /* cpus with isolated domains */
> diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
> index 3e1fd96..5a5ea2c 100644
> --- a/kernel/sched_fair.c
> +++ b/kernel/sched_fair.c
> @@ -3476,7 +3476,7 @@ static void run_rebalance_domains(struct softirq_action *h)
>
> static inline int on_null_domain(int cpu)
> {
> - return !rcu_dereference(cpu_rq(cpu)->sd);
> + return !rcu_dereference_sched(cpu_rq(cpu)->sd);
> }
>
> /*
> diff --git a/lib/radix-tree.c b/lib/radix-tree.c
> index f6ae74c..4c6f149 100644
> --- a/lib/radix-tree.c
> +++ b/lib/radix-tree.c
> @@ -264,7 +264,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
> return -ENOMEM;
>
> /* Increase the height. */
> - __rcu_assign_pointer(node->slots[0],
> + rcu_assign_pointer(node->slots[0],
> radix_tree_indirect_to_ptr(rcu_dereference_const(root->rnode)));
>
> /* Propagate the aggregated tag info into the new root */
> @@ -1090,7 +1090,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
> newptr = rcu_dereference_const(to_free->slots[0]);
> if (root->height > 1)
> newptr = radix_tree_ptr_to_indirect(newptr);
> - __rcu_assign_pointer(root->rnode, newptr);
> + rcu_assign_pointer(root->rnode, newptr);
> root->height--;
> radix_tree_node_free(to_free);
> }
> @@ -1125,7 +1125,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
> slot = rcu_dereference_const(root->rnode);
> if (height == 0) {
> root_tag_clear_all(root);
> - __rcu_assign_pointer(root->rnode, NULL);
> + rcu_assign_pointer(root->rnode, NULL);
> goto out;
> }
> slot = radix_tree_indirect_to_ptr(slot);
> @@ -1183,7 +1183,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
> }
> root_tag_clear_all(root);
> root->height = 0;
> - __rcu_assign_pointer(root->rnode, NULL);
> + rcu_assign_pointer(root->rnode, NULL);
> if (to_free)
> radix_tree_node_free(to_free);
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index d38ef7f..b88675b 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -522,7 +522,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
>
> rcu_read_lock_bh();
> old_fp = rcu_dereference_bh(sk->sk_filter);
> - rcu_assign_pointer(sk->sk_filter, fp);
> + rcu_assign_pointer_bh(sk->sk_filter, fp);
> rcu_read_unlock_bh();
>
> if (old_fp)
> @@ -539,7 +539,7 @@ int sk_detach_filter(struct sock *sk)
> rcu_read_lock_bh();
> filter = rcu_dereference_bh(sk->sk_filter);
> if (filter) {
> - rcu_assign_pointer(sk->sk_filter, NULL);
> + rcu_assign_pointer_bh(sk->sk_filter, NULL);
> sk_filter_delayed_uncharge(sk, filter);
> ret = 0;
> }
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 74242e2..8549387 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1073,11 +1073,11 @@ static void __sk_free(struct sock *sk)
> if (sk->sk_destruct)
> sk->sk_destruct(sk);
>
> - filter = rcu_dereference_check(sk->sk_filter,
> + filter = rcu_dereference_bh_check(sk->sk_filter,
> atomic_read(&sk->sk_wmem_alloc) == 0);
> if (filter) {
> sk_filter_uncharge(sk, filter);
> - rcu_assign_pointer(sk->sk_filter, NULL);
> + rcu_assign_pointer_bh(sk->sk_filter, NULL);
> }
>
> sock_disable_timestamp(sk, SOCK_TIMESTAMP);
> @@ -1167,7 +1167,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
> sock_reset_flag(newsk, SOCK_DONE);
> skb_queue_head_init(&newsk->sk_error_queue);
>
> - filter = rcu_dereference_const(newsk->sk_filter);
> + filter = rcu_dereference_bh_const(newsk->sk_filter);
> if (filter != NULL)
> sk_filter_charge(newsk, filter);
>
> diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
> index a7bf03c..22ec1d1 100644
> --- a/net/decnet/dn_route.c
> +++ b/net/decnet/dn_route.c
> @@ -92,7 +92,7 @@
>
> struct dn_rt_hash_bucket
> {
> - struct dn_route *chain;
> + struct dn_route __rcu_bh *chain;
> spinlock_t lock;
> };
>
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 37bf0d9..99cef80 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -200,7 +200,7 @@ const __u8 ip_tos2prio[16] = {
> */
>
> struct rt_hash_bucket {
> - struct rtable __rcu *chain;
> + struct rtable __rcu_bh *chain;
> };
>
> #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || \
> @@ -731,26 +731,26 @@ static void rt_do_flush(int process_context)
> spin_lock_bh(rt_hash_lock_addr(i));
> #ifdef CONFIG_NET_NS
> {
> - struct rtable __rcu ** prev;
> + struct rtable __rcu_bh ** prev;
> struct rtable * p;
>
> - rth = rcu_dereference_const(rt_hash_table[i].chain);
> + rth = rcu_dereference_bh(rt_hash_table[i].chain);
>
> /* defer releasing the head of the list after spin_unlock */
> - for (tail = rth; tail; tail = rcu_dereference_const(tail->u.dst.rt_next))
> + for (tail = rth; tail; tail = rcu_dereference_bh(tail->u.dst.rt_next))
> if (!rt_is_expired(tail))
> break;
> if (rth != tail)
> - __rcu_assign_pointer(rt_hash_table[i].chain, tail);
> + rcu_assign_pointer_bh(rt_hash_table[i].chain, tail);
>
> /* call rt_free on entries after the tail requiring flush */
> prev = &rt_hash_table[i].chain;
> - for (p = rcu_dereference_const(*prev); p; p = next) {
> - next = rcu_dereference_const(p->u.dst.rt_next);
> + for (p = rcu_dereference_bh(*prev); p; p = next) {
> + next = rcu_dereference_bh(p->u.dst.rt_next);
> if (!rt_is_expired(p)) {
> prev = &p->u.dst.rt_next;
> } else {
> - __rcu_assign_pointer(*prev, next);
> + rcu_assign_pointer_bh(*prev, next);
> rt_free(p);
> }
> }
> @@ -763,7 +763,7 @@ static void rt_do_flush(int process_context)
> spin_unlock_bh(rt_hash_lock_addr(i));
>
> for (; rth != tail; rth = next) {
> - next = rcu_dereference_const(rth->u.dst.rt_next);
> + next = rcu_dereference_bh(rth->u.dst.rt_next);
> rt_free(rth);
> }
> }
> @@ -785,7 +785,7 @@ static void rt_check_expire(void)
> static unsigned int rover;
> unsigned int i = rover, goal;
> struct rtable *rth, *aux;
> - struct rtable __rcu **rthp;
> + struct rtable __rcu_bh **rthp;
> unsigned long samples = 0;
> unsigned long sum = 0, sum2 = 0;
> unsigned long delta;
> @@ -815,8 +815,8 @@ static void rt_check_expire(void)
> continue;
> length = 0;
> spin_lock_bh(rt_hash_lock_addr(i));
> - while ((rth = rcu_dereference_const(*rthp)) != NULL) {
> - prefetch(rcu_dereference_const(rth->u.dst.rt_next));
> + while ((rth = rcu_dereference_bh(*rthp)) != NULL) {
> + prefetch(rcu_dereference_bh(rth->u.dst.rt_next));
> if (rt_is_expired(rth)) {
> *rthp = rth->u.dst.rt_next;
> rt_free(rth);
> @@ -836,14 +836,14 @@ nofree:
> * attributes don't unfairly skew
> * the length computation
> */
> - for (aux = rcu_dereference_const(rt_hash_table[i].chain);;) {
> + for (aux = rcu_dereference_bh(rt_hash_table[i].chain);;) {
> if (aux == rth) {
> length += ONE;
> break;
> }
> if (compare_hash_inputs(&aux->fl, &rth->fl))
> break;
> - aux = rcu_dereference_const(aux->u.dst.rt_next);
> + aux = rcu_dereference_bh(aux->u.dst.rt_next);
> }
> continue;
> }
> @@ -959,7 +959,7 @@ static int rt_garbage_collect(struct dst_ops *ops)
> static int rover;
> static int equilibrium;
> struct rtable *rth;
> - struct rtable __rcu **rthp;
> + struct rtable __rcu_bh **rthp;
> unsigned long now = jiffies;
> int goal;
>
> @@ -1012,7 +1012,7 @@ static int rt_garbage_collect(struct dst_ops *ops)
> k = (k + 1) & rt_hash_mask;
> rthp = &rt_hash_table[k].chain;
> spin_lock_bh(rt_hash_lock_addr(k));
> - while ((rth = rcu_dereference_const(*rthp)) != NULL) {
> + while ((rth = rcu_dereference_bh(*rthp)) != NULL) {
> if (!rt_is_expired(rth) &&
> !rt_may_expire(rth, tmo, expire)) {
> tmo >>= 1;
> @@ -1079,10 +1079,10 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt,
> struct rtable **rp, struct sk_buff *skb)
> {
> struct rtable *rth;
> - struct rtable __rcu **rthp;
> + struct rtable __rcu_bh **rthp;
> unsigned long now;
> struct rtable *cand;
> - struct rtable __rcu **candp;
> + struct rtable __rcu_bh **candp;
> u32 min_score;
> int chain_length;
> int attempts = !in_softirq();
> @@ -1129,7 +1129,7 @@ restart:
> rthp = &rt_hash_table[hash].chain;
>
> spin_lock_bh(rt_hash_lock_addr(hash));
> - while ((rth = rcu_dereference_const(*rthp)) != NULL) {
> + while ((rth = rcu_dereference_bh(*rthp)) != NULL) {
> if (rt_is_expired(rth)) {
> *rthp = rth->u.dst.rt_next;
> rt_free(rth);
> @@ -1143,13 +1143,13 @@ restart:
> * must be visible to another weakly ordered CPU before
> * the insertion at the start of the hash chain.
> */
> - rcu_assign_pointer(rth->u.dst.rt_next,
> + rcu_assign_pointer_bh(rth->u.dst.rt_next,
> rt_hash_table[hash].chain);
> /*
> * Since lookup is lockfree, the update writes
> * must be ordered for consistency on SMP.
> */
> - rcu_assign_pointer(rt_hash_table[hash].chain, rth);
> + rcu_assign_pointer_bh(rt_hash_table[hash].chain, rth);
>
> dst_use(&rth->u.dst, now);
> spin_unlock_bh(rt_hash_lock_addr(hash));
> @@ -1252,7 +1252,7 @@ restart:
> * previous writes to rt are comitted to memory
> * before making rt visible to other CPUS.
> */
> - rcu_assign_pointer(rt_hash_table[hash].chain, rt);
> + rcu_assign_pointer_bh(rt_hash_table[hash].chain, rt);
>
> spin_unlock_bh(rt_hash_lock_addr(hash));
>
> @@ -1325,13 +1325,13 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
>
> static void rt_del(unsigned hash, struct rtable *rt)
> {
> - struct rtable __rcu **rthp;
> + struct rtable __rcu_bh **rthp;
> struct rtable *aux;
>
> rthp = &rt_hash_table[hash].chain;
> spin_lock_bh(rt_hash_lock_addr(hash));
> ip_rt_put(rt);
> - while ((aux = rcu_dereference_const(*rthp)) != NULL) {
> + while ((aux = rcu_dereference_bh(*rthp)) != NULL) {
> if (aux == rt || rt_is_expired(aux)) {
> *rthp = aux->u.dst.rt_next;
> rt_free(aux);
> @@ -1348,7 +1348,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
> int i, k;
> struct in_device *in_dev = in_dev_get(dev);
> struct rtable *rth;
> - struct rtable __rcu **rthp;
> + struct rtable __rcu_bh **rthp;
> __be32 skeys[2] = { saddr, 0 };
> int ikeys[2] = { dev->ifindex, 0 };
> struct netevent_redirect netevent;
> @@ -1384,7 +1384,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
> rthp=&rt_hash_table[hash].chain;
>
> rcu_read_lock();
> - while ((rth = rcu_dereference(*rthp)) != NULL) {
> + while ((rth = rcu_dereference_bh(*rthp)) != NULL) {
> struct rtable *rt;
>
> if (rth->fl.fl4_dst != daddr ||
> @@ -1646,8 +1646,8 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
> rt_genid(net));
>
> rcu_read_lock();
> - for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
> - rth = rcu_dereference(rth->u.dst.rt_next)) {
> + for (rth = rcu_dereference_bh(rt_hash_table[hash].chain); rth;
> + rth = rcu_dereference_bh(rth->u.dst.rt_next)) {
> unsigned short mtu = new_mtu;
>
> if (rth->fl.fl4_dst != daddr ||
> @@ -2287,8 +2287,8 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
> hash = rt_hash(daddr, saddr, iif, rt_genid(net));
>
> rcu_read_lock();
> - for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
> - rth = rcu_dereference(rth->u.dst.rt_next)) {
> + for (rth = rcu_dereference_bh(rt_hash_table[hash].chain); rth;
> + rth = rcu_dereference_bh(rth->u.dst.rt_next)) {
> if (((rth->fl.fl4_dst ^ daddr) |
> (rth->fl.fl4_src ^ saddr) |
> (rth->fl.iif ^ iif) |
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index d8ce05b..003d54f 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -3252,9 +3252,9 @@ void __init tcp_init(void)
> memset(&tcp_secret_two.secrets[0], 0, sizeof(tcp_secret_two.secrets));
> tcp_secret_one.expires = jiffy; /* past due */
> tcp_secret_two.expires = jiffy; /* past due */
> - __rcu_assign_pointer(tcp_secret_generating, &tcp_secret_one);
> + rcu_assign_pointer(tcp_secret_generating, &tcp_secret_one);
> tcp_secret_primary = &tcp_secret_one;
> - __rcu_assign_pointer(tcp_secret_retiring, &tcp_secret_two);
> + rcu_assign_pointer(tcp_secret_retiring, &tcp_secret_two);
> tcp_secret_secondary = &tcp_secret_two;
> }
>
> diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
> index ed7f424..8696677 100644
> --- a/net/llc/llc_core.c
> +++ b/net/llc/llc_core.c
> @@ -50,7 +50,7 @@ static struct llc_sap *__llc_sap_find(unsigned char sap_value)
> {
> struct llc_sap* sap;
>
> - list_for_each_entry(sap, &llc_sap_list, node)
> + list_for_each_entry_rcu(sap, &llc_sap_list, node)
> if (sap->laddr.lsap == sap_value)
> goto out;
> sap = NULL;
> @@ -103,7 +103,7 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
> if (!sap)
> goto out;
> sap->laddr.lsap = lsap;
> - rcu_assign_pointer(sap->rcv_func, func);
> + rcu_assign_pointer_bh(sap->rcv_func, func);
> list_add_tail_rcu(&sap->node, &llc_sap_list);
> out:
> spin_unlock_bh(&llc_sap_list_lock);
> @@ -127,7 +127,7 @@ void llc_sap_close(struct llc_sap *sap)
> list_del_rcu(&sap->node);
> spin_unlock_bh(&llc_sap_list_lock);
>
> - synchronize_rcu();
> + synchronize_rcu_bh();
>
> kfree(sap);
> }
> diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
> index 57ad974..b775530 100644
> --- a/net/llc/llc_input.c
> +++ b/net/llc/llc_input.c
> @@ -179,7 +179,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
> * First the upper layer protocols that don't need the full
> * LLC functionality
> */
> - rcv = rcu_dereference(sap->rcv_func);
> + rcv = rcu_dereference_bh(sap->rcv_func);
> if (rcv) {
> struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
> if (cskb)
> diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
> index 80fd3ad..2ba7048 100644
> --- a/virt/kvm/iommu.c
> +++ b/virt/kvm/iommu.c
> @@ -78,7 +78,7 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
> int i, r = 0;
> struct kvm_memslots *slots;
>
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
>
> for (i = 0; i < slots->nmemslots; i++) {
> r = kvm_iommu_map_pages(kvm, &slots->memslots[i]);
> @@ -217,7 +217,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
> int i;
> struct kvm_memslots *slots;
>
> - slots = rcu_dereference(kvm->memslots);
> + slots = srcu_dereference(kvm->memslots, &kvm->srcu);
>
> for (i = 0; i < slots->nmemslots; i++) {
> kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 548f925..ae28c71 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -372,6 +372,8 @@ static struct kvm *kvm_create_vm(void)
> {
> int r = 0, i;
> struct kvm *kvm = kvm_arch_create_vm();
> + struct kvm_io_bus *buses[KVM_NR_BUSES];
> + struct kvm_memslots *memslots;
This one looks like more that simply an RCU change...
OK, I get it -- you are creating these temporaries in order to avoid
overflowing the line. Never mind!!! ;-)
> if (IS_ERR(kvm))
> goto out;
> @@ -386,14 +388,15 @@ static struct kvm *kvm_create_vm(void)
> #endif
>
> r = -ENOMEM;
> - kvm->memslots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
> + memslots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
> + srcu_assign_pointer(kvm->memslots, memslots);
> if (!kvm->memslots)
> goto out_err;
> if (init_srcu_struct(&kvm->srcu))
> goto out_err;
> for (i = 0; i < KVM_NR_BUSES; i++) {
> - kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus),
> - GFP_KERNEL);
> + buses[i] = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL);
> + srcu_assign_pointer(kvm->buses[i], buses[i]);
But why do you need an array for "buses" instead of only one variable?
> if (!kvm->buses[i]) {
> cleanup_srcu_struct(&kvm->srcu);
> goto out_err;
> @@ -428,8 +431,8 @@ out_err:
> hardware_disable_all();
> out_err_nodisable:
> for (i = 0; i < KVM_NR_BUSES; i++)
> - kfree(kvm->buses[i]);
> - kfree(kvm->memslots);
> + kfree(buses[i]);
OK, I see what you are trying to do. But why not free all the non-NULL
ones from the kvm-> structure, and then use a single "buses" rather than
an array of them? Perhaps running "i" down from whereever the earlier
loop left it, in case it is difficult to zero the underlying kvm->
structure?
Just trying to save a bit of stack space...
> + kfree(memslots);
> kfree(kvm);
> return ERR_PTR(r);
> }
> @@ -464,12 +467,12 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
> void kvm_free_physmem(struct kvm *kvm)
> {
> int i;
> - struct kvm_memslots *slots = kvm->memslots;
> + struct kvm_memslots *slots = srcu_dereference_const(kvm->memslots);
>
> for (i = 0; i < slots->nmemslots; ++i)
> kvm_free_physmem_slot(&slots->memslots[i], NULL);
>
> - kfree(kvm->memslots);
> + kfree(slots);
> }
>
> static void kvm_destroy_vm(struct kvm *kvm)
> @@ -483,7 +486,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
> spin_unlock(&kvm_lock);
> kvm_free_irq_routing(kvm);
> for (i = 0; i < KVM_NR_BUSES; i++)
> - kvm_io_bus_destroy(kvm->buses[i]);
> + kvm_io_bus_destroy(srcu_dereference_const(kvm->buses[i]));
> kvm_coalesced_mmio_free(kvm);
> #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
> mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
> @@ -552,7 +555,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
> if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr)
> goto out;
>
> - memslot = &kvm->memslots->memslots[mem->slot];
> + old_memslots = srcu_dereference(kvm->memslots, &kvm->srcu);
> + memslot = &old_memslots->memslots[mem->slot];
> base_gfn = mem->guest_phys_addr >> PAGE_SHIFT;
> npages = mem->memory_size >> PAGE_SHIFT;
>
> @@ -573,7 +577,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
> /* Check for overlaps */
> r = -EEXIST;
> for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
> - struct kvm_memory_slot *s = &kvm->memslots->memslots[i];
> + struct kvm_memory_slot *s = &old_memslots->memslots[i];
>
> if (s == memslot || !s->npages)
> continue;
> @@ -669,13 +673,13 @@ skip_lpage:
> slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
> if (!slots)
> goto out_free;
> - memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
> + old_memslots = srcu_dereference_const(kvm->memslots);
> + memcpy(slots, old_memslots, sizeof(struct kvm_memslots));
> if (mem->slot >= slots->nmemslots)
> slots->nmemslots = mem->slot + 1;
> slots->memslots[mem->slot].flags |= KVM_MEMSLOT_INVALID;
>
> - old_memslots = kvm->memslots;
> - rcu_assign_pointer(kvm->memslots, slots);
> + srcu_assign_pointer(kvm->memslots, slots);
> synchronize_srcu_expedited(&kvm->srcu);
> /* From this point no new shadow pages pointing to a deleted
> * memslot will be created.
> @@ -705,7 +709,8 @@ skip_lpage:
> slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
> if (!slots)
> goto out_free;
> - memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
> + old_memslots = srcu_dereference_const(kvm->memslots);
> + memcpy(slots, old_memslots, sizeof(struct kvm_memslots));
> if (mem->slot >= slots->nmemslots)
> slots->nmemslots = mem->slot + 1;
>
> @@ -718,8 +723,7 @@ skip_lpage:
> }
>
> slots->memslots[mem->slot] = new;
> - old_memslots = kvm->memslots;
> - rcu_assign_pointer(kvm->memslots, slots);
> + srcu_assign_pointer(kvm->memslots, slots);
> synchronize_srcu_expedited(&kvm->srcu);
>
> kvm_arch_commit_memory_region(kvm, mem, old, user_alloc);
> @@ -775,7 +779,7 @@ int kvm_get_dirty_log(struct kvm *kvm,
> if (log->slot >= KVM_MEMORY_SLOTS)
> goto out;
>
> - memslot = &kvm->memslots->memslots[log->slot];
> + memslot = &srcu_dereference(kvm->memslots, &kvm->srcu)->memslots[log->slot];
> r = -ENOENT;
> if (!memslot->dirty_bitmap)
> goto out;
> @@ -829,7 +833,7 @@ EXPORT_SYMBOL_GPL(kvm_is_error_hva);
> struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn)
> {
> int i;
> - struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
> + struct kvm_memslots *slots = srcu_dereference(kvm->memslots, &kvm->srcu);
>
> for (i = 0; i < slots->nmemslots; ++i) {
> struct kvm_memory_slot *memslot = &slots->memslots[i];
> @@ -851,7 +855,7 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
> int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
> {
> int i;
> - struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
> + struct kvm_memslots *slots = srcu_dereference(kvm->memslots, &kvm->srcu);
>
> gfn = unalias_gfn_instantiation(kvm, gfn);
> for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
> @@ -895,7 +899,7 @@ out:
> int memslot_id(struct kvm *kvm, gfn_t gfn)
> {
> int i;
> - struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
> + struct kvm_memslots *slots = srcu_dereference(kvm->memslots, &kvm->srcu);
> struct kvm_memory_slot *memslot = NULL;
>
> gfn = unalias_gfn(kvm, gfn);
> @@ -1984,7 +1988,7 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> int len, const void *val)
> {
> int i;
> - struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
> + struct kvm_io_bus *bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> for (i = 0; i < bus->dev_count; i++)
> if (!kvm_iodevice_write(bus->devs[i], addr, len, val))
> return 0;
> @@ -1996,7 +2000,7 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> int len, void *val)
> {
> int i;
> - struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
> + struct kvm_io_bus *bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
>
> for (i = 0; i < bus->dev_count; i++)
> if (!kvm_iodevice_read(bus->devs[i], addr, len, val))
> @@ -2010,7 +2014,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> {
> struct kvm_io_bus *new_bus, *bus;
>
> - bus = kvm->buses[bus_idx];
> + bus = srcu_dereference_const(kvm->buses[bus_idx]);
> if (bus->dev_count > NR_IOBUS_DEVS-1)
> return -ENOSPC;
>
> @@ -2019,7 +2023,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> return -ENOMEM;
> memcpy(new_bus, bus, sizeof(struct kvm_io_bus));
> new_bus->devs[new_bus->dev_count++] = dev;
> - rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
> + srcu_assign_pointer(kvm->buses[bus_idx], new_bus);
> synchronize_srcu_expedited(&kvm->srcu);
> kfree(bus);
>
> @@ -2037,7 +2041,7 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> if (!new_bus)
> return -ENOMEM;
>
> - bus = kvm->buses[bus_idx];
> + bus = srcu_dereference_const(kvm->buses[bus_idx]);
> memcpy(new_bus, bus, sizeof(struct kvm_io_bus));
>
> r = -ENOENT;
> @@ -2053,7 +2057,7 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> return r;
> }
>
> - rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
> + srcu_assign_pointer(kvm->buses[bus_idx], new_bus);
> synchronize_srcu_expedited(&kvm->srcu);
> kfree(bus);
> return r;
>
^ permalink raw reply
* [PATCH 0/2] PCI runtime power management for r8169 and e1000e
From: Rafael J. Wysocki @ 2010-03-15 0:31 UTC (permalink / raw)
To: NetDev, Jesse Barnes
Cc: Linux PCI, pm list, Jeff Kirsher, Jesse Brandeburg, e1000-devel,
Francois Romieu, Matthew Garrett
Hi,
The following two patches add basic PCI runtime power management to the r8169
and e1000e drivers.
It works so that the adapter is put into PCI D3 if there's no network cable
attached to it and back into PCI D0 once the cable has been detected.
The feature is disabled by default and it can be enabled by writing "auto" to
the device's /sys/devices/.../power/control file. Writing "on" to this file
disables the feature again.
The patches have been tested on MSI Wind U100 (r8169) and Toshiba Portege
R500 (e1000e).
Thanks,
Rafael
^ permalink raw reply
* [PATCH 1/2] r8169 / PCI / PM: Add simplified runtime PM support (rev. 3)
From: Rafael J. Wysocki @ 2010-03-15 0:33 UTC (permalink / raw)
To: NetDev
Cc: Jesse Barnes, Linux PCI, pm list, Jeff Kirsher, Jesse Brandeburg,
e1000-devel, Francois Romieu, Matthew Garrett
In-Reply-To: <201003150131.59619.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Use the PCI runtime power management framework to add basic PCI
runtime PM support to the r8169 driver. Namely, make the driver
suspend the device when the link is not present and set it up for
generating a wakeup event after the link has been detected again.
[This feature is disabled until the user space enables it with the
help of the /sys/devices/.../power/contol device attribute.]
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/net/r8169.c | 152 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 125 insertions(+), 27 deletions(-)
Index: linux-2.6/drivers/net/r8169.c
===================================================================
--- linux-2.6.orig/drivers/net/r8169.c
+++ linux-2.6/drivers/net/r8169.c
@@ -23,6 +23,7 @@
#include <linux/tcp.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -504,6 +505,7 @@ struct rtl8169_private {
struct mii_if_info mii;
struct rtl8169_counters counters;
+ u32 saved_wolopts;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -744,53 +746,61 @@ static void rtl8169_check_link_status(st
spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
+ /* This is to cancel a scheduled suspend if there's one. */
+ pm_request_resume(&tp->pci_dev->dev);
netif_carrier_on(dev);
netif_info(tp, ifup, dev, "link up\n");
} else {
netif_carrier_off(dev);
netif_info(tp, ifdown, dev, "link down\n");
+ pm_schedule_suspend(&tp->pci_dev->dev, 100);
}
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
+
+static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
{
- struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
u8 options;
-
- wol->wolopts = 0;
-
-#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
- wol->supported = WAKE_ANY;
-
- spin_lock_irq(&tp->lock);
+ u32 wolopts = 0;
options = RTL_R8(Config1);
if (!(options & PMEnable))
- goto out_unlock;
+ return 0;
options = RTL_R8(Config3);
if (options & LinkUp)
- wol->wolopts |= WAKE_PHY;
+ wolopts |= WAKE_PHY;
if (options & MagicPacket)
- wol->wolopts |= WAKE_MAGIC;
+ wolopts |= WAKE_MAGIC;
options = RTL_R8(Config5);
if (options & UWF)
- wol->wolopts |= WAKE_UCAST;
+ wolopts |= WAKE_UCAST;
if (options & BWF)
- wol->wolopts |= WAKE_BCAST;
+ wolopts |= WAKE_BCAST;
if (options & MWF)
- wol->wolopts |= WAKE_MCAST;
+ wolopts |= WAKE_MCAST;
-out_unlock:
- spin_unlock_irq(&tp->lock);
+ return wolopts;
}
-static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
+
+ spin_lock_irq(&tp->lock);
+
+ wol->supported = WAKE_ANY;
+ wol->wolopts = __rtl8169_get_wol(tp);
+
+ spin_unlock_irq(&tp->lock);
+}
+
+static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
+{
void __iomem *ioaddr = tp->mmio_addr;
unsigned int i;
static const struct {
@@ -807,23 +817,29 @@ static int rtl8169_set_wol(struct net_de
{ WAKE_ANY, Config5, LanWake }
};
- spin_lock_irq(&tp->lock);
-
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < ARRAY_SIZE(cfg); i++) {
u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
- if (wol->wolopts & cfg[i].opt)
+ if (wolopts & cfg[i].opt)
options |= cfg[i].mask;
RTL_W8(cfg[i].reg, options);
}
RTL_W8(Cfg9346, Cfg9346_Lock);
+}
+
+static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ spin_lock_irq(&tp->lock);
if (wol->wolopts)
tp->features |= RTL_FEATURE_WOL;
else
tp->features &= ~RTL_FEATURE_WOL;
+ __rtl8169_set_wol(tp, wol->wolopts);
device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
spin_unlock_irq(&tp->lock);
@@ -3189,6 +3205,12 @@ rtl8169_init_one(struct pci_dev *pdev, c
device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
+ if (pci_dev_run_wake(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
+ pm_runtime_idle(&pdev->dev);
+
out:
return rc;
@@ -3211,10 +3233,18 @@ static void __devexit rtl8169_remove_one
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
+ pm_runtime_get_sync(&pdev->dev);
+
flush_scheduled_work();
unregister_netdev(dev);
+ if (pci_dev_run_wake(pdev)) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ }
+ pm_runtime_put_noidle(&pdev->dev);
+
/* restore original MAC address */
rtl_rar_set(tp, dev->perm_addr);
@@ -3237,6 +3267,7 @@ static int rtl8169_open(struct net_devic
struct pci_dev *pdev = tp->pci_dev;
int retval = -ENOMEM;
+ pm_runtime_get_sync(&pdev->dev);
rtl8169_set_rxbufsize(tp, dev);
@@ -3247,7 +3278,7 @@ static int rtl8169_open(struct net_devic
tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
&tp->TxPhyAddr);
if (!tp->TxDescArray)
- goto out;
+ goto err_pm_runtime_put;
tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
&tp->RxPhyAddr);
@@ -3274,6 +3305,9 @@ static int rtl8169_open(struct net_devic
rtl8169_request_timer(dev);
+ tp->saved_wolopts = 0;
+ pm_runtime_put_noidle(&pdev->dev);
+
rtl8169_check_link_status(dev, tp, tp->mmio_addr);
out:
return retval;
@@ -3283,9 +3317,13 @@ err_release_ring_2:
err_free_rx_1:
pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
tp->RxPhyAddr);
+ tp->RxDescArray = NULL;
err_free_tx_0:
pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
tp->TxPhyAddr);
+ tp->TxDescArray = NULL;
+err_pm_runtime_put:
+ pm_runtime_put_noidle(&pdev->dev);
goto out;
}
@@ -4692,6 +4730,8 @@ static int rtl8169_close(struct net_devi
struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev;
+ pm_runtime_get_sync(&pdev->dev);
+
/* update counters before going down */
rtl8169_update_counters(dev);
@@ -4706,6 +4746,8 @@ static int rtl8169_close(struct net_devi
tp->TxDescArray = NULL;
tp->RxDescArray = NULL;
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
}
@@ -4804,21 +4846,74 @@ static int rtl8169_suspend(struct device
return 0;
}
+static void __rtl8169_resume(struct net_device *dev)
+{
+ netif_device_attach(dev);
+ rtl8169_schedule_work(dev, rtl8169_reset_task);
+}
+
static int rtl8169_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
- if (!netif_running(dev))
- goto out;
+ if (netif_running(dev))
+ __rtl8169_resume(dev);
- netif_device_attach(dev);
+ return 0;
+}
+
+static int rtl8169_runtime_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (!tp->TxDescArray)
+ return 0;
+
+ spin_lock_irq(&tp->lock);
+ tp->saved_wolopts = __rtl8169_get_wol(tp);
+ __rtl8169_set_wol(tp, WAKE_ANY);
+ spin_unlock_irq(&tp->lock);
+
+ rtl8169_net_suspend(dev);
+
+ return 0;
+}
+
+static int rtl8169_runtime_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (!tp->TxDescArray)
+ return 0;
+
+ spin_lock_irq(&tp->lock);
+ __rtl8169_set_wol(tp, tp->saved_wolopts);
+ tp->saved_wolopts = 0;
+ spin_unlock_irq(&tp->lock);
+
+ __rtl8169_resume(dev);
- rtl8169_schedule_work(dev, rtl8169_reset_task);
-out:
return 0;
}
+static int rtl8169_runtime_idle(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (!tp->TxDescArray)
+ return 0;
+
+ rtl8169_check_link_status(dev, tp, tp->mmio_addr);
+ return -EBUSY;
+}
+
static const struct dev_pm_ops rtl8169_pm_ops = {
.suspend = rtl8169_suspend,
.resume = rtl8169_resume,
@@ -4826,6 +4921,9 @@ static const struct dev_pm_ops rtl8169_p
.thaw = rtl8169_resume,
.poweroff = rtl8169_suspend,
.restore = rtl8169_resume,
+ .runtime_suspend = rtl8169_runtime_suspend,
+ .runtime_resume = rtl8169_runtime_resume,
+ .runtime_idle = rtl8169_runtime_idle,
};
#define RTL8169_PM_OPS (&rtl8169_pm_ops)
^ permalink raw reply
* [PATCH 2/2] e1000e / PCI / PM: Add basic runtime PM support (rev. 4)
From: Rafael J. Wysocki @ 2010-03-15 0:35 UTC (permalink / raw)
To: NetDev
Cc: Matthew Garrett, e1000-devel, Linux PCI, Jesse Brandeburg,
Jesse Barnes, Jeff Kirsher, Francois Romieu, pm list
In-Reply-To: <201003150131.59619.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Use the PCI runtime power management framework to add basic PCI
runtime PM support to the e1000e driver. Namely, make the driver
suspend the device when the link is off and set it up for generating
a wakeup event after the link has been detected again. [This
feature is disabled until the user space enables it with the help of
the /sys/devices/.../power/contol device attribute.]
Based on a patch from Matthew Garrett.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/net/e1000e/e1000.h | 5 +
drivers/net/e1000e/netdev.c | 160 ++++++++++++++++++++++++++++++++++++--------
2 files changed, 138 insertions(+), 27 deletions(-)
Index: linux-2.6/drivers/net/e1000e/netdev.c
===================================================================
--- linux-2.6.orig/drivers/net/e1000e/netdev.c
+++ linux-2.6/drivers/net/e1000e/netdev.c
@@ -44,6 +44,7 @@
#include <linux/cpu.h>
#include <linux/smp.h>
#include <linux/pm_qos_params.h>
+#include <linux/pm_runtime.h>
#include <linux/aer.h>
#include "e1000.h"
@@ -3083,12 +3084,15 @@ static int e1000_open(struct net_device
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
int err;
/* disallow open during test */
if (test_bit(__E1000_TESTING, &adapter->state))
return -EBUSY;
+ pm_runtime_get_sync(&pdev->dev);
+
netif_carrier_off(netdev);
/* allocate transmit descriptors */
@@ -3149,6 +3153,9 @@ static int e1000_open(struct net_device
netif_start_queue(netdev);
+ adapter->idle_check = true;
+ pm_runtime_put(&pdev->dev);
+
/* fire a link status change interrupt to start the watchdog */
ew32(ICS, E1000_ICS_LSC);
@@ -3162,6 +3169,7 @@ err_setup_rx:
e1000e_free_tx_resources(adapter);
err_setup_tx:
e1000e_reset(adapter);
+ pm_runtime_put_sync(&pdev->dev);
return err;
}
@@ -3180,11 +3188,17 @@ err_setup_tx:
static int e1000_close(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
- e1000e_down(adapter);
+
+ pm_runtime_get_sync(&pdev->dev);
+
+ if (!test_bit(__E1000_DOWN, &adapter->state)) {
+ e1000e_down(adapter);
+ e1000_free_irq(adapter);
+ }
e1000_power_down_phy(adapter);
- e1000_free_irq(adapter);
e1000e_free_tx_resources(adapter);
e1000e_free_rx_resources(adapter);
@@ -3206,6 +3220,8 @@ static int e1000_close(struct net_device
if (adapter->flags & FLAG_HAS_AMT)
e1000_release_hw_control(adapter);
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
}
/**
@@ -3550,6 +3566,9 @@ static void e1000_watchdog_task(struct w
link = e1000e_has_link(adapter);
if ((netif_carrier_ok(netdev)) && link) {
+ /* Cancel scheduled suspend requests. */
+ pm_runtime_resume(netdev->dev.parent);
+
e1000e_enable_receives(adapter);
goto link_up;
}
@@ -3561,6 +3580,10 @@ static void e1000_watchdog_task(struct w
if (link) {
if (!netif_carrier_ok(netdev)) {
bool txb2b = 1;
+
+ /* Cancel scheduled suspend requests. */
+ pm_runtime_resume(netdev->dev.parent);
+
/* update snapshot of PHY registers on LSC */
e1000_phy_read_status(adapter);
mac->ops.get_link_up_info(&adapter->hw,
@@ -3676,6 +3699,9 @@ static void e1000_watchdog_task(struct w
if (adapter->flags & FLAG_RX_NEEDS_RESTART)
schedule_work(&adapter->reset_task);
+ else
+ pm_schedule_suspend(netdev->dev.parent,
+ LINK_TIMEOUT);
}
}
@@ -4473,13 +4499,15 @@ out:
return retval;
}
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
+static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
+ bool runtime)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u32 ctrl, ctrl_ext, rctl, status;
- u32 wufc = adapter->wol;
+ /* Runtime suspend should only enable wakeup for link changes */
+ u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
int retval = 0;
netif_device_detach(netdev);
@@ -4637,41 +4665,65 @@ static void e1000e_disable_l1aspm(struct
}
#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static bool e1000e_pm_ready(struct e1000_adapter *adapter)
+{
+ return !!adapter->tx_ring->buffer_info;
+}
+
+static int e1000_idle(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ if (!e1000e_pm_ready(adapter))
+ return 0;
+
+ if (adapter->idle_check) {
+ adapter->idle_check = false;
+ if (!e1000e_has_link(adapter))
+ pm_schedule_suspend(dev, MSEC_PER_SEC);
+ }
+
+ return -EBUSY;
+}
+
+static int e1000_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
int retval;
bool wake;
- retval = __e1000_shutdown(pdev, &wake);
+ retval = __e1000_shutdown(pdev, &wake, false);
if (!retval)
e1000_complete_shutdown(pdev, true, wake);
return retval;
}
-static int e1000_resume(struct pci_dev *pdev)
+static int e1000_runtime_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
- u32 err;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_save_state(pdev);
- e1000e_disable_l1aspm(pdev);
+ if (e1000e_pm_ready(adapter)) {
+ bool wake;
- err = pci_enable_device_mem(pdev);
- if (err) {
- dev_err(&pdev->dev,
- "Cannot enable PCI device from suspend\n");
- return err;
+ __e1000_shutdown(pdev, &wake, true);
}
- pci_set_master(pdev);
+ return 0;
+}
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+static int __e1000_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 err;
+
+ e1000e_disable_l1aspm(pdev);
e1000e_set_interrupt_capability(adapter);
if (netif_running(netdev)) {
@@ -4730,13 +4782,38 @@ static int e1000_resume(struct pci_dev *
return 0;
}
+
+static int e1000_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ if (e1000e_pm_ready(adapter))
+ adapter->idle_check = true;
+
+ return __e1000_resume(pdev);
+}
+
+static int e1000_runtime_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ if (!e1000e_pm_ready(adapter))
+ return 0;
+
+ adapter->idle_check = !dev->power.runtime_auto;
+ return __e1000_resume(pdev);
+}
#endif
static void e1000_shutdown(struct pci_dev *pdev)
{
bool wake = false;
- __e1000_shutdown(pdev, &wake);
+ __e1000_shutdown(pdev, &wake, false);
if (system_state == SYSTEM_POWER_OFF)
e1000_complete_shutdown(pdev, false, wake);
@@ -4809,8 +4886,8 @@ static pci_ers_result_t e1000_io_slot_re
result = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_set_master(pdev);
+ pdev->state_saved = true;
pci_restore_state(pdev);
- pci_save_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -5217,6 +5294,12 @@ static int __devinit e1000_probe(struct
e1000_print_device_info(adapter);
+ if (pci_dev_run_wake(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
+ pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
+
return 0;
err_register:
@@ -5259,12 +5342,16 @@ static void __devexit e1000_remove(struc
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ bool down = test_bit(__E1000_DOWN, &adapter->state);
+
+ pm_runtime_get_sync(&pdev->dev);
/*
* flush_scheduled work may reschedule our watchdog task, so
* explicitly disable watchdog tasks from being rescheduled
*/
- set_bit(__E1000_DOWN, &adapter->state);
+ if (!down)
+ set_bit(__E1000_DOWN, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
@@ -5278,8 +5365,17 @@ static void __devexit e1000_remove(struc
if (!(netdev->flags & IFF_UP))
e1000_power_down_phy(adapter);
+ /* Don't lie to e1000_close() down the road. */
+ if (!down)
+ clear_bit(__E1000_DOWN, &adapter->state);
unregister_netdev(netdev);
+ if (pci_dev_run_wake(pdev)) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ }
+ pm_runtime_put_noidle(&pdev->dev);
+
/*
* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
@@ -5379,6 +5475,18 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
+static const struct dev_pm_ops e1000_pm_ops = {
+ .suspend = e1000_suspend,
+ .resume = e1000_resume,
+ .freeze = e1000_suspend,
+ .thaw = e1000_resume,
+ .poweroff = e1000_suspend,
+ .restore = e1000_resume,
+ .runtime_suspend = e1000_runtime_suspend,
+ .runtime_resume = e1000_runtime_resume,
+ .runtime_idle = e1000_idle,
+};
+
/* PCI Device API Driver */
static struct pci_driver e1000_driver = {
.name = e1000e_driver_name,
@@ -5386,9 +5494,7 @@ static struct pci_driver e1000_driver =
.probe = e1000_probe,
.remove = __devexit_p(e1000_remove),
#ifdef CONFIG_PM
- /* Power Management Hooks */
- .suspend = e1000_suspend,
- .resume = e1000_resume,
+ .driver.pm = &e1000_pm_ops,
#endif
.shutdown = e1000_shutdown,
.err_handler = &e1000_err_handler
Index: linux-2.6/drivers/net/e1000e/e1000.h
===================================================================
--- linux-2.6.orig/drivers/net/e1000e/e1000.h
+++ linux-2.6/drivers/net/e1000e/e1000.h
@@ -158,6 +158,9 @@ struct e1000_info;
#define HV_M_STATUS_SPEED_1000 0x0200
#define HV_M_STATUS_LINK_UP 0x0040
+/* Time to wait before putting the device into D3 if there's no link (in ms). */
+#define LINK_TIMEOUT 100
+
enum e1000_boards {
board_82571,
board_82572,
@@ -370,6 +373,8 @@ struct e1000_adapter {
struct work_struct update_phy_task;
struct work_struct led_blink_task;
struct work_struct print_hang_task;
+
+ bool idle_check;
};
struct e1000_info {
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: 2.6.34-rc1: rcu lockdep bug?
From: Américo Wang @ 2010-03-15 1:08 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Américo Wang, Eric Dumazet, David Miller, peterz,
linux-kernel, netdev
In-Reply-To: <20100313215838.GB6805@linux.vnet.ibm.com>
On Sat, Mar 13, 2010 at 01:58:38PM -0800, Paul E. McKenney wrote:
>On Sat, Mar 13, 2010 at 01:33:56PM +0800, Américo Wang wrote:
>> On Fri, Mar 12, 2010 at 02:37:38PM +0100, Eric Dumazet wrote:
>> >Le vendredi 12 mars 2010 à 21:11 +0800, Américo Wang a écrit :
>> >
>> >> Oh, but lockdep complains about rcu_read_lock(), it said
>> >> rcu_read_lock() can't be used in softirq context.
>> >>
>> >> Am I missing something?
>> >
>> >Well, lockdep might be dumb, I dont know...
>> >
>> >I suggest you read rcu_read_lock_bh kernel doc :
>> >
>> >/**
>> > * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical
>> >section
>> > *
>> > * This is equivalent of rcu_read_lock(), but to be used when updates
>> > * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
>> > * consider completion of a softirq handler to be a quiescent state,
>> > * a process in RCU read-side critical section must be protected by
>> > * disabling softirqs. Read-side critical sections in interrupt context
>> > * can use just rcu_read_lock().
>> > *
>> > */
>> >
>> >
>> >Last sentence being perfect :
>> >
>> >Read-side critical sections in interrupt context
>> >can use just rcu_read_lock().
>> >
>>
>> Yeah, right, then it is more likely to be a bug of rcu lockdep.
>> Paul is looking at it.
>
>Except that it seems to be working correctly for me...
>
Hmm, then I am confused. The only possibility here is that this is
a lockdep bug...
Thanks for your help!
^ permalink raw reply
* Re: C/R: Checkpoint and restore network namespaces and devices
From: Oren Laadan @ 2010-03-15 2:49 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, den, netdev, davem, ebiederm, benjamin.thery
In-Reply-To: <1267130595-23637-1-git-send-email-danms@us.ibm.com>
Hi Dan,
With this series I get this error when NETNS isn't configured:
(ckpt-v20-rc1)
drivers/net/loopback.c: In function ‘loopback_checkpoint’:
drivers/net/loopback.c:165: error: implicit declaration of function
‘ckpt_netdev_base’
drivers/net/loopback.c:165: warning: assignment makes pointer from integer
without a cast
make[2]: *** [drivers/net/loopback.o] Error 1
make[1]: *** [drivers/net] Error 2
make: *** [drivers] Error 2
Oren.
Dan Smith wrote:
> This patch set adds checkpoint/restart support for network namespaces,
> as well as the network devices within. Currently supports veth, macvlan,
> and loopback device types.
>
> Includes the latest feedback and the new macvlan bits. Rebased on Oren's
> official v19. Changes detailed per patch.
>
> _______________________________________________
> Containers mailing list
> Containers@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/containers
>
^ permalink raw reply
* Re: 2.6.34-rc1: rcu lockdep bug?
From: Américo Wang @ 2010-03-15 3:10 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Américo Wang, Eric Dumazet, David Miller, peterz,
linux-kernel, netdev
In-Reply-To: <20100315010802.GB2735@hack>
2010/3/15 Américo Wang <xiyou.wangcong@gmail.com>:
> On Sat, Mar 13, 2010 at 01:58:38PM -0800, Paul E. McKenney wrote:
>>On Sat, Mar 13, 2010 at 01:33:56PM +0800, Américo Wang wrote:
>>> On Fri, Mar 12, 2010 at 02:37:38PM +0100, Eric Dumazet wrote:
>>> >Le vendredi 12 mars 2010 à 21:11 +0800, Américo Wang a écrit :
>>> >
>>> >> Oh, but lockdep complains about rcu_read_lock(), it said
>>> >> rcu_read_lock() can't be used in softirq context.
>>> >>
>>> >> Am I missing something?
>>> >
>>> >Well, lockdep might be dumb, I dont know...
>>> >
>>> >I suggest you read rcu_read_lock_bh kernel doc :
>>> >
>>> >/**
>>> > * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical
>>> >section
>>> > *
>>> > * This is equivalent of rcu_read_lock(), but to be used when updates
>>> > * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
>>> > * consider completion of a softirq handler to be a quiescent state,
>>> > * a process in RCU read-side critical section must be protected by
>>> > * disabling softirqs. Read-side critical sections in interrupt context
>>> > * can use just rcu_read_lock().
>>> > *
>>> > */
>>> >
>>> >
>>> >Last sentence being perfect :
>>> >
>>> >Read-side critical sections in interrupt context
>>> >can use just rcu_read_lock().
>>> >
>>>
>>> Yeah, right, then it is more likely to be a bug of rcu lockdep.
>>> Paul is looking at it.
>>
>>Except that it seems to be working correctly for me...
>>
>
> Hmm, then I am confused. The only possibility here is that this is
> a lockdep bug...
>
I believe so...
Peter, this looks odd:
kernel: (usbfs_mutex){+.?...}, at: [<ffffffff8146419f>]
netif_receive_skb+0xe7/0x819
netif_receive_skb() never has a chance to take usbfs_mutex. How can this
comes out?
^ permalink raw reply
* [PATCH net-2.6 3/3] jme: Advance driver version number
From: cooldavid @ 2010-03-15 5:15 UTC (permalink / raw)
To: David Miller; +Cc: Guo-Fu Tseng, linux-netdev, Ethan Hsiao
In-Reply-To: <1268630108-10374-2-git-send-email-cooldavid@cooldavid.org>
From: Guo-Fu Tseng <cooldavid@cooldavid.org>
Advance driver version number after some bug fix.
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
---
drivers/net/jme.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index 0ed4924..727a3bf 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -25,7 +25,7 @@
#define __JME_H_INCLUDED__
#define DRV_NAME "jme"
-#define DRV_VERSION "1.0.5"
+#define DRV_VERSION "1.0.6"
#define PFX DRV_NAME ": "
#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
--
1.6.4.4
^ permalink raw reply related
* [PATCH net-2.6 2/3] jme: Adding lock to protect vlgrp structure.
From: cooldavid @ 2010-03-15 5:15 UTC (permalink / raw)
To: David Miller; +Cc: Guo-Fu Tseng, linux-netdev, Ethan Hsiao
In-Reply-To: <1268630108-10374-1-git-send-email-cooldavid@cooldavid.org>
From: Guo-Fu Tseng <cooldavid@cooldavid.org>
Adding a lock to prevent modifying the vlgrp structure while receiving
VLAN packet.
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
---
drivers/net/jme.c | 6 ++++++
drivers/net/jme.h | 1 +
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index cfc7b98..9096bbd 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -942,11 +942,14 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
skb->ip_summed = CHECKSUM_NONE;
if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
+ spin_lock(&jme->vlgrp_lock);
if (jme->vlgrp) {
jme->jme_vlan_rx(skb, jme->vlgrp,
le16_to_cpu(rxdesc->descwb.vlan));
+ spin_unlock(&jme->vlgrp_lock);
NET_STAT(jme).rx_bytes += 4;
} else {
+ spin_unlock(&jme->vlgrp_lock);
dev_kfree_skb(skb);
}
} else {
@@ -2088,7 +2091,9 @@ jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
struct jme_adapter *jme = netdev_priv(netdev);
+ spin_lock_bh(&jme->vlgrp_lock);
jme->vlgrp = grp;
+ spin_unlock_bh(&jme->vlgrp_lock);
}
static void
@@ -2755,6 +2760,7 @@ jme_init_one(struct pci_dev *pdev,
spin_lock_init(&jme->phy_lock);
spin_lock_init(&jme->macaddr_lock);
spin_lock_init(&jme->rxmcs_lock);
+ spin_lock_init(&jme->vlgrp_lock);
atomic_set(&jme->link_changing, 1);
atomic_set(&jme->rx_cleaning, 1);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index c19db91..0ed4924 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -393,6 +393,7 @@ struct jme_adapter {
spinlock_t phy_lock;
spinlock_t macaddr_lock;
spinlock_t rxmcs_lock;
+ spinlock_t vlgrp_lock;
struct tasklet_struct rxempty_task;
struct tasklet_struct rxclean_task;
struct tasklet_struct txclean_task;
--
1.6.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox