diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-29 10:55:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-29 10:55:45 -0400 |
commit | 3dacbdad2401c06b97d8d754974233a70c165536 (patch) | |
tree | dc33467f26190572eabf49f7dcac3cd8aa50a101 | |
parent | 56a50adda49b2020156616c4eb15353e0f9ad7de (diff) | |
parent | ac7c992cac0c8f276aa8e4a8273204a6db707bb3 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (24 commits)
e100: do not go D3 in shutdown unless system is powering off
netfilter: revised locking for x_tables
Bluetooth: Fix connection establishment with low security requirement
Bluetooth: Add different pairing timeout for Legacy Pairing
Bluetooth: Ensure that HCI sysfs add/del is preempt safe
net: Avoid extra wakeups of threads blocked in wait_for_packet()
net: Fix typo in net_device_ops description.
ipv4: Limit size of route cache hash table
Add reference to CAPI 2.0 standard
Documentation/isdn/INTERFACE.CAPI
update Documentation/isdn/00-INDEX
ixgbe: Fix WoL functionality for 82599 KX4 devices
veth: prevent oops caused by netdev destructor
xfrm: wrong hash value for temporary SA
forcedeth: tx timeout fix
net: Fix LL_MAX_HEADER for CONFIG_TR_MODULE
mlx4_en: Handle page allocation failure during receive
mlx4_en: Fix cleanup flow on cq activation
vlan: update vlan carrier state for admin up/down
netfilter: xt_recent: fix stack overread in compat code
...
33 files changed, 795 insertions, 447 deletions
diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index 9fee5f2e5c62..5a2d69989a8c 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX | |||
@@ -2,8 +2,14 @@ | |||
2 | - this file (info on ISDN implementation for Linux) | 2 | - this file (info on ISDN implementation for Linux) |
3 | CREDITS | 3 | CREDITS |
4 | - list of the kind folks that brought you this stuff. | 4 | - list of the kind folks that brought you this stuff. |
5 | HiSax.cert | ||
6 | - information about the ITU approval certification of the HiSax driver. | ||
5 | INTERFACE | 7 | INTERFACE |
6 | - description of Linklevel and Hardwarelevel ISDN interface. | 8 | - description of isdn4linux Link Level and Hardware Level interfaces. |
9 | INTERFACE.fax | ||
10 | - description of the fax subinterface of isdn4linux. | ||
11 | INTERFACE.CAPI | ||
12 | - description of kernel CAPI Link Level to Hardware Level interface. | ||
7 | README | 13 | README |
8 | - general info on what you need and what to do for Linux ISDN. | 14 | - general info on what you need and what to do for Linux ISDN. |
9 | README.FAQ | 15 | README.FAQ |
@@ -12,6 +18,8 @@ README.audio | |||
12 | - info for running audio over ISDN. | 18 | - info for running audio over ISDN. |
13 | README.fax | 19 | README.fax |
14 | - info for using Fax over ISDN. | 20 | - info for using Fax over ISDN. |
21 | README.gigaset | ||
22 | - info on the drivers for Siemens Gigaset ISDN adapters. | ||
15 | README.icn | 23 | README.icn |
16 | - info on the ICN-ISDN-card and its driver. | 24 | - info on the ICN-ISDN-card and its driver. |
17 | README.HiSax | 25 | README.HiSax |
@@ -37,7 +45,8 @@ README.diversion | |||
37 | README.sc | 45 | README.sc |
38 | - info on driver for Spellcaster cards. | 46 | - info on driver for Spellcaster cards. |
39 | README.x25 | 47 | README.x25 |
40 | _ info for running X.25 over ISDN. | 48 | - info for running X.25 over ISDN. |
41 | README.hysdn | 49 | README.hysdn |
42 | - info on driver for Hypercope active HYSDN cards | 50 | - info on driver for Hypercope active HYSDN cards |
43 | 51 | README.mISDN | |
52 | - info on the Modular ISDN subsystem (mISDN). | ||
diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI new file mode 100644 index 000000000000..786d619b36e5 --- /dev/null +++ b/Documentation/isdn/INTERFACE.CAPI | |||
@@ -0,0 +1,213 @@ | |||
1 | Kernel CAPI Interface to Hardware Drivers | ||
2 | ----------------------------------------- | ||
3 | |||
4 | 1. Overview | ||
5 | |||
6 | From the CAPI 2.0 specification: | ||
7 | COMMON-ISDN-API (CAPI) is an application programming interface standard used | ||
8 | to access ISDN equipment connected to basic rate interfaces (BRI) and primary | ||
9 | rate interfaces (PRI). | ||
10 | |||
11 | Kernel CAPI operates as a dispatching layer between CAPI applications and CAPI | ||
12 | hardware drivers. Hardware drivers register ISDN devices (controllers, in CAPI | ||
13 | lingo) with Kernel CAPI to indicate their readiness to provide their service | ||
14 | to CAPI applications. CAPI applications also register with Kernel CAPI, | ||
15 | requesting association with a CAPI device. Kernel CAPI then dispatches the | ||
16 | application registration to an available device, forwarding it to the | ||
17 | corresponding hardware driver. Kernel CAPI then forwards CAPI messages in both | ||
18 | directions between the application and the hardware driver. | ||
19 | |||
20 | Format and semantics of CAPI messages are specified in the CAPI 2.0 standard. | ||
21 | This standard is freely available from http://www.capi.org. | ||
22 | |||
23 | |||
24 | 2. Driver and Device Registration | ||
25 | |||
26 | CAPI drivers optionally register themselves with Kernel CAPI by calling the | ||
27 | Kernel CAPI function register_capi_driver() with a pointer to a struct | ||
28 | capi_driver. This structure must be filled with the name and revision of the | ||
29 | driver, and optionally a pointer to a callback function, add_card(). The | ||
30 | registration can be revoked by calling the function unregister_capi_driver() | ||
31 | with a pointer to the same struct capi_driver. | ||
32 | |||
33 | CAPI drivers must register each of the ISDN devices they control with Kernel | ||
34 | CAPI by calling the Kernel CAPI function attach_capi_ctr() with a pointer to a | ||
35 | struct capi_ctr before they can be used. This structure must be filled with | ||
36 | the names of the driver and controller, and a number of callback function | ||
37 | pointers which are subsequently used by Kernel CAPI for communicating with the | ||
38 | driver. The registration can be revoked by calling the function | ||
39 | detach_capi_ctr() with a pointer to the same struct capi_ctr. | ||
40 | |||
41 | Before the device can be actually used, the driver must fill in the device | ||
42 | information fields 'manu', 'version', 'profile' and 'serial' in the capi_ctr | ||
43 | structure of the device, and signal its readiness by calling capi_ctr_ready(). | ||
44 | From then on, Kernel CAPI may call the registered callback functions for the | ||
45 | device. | ||
46 | |||
47 | If the device becomes unusable for any reason (shutdown, disconnect ...), the | ||
48 | driver has to call capi_ctr_reseted(). This will prevent further calls to the | ||
49 | callback functions by Kernel CAPI. | ||
50 | |||
51 | |||
52 | 3. Application Registration and Communication | ||
53 | |||
54 | Kernel CAPI forwards registration requests from applications (calls to CAPI | ||
55 | operation CAPI_REGISTER) to an appropriate hardware driver by calling its | ||
56 | register_appl() callback function. A unique Application ID (ApplID, u16) is | ||
57 | allocated by Kernel CAPI and passed to register_appl() along with the | ||
58 | parameter structure provided by the application. This is analogous to the | ||
59 | open() operation on regular files or character devices. | ||
60 | |||
61 | After a successful return from register_appl(), CAPI messages from the | ||
62 | application may be passed to the driver for the device via calls to the | ||
63 | send_message() callback function. The CAPI message to send is stored in the | ||
64 | data portion of an skb. Conversely, the driver may call Kernel CAPI's | ||
65 | capi_ctr_handle_message() function to pass a received CAPI message to Kernel | ||
66 | CAPI for forwarding to an application, specifying its ApplID. | ||
67 | |||
68 | Deregistration requests (CAPI operation CAPI_RELEASE) from applications are | ||
69 | forwarded as calls to the release_appl() callback function, passing the same | ||
70 | ApplID as with register_appl(). After return from release_appl(), no CAPI | ||
71 | messages for that application may be passed to or from the device anymore. | ||
72 | |||
73 | |||
74 | 4. Data Structures | ||
75 | |||
76 | 4.1 struct capi_driver | ||
77 | |||
78 | This structure describes a Kernel CAPI driver itself. It is used in the | ||
79 | register_capi_driver() and unregister_capi_driver() functions, and contains | ||
80 | the following non-private fields, all to be set by the driver before calling | ||
81 | register_capi_driver(): | ||
82 | |||
83 | char name[32] | ||
84 | the name of the driver, as a zero-terminated ASCII string | ||
85 | char revision[32] | ||
86 | the revision number of the driver, as a zero-terminated ASCII string | ||
87 | int (*add_card)(struct capi_driver *driver, capicardparams *data) | ||
88 | a callback function pointer (may be NULL) | ||
89 | |||
90 | |||
91 | 4.2 struct capi_ctr | ||
92 | |||
93 | This structure describes an ISDN device (controller) handled by a Kernel CAPI | ||
94 | driver. After registration via the attach_capi_ctr() function it is passed to | ||
95 | all controller specific lower layer interface and callback functions to | ||
96 | identify the controller to operate on. | ||
97 | |||
98 | It contains the following non-private fields: | ||
99 | |||
100 | - to be set by the driver before calling attach_capi_ctr(): | ||
101 | |||
102 | struct module *owner | ||
103 | pointer to the driver module owning the device | ||
104 | |||
105 | void *driverdata | ||
106 | an opaque pointer to driver specific data, not touched by Kernel CAPI | ||
107 | |||
108 | char name[32] | ||
109 | the name of the controller, as a zero-terminated ASCII string | ||
110 | |||
111 | char *driver_name | ||
112 | the name of the driver, as a zero-terminated ASCII string | ||
113 | |||
114 | int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata) | ||
115 | (optional) pointer to a callback function for sending firmware and | ||
116 | configuration data to the device | ||
117 | |||
118 | void (*reset_ctr)(struct capi_ctr *ctrlr) | ||
119 | pointer to a callback function for performing a reset on the device, | ||
120 | releasing all registered applications | ||
121 | |||
122 | void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, | ||
123 | capi_register_params *rparam) | ||
124 | void (*release_appl)(struct capi_ctr *ctrlr, u16 applid) | ||
125 | pointers to callback functions for registration and deregistration of | ||
126 | applications with the device | ||
127 | |||
128 | u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) | ||
129 | pointer to a callback function for sending a CAPI message to the | ||
130 | device | ||
131 | |||
132 | char *(*procinfo)(struct capi_ctr *ctrlr) | ||
133 | pointer to a callback function returning the entry for the device in | ||
134 | the CAPI controller info table, /proc/capi/controller | ||
135 | |||
136 | read_proc_t *ctr_read_proc | ||
137 | pointer to the read_proc callback function for the device's proc file | ||
138 | system entry, /proc/capi/controllers/<n>; will be called with a | ||
139 | pointer to the device's capi_ctr structure as the last (data) argument | ||
140 | |||
141 | - to be filled in before calling capi_ctr_ready(): | ||
142 | |||
143 | u8 manu[CAPI_MANUFACTURER_LEN] | ||
144 | value to return for CAPI_GET_MANUFACTURER | ||
145 | |||
146 | capi_version version | ||
147 | value to return for CAPI_GET_VERSION | ||
148 | |||
149 | capi_profile profile | ||
150 | value to return for CAPI_GET_PROFILE | ||
151 | |||
152 | u8 serial[CAPI_SERIAL_LEN] | ||
153 | value to return for CAPI_GET_SERIAL | ||
154 | |||
155 | |||
156 | 5. Lower Layer Interface Functions | ||
157 | |||
158 | (declared in <linux/isdn/capilli.h>) | ||
159 | |||
160 | void register_capi_driver(struct capi_driver *drvr) | ||
161 | void unregister_capi_driver(struct capi_driver *drvr) | ||
162 | register/unregister a driver with Kernel CAPI | ||
163 | |||
164 | int attach_capi_ctr(struct capi_ctr *ctrlr) | ||
165 | int detach_capi_ctr(struct capi_ctr *ctrlr) | ||
166 | register/unregister a device (controller) with Kernel CAPI | ||
167 | |||
168 | void capi_ctr_ready(struct capi_ctr *ctrlr) | ||
169 | void capi_ctr_reseted(struct capi_ctr *ctrlr) | ||
170 | signal controller ready/not ready | ||
171 | |||
172 | void capi_ctr_suspend_output(struct capi_ctr *ctrlr) | ||
173 | void capi_ctr_resume_output(struct capi_ctr *ctrlr) | ||
174 | signal suspend/resume | ||
175 | |||
176 | void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, | ||
177 | struct sk_buff *skb) | ||
178 | pass a received CAPI message to Kernel CAPI | ||
179 | for forwarding to the specified application | ||
180 | |||
181 | |||
182 | 6. Helper Functions and Macros | ||
183 | |||
184 | Library functions (from <linux/isdn/capilli.h>): | ||
185 | |||
186 | void capilib_new_ncci(struct list_head *head, u16 applid, | ||
187 | u32 ncci, u32 winsize) | ||
188 | void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) | ||
189 | void capilib_release_appl(struct list_head *head, u16 applid) | ||
190 | void capilib_release(struct list_head *head) | ||
191 | void capilib_data_b3_conf(struct list_head *head, u16 applid, | ||
192 | u32 ncci, u16 msgid) | ||
193 | u16 capilib_data_b3_req(struct list_head *head, u16 applid, | ||
194 | u32 ncci, u16 msgid) | ||
195 | |||
196 | |||
197 | Macros to extract/set element values from/in a CAPI message header | ||
198 | (from <linux/isdn/capiutil.h>): | ||
199 | |||
200 | Get Macro Set Macro Element (Type) | ||
201 | |||
202 | CAPIMSG_LEN(m) CAPIMSG_SETLEN(m, len) Total Length (u16) | ||
203 | CAPIMSG_APPID(m) CAPIMSG_SETAPPID(m, applid) ApplID (u16) | ||
204 | CAPIMSG_COMMAND(m) CAPIMSG_SETCOMMAND(m,cmd) Command (u8) | ||
205 | CAPIMSG_SUBCOMMAND(m) CAPIMSG_SETSUBCOMMAND(m, cmd) Subcommand (u8) | ||
206 | CAPIMSG_CMD(m) - Command*256 | ||
207 | + Subcommand (u16) | ||
208 | CAPIMSG_MSGID(m) CAPIMSG_SETMSGID(m, msgid) Message Number (u16) | ||
209 | |||
210 | CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI | ||
211 | (u32) | ||
212 | CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) | ||
213 | |||
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 5360c4fd4739..f33170368cd1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c | |||
@@ -270,6 +270,15 @@ static void recv_handler(struct work_struct *work) | |||
270 | mutex_unlock(&ap->recv_mtx); | 270 | mutex_unlock(&ap->recv_mtx); |
271 | } | 271 | } |
272 | 272 | ||
273 | /** | ||
274 | * capi_ctr_handle_message() - handle incoming CAPI message | ||
275 | * @card: controller descriptor structure. | ||
276 | * @appl: application ID. | ||
277 | * @skb: message. | ||
278 | * | ||
279 | * Called by hardware driver to pass a CAPI message to the application. | ||
280 | */ | ||
281 | |||
273 | void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) | 282 | void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) |
274 | { | 283 | { |
275 | struct capi20_appl *ap; | 284 | struct capi20_appl *ap; |
@@ -348,6 +357,13 @@ error: | |||
348 | 357 | ||
349 | EXPORT_SYMBOL(capi_ctr_handle_message); | 358 | EXPORT_SYMBOL(capi_ctr_handle_message); |
350 | 359 | ||
360 | /** | ||
361 | * capi_ctr_ready() - signal CAPI controller ready | ||
362 | * @card: controller descriptor structure. | ||
363 | * | ||
364 | * Called by hardware driver to signal that the controller is up and running. | ||
365 | */ | ||
366 | |||
351 | void capi_ctr_ready(struct capi_ctr * card) | 367 | void capi_ctr_ready(struct capi_ctr * card) |
352 | { | 368 | { |
353 | card->cardstate = CARD_RUNNING; | 369 | card->cardstate = CARD_RUNNING; |
@@ -360,6 +376,14 @@ void capi_ctr_ready(struct capi_ctr * card) | |||
360 | 376 | ||
361 | EXPORT_SYMBOL(capi_ctr_ready); | 377 | EXPORT_SYMBOL(capi_ctr_ready); |
362 | 378 | ||
379 | /** | ||
380 | * capi_ctr_reseted() - signal CAPI controller reset | ||
381 | * @card: controller descriptor structure. | ||
382 | * | ||
383 | * Called by hardware driver to signal that the controller is down and | ||
384 | * unavailable for use. | ||
385 | */ | ||
386 | |||
363 | void capi_ctr_reseted(struct capi_ctr * card) | 387 | void capi_ctr_reseted(struct capi_ctr * card) |
364 | { | 388 | { |
365 | u16 appl; | 389 | u16 appl; |
@@ -391,6 +415,13 @@ void capi_ctr_reseted(struct capi_ctr * card) | |||
391 | 415 | ||
392 | EXPORT_SYMBOL(capi_ctr_reseted); | 416 | EXPORT_SYMBOL(capi_ctr_reseted); |
393 | 417 | ||
418 | /** | ||
419 | * capi_ctr_suspend_output() - suspend controller | ||
420 | * @card: controller descriptor structure. | ||
421 | * | ||
422 | * Called by hardware driver to stop data flow. | ||
423 | */ | ||
424 | |||
394 | void capi_ctr_suspend_output(struct capi_ctr *card) | 425 | void capi_ctr_suspend_output(struct capi_ctr *card) |
395 | { | 426 | { |
396 | if (!card->blocked) { | 427 | if (!card->blocked) { |
@@ -401,6 +432,13 @@ void capi_ctr_suspend_output(struct capi_ctr *card) | |||
401 | 432 | ||
402 | EXPORT_SYMBOL(capi_ctr_suspend_output); | 433 | EXPORT_SYMBOL(capi_ctr_suspend_output); |
403 | 434 | ||
435 | /** | ||
436 | * capi_ctr_resume_output() - resume controller | ||
437 | * @card: controller descriptor structure. | ||
438 | * | ||
439 | * Called by hardware driver to resume data flow. | ||
440 | */ | ||
441 | |||
404 | void capi_ctr_resume_output(struct capi_ctr *card) | 442 | void capi_ctr_resume_output(struct capi_ctr *card) |
405 | { | 443 | { |
406 | if (card->blocked) { | 444 | if (card->blocked) { |
@@ -413,6 +451,14 @@ EXPORT_SYMBOL(capi_ctr_resume_output); | |||
413 | 451 | ||
414 | /* ------------------------------------------------------------- */ | 452 | /* ------------------------------------------------------------- */ |
415 | 453 | ||
454 | /** | ||
455 | * attach_capi_ctr() - register CAPI controller | ||
456 | * @card: controller descriptor structure. | ||
457 | * | ||
458 | * Called by hardware driver to register a controller with the CAPI subsystem. | ||
459 | * Return value: 0 on success, error code < 0 on error | ||
460 | */ | ||
461 | |||
416 | int | 462 | int |
417 | attach_capi_ctr(struct capi_ctr *card) | 463 | attach_capi_ctr(struct capi_ctr *card) |
418 | { | 464 | { |
@@ -459,6 +505,15 @@ attach_capi_ctr(struct capi_ctr *card) | |||
459 | 505 | ||
460 | EXPORT_SYMBOL(attach_capi_ctr); | 506 | EXPORT_SYMBOL(attach_capi_ctr); |
461 | 507 | ||
508 | /** | ||
509 | * detach_capi_ctr() - unregister CAPI controller | ||
510 | * @card: controller descriptor structure. | ||
511 | * | ||
512 | * Called by hardware driver to remove the registration of a controller | ||
513 | * with the CAPI subsystem. | ||
514 | * Return value: 0 on success, error code < 0 on error | ||
515 | */ | ||
516 | |||
462 | int detach_capi_ctr(struct capi_ctr *card) | 517 | int detach_capi_ctr(struct capi_ctr *card) |
463 | { | 518 | { |
464 | if (card->cardstate != CARD_DETECTED) | 519 | if (card->cardstate != CARD_DETECTED) |
@@ -479,6 +534,13 @@ int detach_capi_ctr(struct capi_ctr *card) | |||
479 | 534 | ||
480 | EXPORT_SYMBOL(detach_capi_ctr); | 535 | EXPORT_SYMBOL(detach_capi_ctr); |
481 | 536 | ||
537 | /** | ||
538 | * register_capi_driver() - register CAPI driver | ||
539 | * @driver: driver descriptor structure. | ||
540 | * | ||
541 | * Called by hardware driver to register itself with the CAPI subsystem. | ||
542 | */ | ||
543 | |||
482 | void register_capi_driver(struct capi_driver *driver) | 544 | void register_capi_driver(struct capi_driver *driver) |
483 | { | 545 | { |
484 | unsigned long flags; | 546 | unsigned long flags; |
@@ -490,6 +552,13 @@ void register_capi_driver(struct capi_driver *driver) | |||
490 | 552 | ||
491 | EXPORT_SYMBOL(register_capi_driver); | 553 | EXPORT_SYMBOL(register_capi_driver); |
492 | 554 | ||
555 | /** | ||
556 | * unregister_capi_driver() - unregister CAPI driver | ||
557 | * @driver: driver descriptor structure. | ||
558 | * | ||
559 | * Called by hardware driver to unregister itself from the CAPI subsystem. | ||
560 | */ | ||
561 | |||
493 | void unregister_capi_driver(struct capi_driver *driver) | 562 | void unregister_capi_driver(struct capi_driver *driver) |
494 | { | 563 | { |
495 | unsigned long flags; | 564 | unsigned long flags; |
@@ -505,6 +574,13 @@ EXPORT_SYMBOL(unregister_capi_driver); | |||
505 | /* -------- CAPI2.0 Interface ---------------------------------- */ | 574 | /* -------- CAPI2.0 Interface ---------------------------------- */ |
506 | /* ------------------------------------------------------------- */ | 575 | /* ------------------------------------------------------------- */ |
507 | 576 | ||
577 | /** | ||
578 | * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED | ||
579 | * | ||
580 | * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller | ||
581 | * is ready for use, CAPI_REGNOTINSTALLED otherwise) | ||
582 | */ | ||
583 | |||
508 | u16 capi20_isinstalled(void) | 584 | u16 capi20_isinstalled(void) |
509 | { | 585 | { |
510 | int i; | 586 | int i; |
@@ -517,6 +593,18 @@ u16 capi20_isinstalled(void) | |||
517 | 593 | ||
518 | EXPORT_SYMBOL(capi20_isinstalled); | 594 | EXPORT_SYMBOL(capi20_isinstalled); |
519 | 595 | ||
596 | /** | ||
597 | * capi20_register() - CAPI 2.0 operation CAPI_REGISTER | ||
598 | * @ap: CAPI application descriptor structure. | ||
599 | * | ||
600 | * Register an application's presence with CAPI. | ||
601 | * A unique application ID is assigned and stored in @ap->applid. | ||
602 | * After this function returns successfully, the message receive | ||
603 | * callback function @ap->recv_message() may be called at any time | ||
604 | * until capi20_release() has been called for the same @ap. | ||
605 | * Return value: CAPI result code | ||
606 | */ | ||
607 | |||
520 | u16 capi20_register(struct capi20_appl *ap) | 608 | u16 capi20_register(struct capi20_appl *ap) |
521 | { | 609 | { |
522 | int i; | 610 | int i; |
@@ -571,6 +659,16 @@ u16 capi20_register(struct capi20_appl *ap) | |||
571 | 659 | ||
572 | EXPORT_SYMBOL(capi20_register); | 660 | EXPORT_SYMBOL(capi20_register); |
573 | 661 | ||
662 | /** | ||
663 | * capi20_release() - CAPI 2.0 operation CAPI_RELEASE | ||
664 | * @ap: CAPI application descriptor structure. | ||
665 | * | ||
666 | * Terminate an application's registration with CAPI. | ||
667 | * After this function returns successfully, the message receive | ||
668 | * callback function @ap->recv_message() will no longer be called. | ||
669 | * Return value: CAPI result code | ||
670 | */ | ||
671 | |||
574 | u16 capi20_release(struct capi20_appl *ap) | 672 | u16 capi20_release(struct capi20_appl *ap) |
575 | { | 673 | { |
576 | int i; | 674 | int i; |
@@ -603,6 +701,15 @@ u16 capi20_release(struct capi20_appl *ap) | |||
603 | 701 | ||
604 | EXPORT_SYMBOL(capi20_release); | 702 | EXPORT_SYMBOL(capi20_release); |
605 | 703 | ||
704 | /** | ||
705 | * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE | ||
706 | * @ap: CAPI application descriptor structure. | ||
707 | * @skb: CAPI message. | ||
708 | * | ||
709 | * Transfer a single message to CAPI. | ||
710 | * Return value: CAPI result code | ||
711 | */ | ||
712 | |||
606 | u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | 713 | u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) |
607 | { | 714 | { |
608 | struct capi_ctr *card; | 715 | struct capi_ctr *card; |
@@ -668,6 +775,16 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
668 | 775 | ||
669 | EXPORT_SYMBOL(capi20_put_message); | 776 | EXPORT_SYMBOL(capi20_put_message); |
670 | 777 | ||
778 | /** | ||
779 | * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER | ||
780 | * @contr: controller number. | ||
781 | * @buf: result buffer (64 bytes). | ||
782 | * | ||
783 | * Retrieve information about the manufacturer of the specified ISDN controller | ||
784 | * or (for @contr == 0) the driver itself. | ||
785 | * Return value: CAPI result code | ||
786 | */ | ||
787 | |||
671 | u16 capi20_get_manufacturer(u32 contr, u8 *buf) | 788 | u16 capi20_get_manufacturer(u32 contr, u8 *buf) |
672 | { | 789 | { |
673 | struct capi_ctr *card; | 790 | struct capi_ctr *card; |
@@ -685,6 +802,16 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) | |||
685 | 802 | ||
686 | EXPORT_SYMBOL(capi20_get_manufacturer); | 803 | EXPORT_SYMBOL(capi20_get_manufacturer); |
687 | 804 | ||
805 | /** | ||
806 | * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION | ||
807 | * @contr: controller number. | ||
808 | * @verp: result structure. | ||
809 | * | ||
810 | * Retrieve version information for the specified ISDN controller | ||
811 | * or (for @contr == 0) the driver itself. | ||
812 | * Return value: CAPI result code | ||
813 | */ | ||
814 | |||
688 | u16 capi20_get_version(u32 contr, struct capi_version *verp) | 815 | u16 capi20_get_version(u32 contr, struct capi_version *verp) |
689 | { | 816 | { |
690 | struct capi_ctr *card; | 817 | struct capi_ctr *card; |
@@ -703,6 +830,16 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) | |||
703 | 830 | ||
704 | EXPORT_SYMBOL(capi20_get_version); | 831 | EXPORT_SYMBOL(capi20_get_version); |
705 | 832 | ||
833 | /** | ||
834 | * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER | ||
835 | * @contr: controller number. | ||
836 | * @serial: result buffer (8 bytes). | ||
837 | * | ||
838 | * Retrieve the serial number of the specified ISDN controller | ||
839 | * or (for @contr == 0) the driver itself. | ||
840 | * Return value: CAPI result code | ||
841 | */ | ||
842 | |||
706 | u16 capi20_get_serial(u32 contr, u8 *serial) | 843 | u16 capi20_get_serial(u32 contr, u8 *serial) |
707 | { | 844 | { |
708 | struct capi_ctr *card; | 845 | struct capi_ctr *card; |
@@ -721,6 +858,16 @@ u16 capi20_get_serial(u32 contr, u8 *serial) | |||
721 | 858 | ||
722 | EXPORT_SYMBOL(capi20_get_serial); | 859 | EXPORT_SYMBOL(capi20_get_serial); |
723 | 860 | ||
861 | /** | ||
862 | * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE | ||
863 | * @contr: controller number. | ||
864 | * @profp: result structure. | ||
865 | * | ||
866 | * Retrieve capability information for the specified ISDN controller | ||
867 | * or (for @contr == 0) the number of installed controllers. | ||
868 | * Return value: CAPI result code | ||
869 | */ | ||
870 | |||
724 | u16 capi20_get_profile(u32 contr, struct capi_profile *profp) | 871 | u16 capi20_get_profile(u32 contr, struct capi_profile *profp) |
725 | { | 872 | { |
726 | struct capi_ctr *card; | 873 | struct capi_ctr *card; |
@@ -903,6 +1050,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
903 | } | 1050 | } |
904 | #endif | 1051 | #endif |
905 | 1052 | ||
1053 | /** | ||
1054 | * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER | ||
1055 | * @cmd: command. | ||
1056 | * @data: parameter. | ||
1057 | * | ||
1058 | * Perform manufacturer specific command. | ||
1059 | * Return value: CAPI result code | ||
1060 | */ | ||
1061 | |||
906 | int capi20_manufacturer(unsigned int cmd, void __user *data) | 1062 | int capi20_manufacturer(unsigned int cmd, void __user *data) |
907 | { | 1063 | { |
908 | struct capi_ctr *card; | 1064 | struct capi_ctr *card; |
@@ -981,6 +1137,21 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
981 | EXPORT_SYMBOL(capi20_manufacturer); | 1137 | EXPORT_SYMBOL(capi20_manufacturer); |
982 | 1138 | ||
983 | /* temporary hack */ | 1139 | /* temporary hack */ |
1140 | |||
1141 | /** | ||
1142 | * capi20_set_callback() - set CAPI application notification callback function | ||
1143 | * @ap: CAPI application descriptor structure. | ||
1144 | * @callback: callback function (NULL to remove). | ||
1145 | * | ||
1146 | * If not NULL, the callback function will be called to notify the | ||
1147 | * application of the addition or removal of a controller. | ||
1148 | * The first argument (cmd) will tell whether the controller was added | ||
1149 | * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). | ||
1150 | * The second argument (contr) will be the controller number. | ||
1151 | * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the | ||
1152 | * new controller's capability profile structure. | ||
1153 | */ | ||
1154 | |||
984 | void capi20_set_callback(struct capi20_appl *ap, | 1155 | void capi20_set_callback(struct capi20_appl *ap, |
985 | void (*callback) (unsigned int cmd, __u32 contr, void *data)) | 1156 | void (*callback) (unsigned int cmd, __u32 contr, void *data)) |
986 | { | 1157 | { |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 5c0b457c7868..0f9ee1348552 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -2728,7 +2728,7 @@ static void __devexit e100_remove(struct pci_dev *pdev) | |||
2728 | #define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ | 2728 | #define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ |
2729 | #define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ | 2729 | #define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ |
2730 | #define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ | 2730 | #define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ |
2731 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | 2731 | static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) |
2732 | { | 2732 | { |
2733 | struct net_device *netdev = pci_get_drvdata(pdev); | 2733 | struct net_device *netdev = pci_get_drvdata(pdev); |
2734 | struct nic *nic = netdev_priv(netdev); | 2734 | struct nic *nic = netdev_priv(netdev); |
@@ -2749,19 +2749,32 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2749 | E100_82552_SMARTSPEED, smartspeed | | 2749 | E100_82552_SMARTSPEED, smartspeed | |
2750 | E100_82552_REV_ANEG | E100_82552_ANEG_NOW); | 2750 | E100_82552_REV_ANEG | E100_82552_ANEG_NOW); |
2751 | } | 2751 | } |
2752 | if (pci_enable_wake(pdev, PCI_D3cold, true)) | 2752 | *enable_wake = true; |
2753 | pci_enable_wake(pdev, PCI_D3hot, true); | ||
2754 | } else { | 2753 | } else { |
2755 | pci_enable_wake(pdev, PCI_D3hot, false); | 2754 | *enable_wake = false; |
2756 | } | 2755 | } |
2757 | 2756 | ||
2758 | pci_disable_device(pdev); | 2757 | pci_disable_device(pdev); |
2759 | pci_set_power_state(pdev, PCI_D3hot); | 2758 | } |
2760 | 2759 | ||
2761 | return 0; | 2760 | static int __e100_power_off(struct pci_dev *pdev, bool wake) |
2761 | { | ||
2762 | if (wake) { | ||
2763 | return pci_prepare_to_sleep(pdev); | ||
2764 | } else { | ||
2765 | pci_wake_from_d3(pdev, false); | ||
2766 | return pci_set_power_state(pdev, PCI_D3hot); | ||
2767 | } | ||
2762 | } | 2768 | } |
2763 | 2769 | ||
2764 | #ifdef CONFIG_PM | 2770 | #ifdef CONFIG_PM |
2771 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | ||
2772 | { | ||
2773 | bool wake; | ||
2774 | __e100_shutdown(pdev, &wake); | ||
2775 | return __e100_power_off(pdev, wake); | ||
2776 | } | ||
2777 | |||
2765 | static int e100_resume(struct pci_dev *pdev) | 2778 | static int e100_resume(struct pci_dev *pdev) |
2766 | { | 2779 | { |
2767 | struct net_device *netdev = pci_get_drvdata(pdev); | 2780 | struct net_device *netdev = pci_get_drvdata(pdev); |
@@ -2792,7 +2805,10 @@ static int e100_resume(struct pci_dev *pdev) | |||
2792 | 2805 | ||
2793 | static void e100_shutdown(struct pci_dev *pdev) | 2806 | static void e100_shutdown(struct pci_dev *pdev) |
2794 | { | 2807 | { |
2795 | e100_suspend(pdev, PMSG_SUSPEND); | 2808 | bool wake; |
2809 | __e100_shutdown(pdev, &wake); | ||
2810 | if (system_state == SYSTEM_POWER_OFF) | ||
2811 | __e100_power_off(pdev, wake); | ||
2796 | } | 2812 | } |
2797 | 2813 | ||
2798 | /* ------------------ PCI Error Recovery infrastructure -------------- */ | 2814 | /* ------------------ PCI Error Recovery infrastructure -------------- */ |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 11d5db16ed9c..f9a846b1b92f 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -1880,6 +1880,7 @@ static void nv_init_tx(struct net_device *dev) | |||
1880 | np->tx_pkts_in_progress = 0; | 1880 | np->tx_pkts_in_progress = 0; |
1881 | np->tx_change_owner = NULL; | 1881 | np->tx_change_owner = NULL; |
1882 | np->tx_end_flip = NULL; | 1882 | np->tx_end_flip = NULL; |
1883 | np->tx_stop = 0; | ||
1883 | 1884 | ||
1884 | for (i = 0; i < np->tx_ring_size; i++) { | 1885 | for (i = 0; i < np->tx_ring_size; i++) { |
1885 | if (!nv_optimized(np)) { | 1886 | if (!nv_optimized(np)) { |
@@ -2530,6 +2531,8 @@ static void nv_tx_timeout(struct net_device *dev) | |||
2530 | struct fe_priv *np = netdev_priv(dev); | 2531 | struct fe_priv *np = netdev_priv(dev); |
2531 | u8 __iomem *base = get_hwbase(dev); | 2532 | u8 __iomem *base = get_hwbase(dev); |
2532 | u32 status; | 2533 | u32 status; |
2534 | union ring_type put_tx; | ||
2535 | int saved_tx_limit; | ||
2533 | 2536 | ||
2534 | if (np->msi_flags & NV_MSI_X_ENABLED) | 2537 | if (np->msi_flags & NV_MSI_X_ENABLED) |
2535 | status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; | 2538 | status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; |
@@ -2589,24 +2592,32 @@ static void nv_tx_timeout(struct net_device *dev) | |||
2589 | /* 1) stop tx engine */ | 2592 | /* 1) stop tx engine */ |
2590 | nv_stop_tx(dev); | 2593 | nv_stop_tx(dev); |
2591 | 2594 | ||
2592 | /* 2) check that the packets were not sent already: */ | 2595 | /* 2) complete any outstanding tx and do not give HW any limited tx pkts */ |
2596 | saved_tx_limit = np->tx_limit; | ||
2597 | np->tx_limit = 0; /* prevent giving HW any limited pkts */ | ||
2598 | np->tx_stop = 0; /* prevent waking tx queue */ | ||
2593 | if (!nv_optimized(np)) | 2599 | if (!nv_optimized(np)) |
2594 | nv_tx_done(dev, np->tx_ring_size); | 2600 | nv_tx_done(dev, np->tx_ring_size); |
2595 | else | 2601 | else |
2596 | nv_tx_done_optimized(dev, np->tx_ring_size); | 2602 | nv_tx_done_optimized(dev, np->tx_ring_size); |
2597 | 2603 | ||
2598 | /* 3) if there are dead entries: clear everything */ | 2604 | /* save current HW postion */ |
2599 | if (np->get_tx_ctx != np->put_tx_ctx) { | 2605 | if (np->tx_change_owner) |
2600 | printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name); | 2606 | put_tx.ex = np->tx_change_owner->first_tx_desc; |
2601 | nv_drain_tx(dev); | 2607 | else |
2602 | nv_init_tx(dev); | 2608 | put_tx = np->put_tx; |
2603 | setup_hw_rings(dev, NV_SETUP_TX_RING); | ||
2604 | } | ||
2605 | 2609 | ||
2606 | netif_wake_queue(dev); | 2610 | /* 3) clear all tx state */ |
2611 | nv_drain_tx(dev); | ||
2612 | nv_init_tx(dev); | ||
2613 | |||
2614 | /* 4) restore state to current HW position */ | ||
2615 | np->get_tx = np->put_tx = put_tx; | ||
2616 | np->tx_limit = saved_tx_limit; | ||
2607 | 2617 | ||
2608 | /* 4) restart tx engine */ | 2618 | /* 5) restart tx engine */ |
2609 | nv_start_tx(dev); | 2619 | nv_start_tx(dev); |
2620 | netif_wake_queue(dev); | ||
2610 | spin_unlock_irq(&np->lock); | 2621 | spin_unlock_irq(&np->lock); |
2611 | } | 2622 | } |
2612 | 2623 | ||
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 5567519676d5..186a65069b33 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c | |||
@@ -50,7 +50,6 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); | |||
50 | static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); | 50 | static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); |
51 | static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); | 51 | static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); |
52 | static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); | 52 | static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); |
53 | static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); | ||
54 | static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); | 53 | static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); |
55 | 54 | ||
56 | /** | 55 | /** |
@@ -1377,8 +1376,7 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, | |||
1377 | * Clear accounting of old secondary address list, | 1376 | * Clear accounting of old secondary address list, |
1378 | * don't count RAR[0] | 1377 | * don't count RAR[0] |
1379 | */ | 1378 | */ |
1380 | uc_addr_in_use = hw->addr_ctrl.rar_used_count - | 1379 | uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; |
1381 | hw->addr_ctrl.mc_addr_in_rar_count - 1; | ||
1382 | hw->addr_ctrl.rar_used_count -= uc_addr_in_use; | 1380 | hw->addr_ctrl.rar_used_count -= uc_addr_in_use; |
1383 | hw->addr_ctrl.overflow_promisc = 0; | 1381 | hw->addr_ctrl.overflow_promisc = 0; |
1384 | 1382 | ||
@@ -1493,40 +1491,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) | |||
1493 | } | 1491 | } |
1494 | 1492 | ||
1495 | /** | 1493 | /** |
1496 | * ixgbe_add_mc_addr - Adds a multicast address. | ||
1497 | * @hw: pointer to hardware structure | ||
1498 | * @mc_addr: new multicast address | ||
1499 | * | ||
1500 | * Adds it to unused receive address register or to the multicast table. | ||
1501 | **/ | ||
1502 | static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) | ||
1503 | { | ||
1504 | u32 rar_entries = hw->mac.num_rar_entries; | ||
1505 | u32 rar; | ||
1506 | |||
1507 | hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", | ||
1508 | mc_addr[0], mc_addr[1], mc_addr[2], | ||
1509 | mc_addr[3], mc_addr[4], mc_addr[5]); | ||
1510 | |||
1511 | /* | ||
1512 | * Place this multicast address in the RAR if there is room, | ||
1513 | * else put it in the MTA | ||
1514 | */ | ||
1515 | if (hw->addr_ctrl.rar_used_count < rar_entries) { | ||
1516 | /* use RAR from the end up for multicast */ | ||
1517 | rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; | ||
1518 | hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); | ||
1519 | hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar); | ||
1520 | hw->addr_ctrl.rar_used_count++; | ||
1521 | hw->addr_ctrl.mc_addr_in_rar_count++; | ||
1522 | } else { | ||
1523 | ixgbe_set_mta(hw, mc_addr); | ||
1524 | } | ||
1525 | |||
1526 | hw_dbg(hw, "ixgbe_add_mc_addr Complete\n"); | ||
1527 | } | ||
1528 | |||
1529 | /** | ||
1530 | * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses | 1494 | * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses |
1531 | * @hw: pointer to hardware structure | 1495 | * @hw: pointer to hardware structure |
1532 | * @mc_addr_list: the list of new multicast addresses | 1496 | * @mc_addr_list: the list of new multicast addresses |
@@ -1542,7 +1506,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | |||
1542 | u32 mc_addr_count, ixgbe_mc_addr_itr next) | 1506 | u32 mc_addr_count, ixgbe_mc_addr_itr next) |
1543 | { | 1507 | { |
1544 | u32 i; | 1508 | u32 i; |
1545 | u32 rar_entries = hw->mac.num_rar_entries; | ||
1546 | u32 vmdq; | 1509 | u32 vmdq; |
1547 | 1510 | ||
1548 | /* | 1511 | /* |
@@ -1550,18 +1513,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | |||
1550 | * use. | 1513 | * use. |
1551 | */ | 1514 | */ |
1552 | hw->addr_ctrl.num_mc_addrs = mc_addr_count; | 1515 | hw->addr_ctrl.num_mc_addrs = mc_addr_count; |
1553 | hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count; | ||
1554 | hw->addr_ctrl.mc_addr_in_rar_count = 0; | ||
1555 | hw->addr_ctrl.mta_in_use = 0; | 1516 | hw->addr_ctrl.mta_in_use = 0; |
1556 | 1517 | ||
1557 | /* Zero out the other receive addresses. */ | ||
1558 | hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, | ||
1559 | rar_entries - 1); | ||
1560 | for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { | ||
1561 | IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); | ||
1562 | IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); | ||
1563 | } | ||
1564 | |||
1565 | /* Clear the MTA */ | 1518 | /* Clear the MTA */ |
1566 | hw_dbg(hw, " Clearing MTA\n"); | 1519 | hw_dbg(hw, " Clearing MTA\n"); |
1567 | for (i = 0; i < hw->mac.mcft_size; i++) | 1520 | for (i = 0; i < hw->mac.mcft_size; i++) |
@@ -1570,7 +1523,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | |||
1570 | /* Add the new addresses */ | 1523 | /* Add the new addresses */ |
1571 | for (i = 0; i < mc_addr_count; i++) { | 1524 | for (i = 0; i < mc_addr_count; i++) { |
1572 | hw_dbg(hw, " Adding the multicast addresses:\n"); | 1525 | hw_dbg(hw, " Adding the multicast addresses:\n"); |
1573 | ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq)); | 1526 | ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); |
1574 | } | 1527 | } |
1575 | 1528 | ||
1576 | /* Enable mta */ | 1529 | /* Enable mta */ |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 01884256f4c9..07e778d3e5d2 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -3646,6 +3646,8 @@ static int ixgbe_resume(struct pci_dev *pdev) | |||
3646 | 3646 | ||
3647 | ixgbe_reset(adapter); | 3647 | ixgbe_reset(adapter); |
3648 | 3648 | ||
3649 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); | ||
3650 | |||
3649 | if (netif_running(netdev)) { | 3651 | if (netif_running(netdev)) { |
3650 | err = ixgbe_open(adapter->netdev); | 3652 | err = ixgbe_open(adapter->netdev); |
3651 | if (err) | 3653 | if (err) |
@@ -4575,7 +4577,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
4575 | const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; | 4577 | const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; |
4576 | static int cards_found; | 4578 | static int cards_found; |
4577 | int i, err, pci_using_dac; | 4579 | int i, err, pci_using_dac; |
4578 | u16 pm_value = 0; | ||
4579 | u32 part_num, eec; | 4580 | u32 part_num, eec; |
4580 | 4581 | ||
4581 | err = pci_enable_device(pdev); | 4582 | err = pci_enable_device(pdev); |
@@ -4763,11 +4764,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
4763 | 4764 | ||
4764 | switch (pdev->device) { | 4765 | switch (pdev->device) { |
4765 | case IXGBE_DEV_ID_82599_KX4: | 4766 | case IXGBE_DEV_ID_82599_KX4: |
4766 | #define IXGBE_PCIE_PMCSR 0x44 | 4767 | adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | |
4767 | adapter->wol = IXGBE_WUFC_MAG; | 4768 | IXGBE_WUFC_MC | IXGBE_WUFC_BC); |
4768 | pci_read_config_word(pdev, IXGBE_PCIE_PMCSR, &pm_value); | ||
4769 | pci_write_config_word(pdev, IXGBE_PCIE_PMCSR, | ||
4770 | (pm_value | (1 << 8))); | ||
4771 | break; | 4769 | break; |
4772 | default: | 4770 | default: |
4773 | adapter->wol = 0; | 4771 | adapter->wol = 0; |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 438678ab2a10..7bcc49de1637 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
@@ -583,7 +583,7 @@ int mlx4_en_start_port(struct net_device *dev) | |||
583 | err = mlx4_en_activate_cq(priv, cq); | 583 | err = mlx4_en_activate_cq(priv, cq); |
584 | if (err) { | 584 | if (err) { |
585 | mlx4_err(mdev, "Failed activating Rx CQ\n"); | 585 | mlx4_err(mdev, "Failed activating Rx CQ\n"); |
586 | goto rx_err; | 586 | goto cq_err; |
587 | } | 587 | } |
588 | for (j = 0; j < cq->size; j++) | 588 | for (j = 0; j < cq->size; j++) |
589 | cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; | 589 | cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; |
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 0cbb78ca7b29..7942c4d3cd88 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c | |||
@@ -610,6 +610,10 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, | |||
610 | used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, | 610 | used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, |
611 | skb_shinfo(skb)->frags, | 611 | skb_shinfo(skb)->frags, |
612 | page_alloc, length); | 612 | page_alloc, length); |
613 | if (unlikely(!used_frags)) { | ||
614 | kfree_skb(skb); | ||
615 | return NULL; | ||
616 | } | ||
613 | skb_shinfo(skb)->nr_frags = used_frags; | 617 | skb_shinfo(skb)->nr_frags = used_frags; |
614 | 618 | ||
615 | /* Copy headers into the skb linear buffer */ | 619 | /* Copy headers into the skb linear buffer */ |
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 015db1cece72..8e56fcf0a0e3 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
@@ -210,14 +210,11 @@ rx_drop: | |||
210 | 210 | ||
211 | static struct net_device_stats *veth_get_stats(struct net_device *dev) | 211 | static struct net_device_stats *veth_get_stats(struct net_device *dev) |
212 | { | 212 | { |
213 | struct veth_priv *priv; | 213 | struct veth_priv *priv = netdev_priv(dev); |
214 | struct net_device_stats *dev_stats; | 214 | struct net_device_stats *dev_stats = &dev->stats; |
215 | int cpu; | 215 | unsigned int cpu; |
216 | struct veth_net_stats *stats; | 216 | struct veth_net_stats *stats; |
217 | 217 | ||
218 | priv = netdev_priv(dev); | ||
219 | dev_stats = &dev->stats; | ||
220 | |||
221 | dev_stats->rx_packets = 0; | 218 | dev_stats->rx_packets = 0; |
222 | dev_stats->tx_packets = 0; | 219 | dev_stats->tx_packets = 0; |
223 | dev_stats->rx_bytes = 0; | 220 | dev_stats->rx_bytes = 0; |
@@ -225,16 +222,17 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) | |||
225 | dev_stats->tx_dropped = 0; | 222 | dev_stats->tx_dropped = 0; |
226 | dev_stats->rx_dropped = 0; | 223 | dev_stats->rx_dropped = 0; |
227 | 224 | ||
228 | for_each_online_cpu(cpu) { | 225 | if (priv->stats) |
229 | stats = per_cpu_ptr(priv->stats, cpu); | 226 | for_each_online_cpu(cpu) { |
227 | stats = per_cpu_ptr(priv->stats, cpu); | ||
230 | 228 | ||
231 | dev_stats->rx_packets += stats->rx_packets; | 229 | dev_stats->rx_packets += stats->rx_packets; |
232 | dev_stats->tx_packets += stats->tx_packets; | 230 | dev_stats->tx_packets += stats->tx_packets; |
233 | dev_stats->rx_bytes += stats->rx_bytes; | 231 | dev_stats->rx_bytes += stats->rx_bytes; |
234 | dev_stats->tx_bytes += stats->tx_bytes; | 232 | dev_stats->tx_bytes += stats->tx_bytes; |
235 | dev_stats->tx_dropped += stats->tx_dropped; | 233 | dev_stats->tx_dropped += stats->tx_dropped; |
236 | dev_stats->rx_dropped += stats->rx_dropped; | 234 | dev_stats->rx_dropped += stats->rx_dropped; |
237 | } | 235 | } |
238 | 236 | ||
239 | return dev_stats; | 237 | return dev_stats; |
240 | } | 238 | } |
@@ -261,6 +259,8 @@ static int veth_close(struct net_device *dev) | |||
261 | netif_carrier_off(dev); | 259 | netif_carrier_off(dev); |
262 | netif_carrier_off(priv->peer); | 260 | netif_carrier_off(priv->peer); |
263 | 261 | ||
262 | free_percpu(priv->stats); | ||
263 | priv->stats = NULL; | ||
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
@@ -291,15 +291,6 @@ static int veth_dev_init(struct net_device *dev) | |||
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | static void veth_dev_free(struct net_device *dev) | ||
295 | { | ||
296 | struct veth_priv *priv; | ||
297 | |||
298 | priv = netdev_priv(dev); | ||
299 | free_percpu(priv->stats); | ||
300 | free_netdev(dev); | ||
301 | } | ||
302 | |||
303 | static const struct net_device_ops veth_netdev_ops = { | 294 | static const struct net_device_ops veth_netdev_ops = { |
304 | .ndo_init = veth_dev_init, | 295 | .ndo_init = veth_dev_init, |
305 | .ndo_open = veth_open, | 296 | .ndo_open = veth_open, |
@@ -317,7 +308,7 @@ static void veth_setup(struct net_device *dev) | |||
317 | dev->netdev_ops = &veth_netdev_ops; | 308 | dev->netdev_ops = &veth_netdev_ops; |
318 | dev->ethtool_ops = &veth_ethtool_ops; | 309 | dev->ethtool_ops = &veth_ethtool_ops; |
319 | dev->features |= NETIF_F_LLTX; | 310 | dev->features |= NETIF_F_LLTX; |
320 | dev->destructor = veth_dev_free; | 311 | dev->destructor = free_netdev; |
321 | } | 312 | } |
322 | 313 | ||
323 | /* | 314 | /* |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2e7783f4a755..5a96a1a406e9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -104,7 +104,7 @@ struct wireless_dev; | |||
104 | # else | 104 | # else |
105 | # define LL_MAX_HEADER 96 | 105 | # define LL_MAX_HEADER 96 |
106 | # endif | 106 | # endif |
107 | #elif defined(CONFIG_TR) | 107 | #elif defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) |
108 | # define LL_MAX_HEADER 48 | 108 | # define LL_MAX_HEADER 48 |
109 | #else | 109 | #else |
110 | # define LL_MAX_HEADER 32 | 110 | # define LL_MAX_HEADER 32 |
@@ -500,7 +500,7 @@ struct netdev_queue { | |||
500 | * | 500 | * |
501 | * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); | 501 | * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); |
502 | * This function is called when the Media Access Control address | 502 | * This function is called when the Media Access Control address |
503 | * needs to be changed. If not this interface is not defined, the | 503 | * needs to be changed. If this interface is not defined, the |
504 | * mac address can not be changed. | 504 | * mac address can not be changed. |
505 | * | 505 | * |
506 | * int (*ndo_validate_addr)(struct net_device *dev); | 506 | * int (*ndo_validate_addr)(struct net_device *dev); |
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 29fe9ea1d346..1a865e48b8eb 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h | |||
@@ -100,6 +100,7 @@ enum ctattr_protoinfo_tcp { | |||
100 | enum ctattr_protoinfo_dccp { | 100 | enum ctattr_protoinfo_dccp { |
101 | CTA_PROTOINFO_DCCP_UNSPEC, | 101 | CTA_PROTOINFO_DCCP_UNSPEC, |
102 | CTA_PROTOINFO_DCCP_STATE, | 102 | CTA_PROTOINFO_DCCP_STATE, |
103 | CTA_PROTOINFO_DCCP_ROLE, | ||
103 | __CTA_PROTOINFO_DCCP_MAX, | 104 | __CTA_PROTOINFO_DCCP_MAX, |
104 | }; | 105 | }; |
105 | #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) | 106 | #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) |
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 7b1a652066c0..1b2e43502ef7 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
@@ -354,9 +354,6 @@ struct xt_table | |||
354 | /* What hooks you will enter on */ | 354 | /* What hooks you will enter on */ |
355 | unsigned int valid_hooks; | 355 | unsigned int valid_hooks; |
356 | 356 | ||
357 | /* Lock for the curtain */ | ||
358 | struct mutex lock; | ||
359 | |||
360 | /* Man behind the curtain... */ | 357 | /* Man behind the curtain... */ |
361 | struct xt_table_info *private; | 358 | struct xt_table_info *private; |
362 | 359 | ||
@@ -434,8 +431,74 @@ extern void xt_proto_fini(struct net *net, u_int8_t af); | |||
434 | 431 | ||
435 | extern struct xt_table_info *xt_alloc_table_info(unsigned int size); | 432 | extern struct xt_table_info *xt_alloc_table_info(unsigned int size); |
436 | extern void xt_free_table_info(struct xt_table_info *info); | 433 | extern void xt_free_table_info(struct xt_table_info *info); |
437 | extern void xt_table_entry_swap_rcu(struct xt_table_info *old, | 434 | |
438 | struct xt_table_info *new); | 435 | /* |
436 | * Per-CPU spinlock associated with per-cpu table entries, and | ||
437 | * with a counter for the "reading" side that allows a recursive | ||
438 | * reader to avoid taking the lock and deadlocking. | ||
439 | * | ||
440 | * "reading" is used by ip/arp/ip6 tables rule processing which runs per-cpu. | ||
441 | * It needs to ensure that the rules are not being changed while the packet | ||
442 | * is being processed. In some cases, the read lock will be acquired | ||
443 | * twice on the same CPU; this is okay because of the count. | ||
444 | * | ||
445 | * "writing" is used when reading counters. | ||
446 | * During replace any readers that are using the old tables have to complete | ||
447 | * before freeing the old table. This is handled by the write locking | ||
448 | * necessary for reading the counters. | ||
449 | */ | ||
450 | struct xt_info_lock { | ||
451 | spinlock_t lock; | ||
452 | unsigned char readers; | ||
453 | }; | ||
454 | DECLARE_PER_CPU(struct xt_info_lock, xt_info_locks); | ||
455 | |||
456 | /* | ||
457 | * Note: we need to ensure that preemption is disabled before acquiring | ||
458 | * the per-cpu-variable, so we do it as a two step process rather than | ||
459 | * using "spin_lock_bh()". | ||
460 | * | ||
461 | * We _also_ need to disable bottom half processing before updating our | ||
462 | * nesting count, to make sure that the only kind of re-entrancy is this | ||
463 | * code being called by itself: since the count+lock is not an atomic | ||
464 | * operation, we can allow no races. | ||
465 | * | ||
466 | * _Only_ that special combination of being per-cpu and never getting | ||
467 | * re-entered asynchronously means that the count is safe. | ||
468 | */ | ||
469 | static inline void xt_info_rdlock_bh(void) | ||
470 | { | ||
471 | struct xt_info_lock *lock; | ||
472 | |||
473 | local_bh_disable(); | ||
474 | lock = &__get_cpu_var(xt_info_locks); | ||
475 | if (!lock->readers++) | ||
476 | spin_lock(&lock->lock); | ||
477 | } | ||
478 | |||
479 | static inline void xt_info_rdunlock_bh(void) | ||
480 | { | ||
481 | struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); | ||
482 | |||
483 | if (!--lock->readers) | ||
484 | spin_unlock(&lock->lock); | ||
485 | local_bh_enable(); | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * The "writer" side needs to get exclusive access to the lock, | ||
490 | * regardless of readers. This must be called with bottom half | ||
491 | * processing (and thus also preemption) disabled. | ||
492 | */ | ||
493 | static inline void xt_info_wrlock(unsigned int cpu) | ||
494 | { | ||
495 | spin_lock(&per_cpu(xt_info_locks, cpu).lock); | ||
496 | } | ||
497 | |||
498 | static inline void xt_info_wrunlock(unsigned int cpu) | ||
499 | { | ||
500 | spin_unlock(&per_cpu(xt_info_locks, cpu).lock); | ||
501 | } | ||
439 | 502 | ||
440 | /* | 503 | /* |
441 | * This helper is performance critical and must be inlined | 504 | * This helper is performance critical and must be inlined |
diff --git a/include/linux/wait.h b/include/linux/wait.h index 5d631c17eaee..bc024632f365 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h | |||
@@ -440,13 +440,15 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, | |||
440 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | 440 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); |
441 | int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | 441 | int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); |
442 | 442 | ||
443 | #define DEFINE_WAIT(name) \ | 443 | #define DEFINE_WAIT_FUNC(name, function) \ |
444 | wait_queue_t name = { \ | 444 | wait_queue_t name = { \ |
445 | .private = current, \ | 445 | .private = current, \ |
446 | .func = autoremove_wake_function, \ | 446 | .func = function, \ |
447 | .task_list = LIST_HEAD_INIT((name).task_list), \ | 447 | .task_list = LIST_HEAD_INIT((name).task_list), \ |
448 | } | 448 | } |
449 | 449 | ||
450 | #define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function) | ||
451 | |||
450 | #define DEFINE_WAIT_BIT(name, word, bit) \ | 452 | #define DEFINE_WAIT_BIT(name, word, bit) \ |
451 | struct wait_bit_queue name = { \ | 453 | struct wait_bit_queue name = { \ |
452 | .key = __WAIT_BIT_KEY_INITIALIZER(word, bit), \ | 454 | .key = __WAIT_BIT_KEY_INITIALIZER(word, bit), \ |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index f69f015bbcc0..ed3aea1605e8 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -101,6 +101,7 @@ enum { | |||
101 | /* HCI timeouts */ | 101 | /* HCI timeouts */ |
102 | #define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */ | 102 | #define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */ |
103 | #define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ | 103 | #define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ |
104 | #define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */ | ||
104 | #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ | 105 | #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ |
105 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ | 106 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ |
106 | 107 | ||
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 01f9316b4c23..be5bd713d2c9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -171,6 +171,7 @@ struct hci_conn { | |||
171 | __u8 auth_type; | 171 | __u8 auth_type; |
172 | __u8 sec_level; | 172 | __u8 sec_level; |
173 | __u8 power_save; | 173 | __u8 power_save; |
174 | __u16 disc_timeout; | ||
174 | unsigned long pend; | 175 | unsigned long pend; |
175 | 176 | ||
176 | unsigned int sent; | 177 | unsigned int sent; |
@@ -180,7 +181,8 @@ struct hci_conn { | |||
180 | struct timer_list disc_timer; | 181 | struct timer_list disc_timer; |
181 | struct timer_list idle_timer; | 182 | struct timer_list idle_timer; |
182 | 183 | ||
183 | struct work_struct work; | 184 | struct work_struct work_add; |
185 | struct work_struct work_del; | ||
184 | 186 | ||
185 | struct device dev; | 187 | struct device dev; |
186 | 188 | ||
@@ -348,9 +350,9 @@ static inline void hci_conn_put(struct hci_conn *conn) | |||
348 | if (conn->type == ACL_LINK) { | 350 | if (conn->type == ACL_LINK) { |
349 | del_timer(&conn->idle_timer); | 351 | del_timer(&conn->idle_timer); |
350 | if (conn->state == BT_CONNECTED) { | 352 | if (conn->state == BT_CONNECTED) { |
351 | timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT); | 353 | timeo = msecs_to_jiffies(conn->disc_timeout); |
352 | if (!conn->out) | 354 | if (!conn->out) |
353 | timeo *= 5; | 355 | timeo *= 2; |
354 | } else | 356 | } else |
355 | timeo = msecs_to_jiffies(10); | 357 | timeo = msecs_to_jiffies(10); |
356 | } else | 358 | } else |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 2b7390e377b3..d1e10546eb85 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -492,6 +492,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
492 | continue; | 492 | continue; |
493 | 493 | ||
494 | dev_change_flags(vlandev, flgs & ~IFF_UP); | 494 | dev_change_flags(vlandev, flgs & ~IFF_UP); |
495 | vlan_transfer_operstate(dev, vlandev); | ||
495 | } | 496 | } |
496 | break; | 497 | break; |
497 | 498 | ||
@@ -507,6 +508,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
507 | continue; | 508 | continue; |
508 | 509 | ||
509 | dev_change_flags(vlandev, flgs | IFF_UP); | 510 | dev_change_flags(vlandev, flgs | IFF_UP); |
511 | vlan_transfer_operstate(dev, vlandev); | ||
510 | } | 512 | } |
511 | break; | 513 | break; |
512 | 514 | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6b0921364014..b4b9068e55a7 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -462,6 +462,7 @@ static int vlan_dev_open(struct net_device *dev) | |||
462 | if (vlan->flags & VLAN_FLAG_GVRP) | 462 | if (vlan->flags & VLAN_FLAG_GVRP) |
463 | vlan_gvrp_request_join(dev); | 463 | vlan_gvrp_request_join(dev); |
464 | 464 | ||
465 | netif_carrier_on(dev); | ||
465 | return 0; | 466 | return 0; |
466 | 467 | ||
467 | clear_allmulti: | 468 | clear_allmulti: |
@@ -471,6 +472,7 @@ del_unicast: | |||
471 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 472 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
472 | dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); | 473 | dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); |
473 | out: | 474 | out: |
475 | netif_carrier_off(dev); | ||
474 | return err; | 476 | return err; |
475 | } | 477 | } |
476 | 478 | ||
@@ -492,6 +494,7 @@ static int vlan_dev_stop(struct net_device *dev) | |||
492 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 494 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
493 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); | 495 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); |
494 | 496 | ||
497 | netif_carrier_off(dev); | ||
495 | return 0; | 498 | return 0; |
496 | } | 499 | } |
497 | 500 | ||
@@ -612,6 +615,8 @@ static int vlan_dev_init(struct net_device *dev) | |||
612 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | 615 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; |
613 | int subclass = 0; | 616 | int subclass = 0; |
614 | 617 | ||
618 | netif_carrier_off(dev); | ||
619 | |||
615 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ | 620 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ |
616 | dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); | 621 | dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); |
617 | dev->iflink = real_dev->ifindex; | 622 | dev->iflink = real_dev->ifindex; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1181db08d9de..375f4b4f7f79 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -215,6 +215,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
215 | conn->state = BT_OPEN; | 215 | conn->state = BT_OPEN; |
216 | 216 | ||
217 | conn->power_save = 1; | 217 | conn->power_save = 1; |
218 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
218 | 219 | ||
219 | switch (type) { | 220 | switch (type) { |
220 | case ACL_LINK: | 221 | case ACL_LINK: |
@@ -424,12 +425,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
424 | if (sec_level == BT_SECURITY_SDP) | 425 | if (sec_level == BT_SECURITY_SDP) |
425 | return 1; | 426 | return 1; |
426 | 427 | ||
427 | if (sec_level == BT_SECURITY_LOW) { | 428 | if (sec_level == BT_SECURITY_LOW && |
428 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) | 429 | (!conn->ssp_mode || !conn->hdev->ssp_mode)) |
429 | return hci_conn_auth(conn, sec_level, auth_type); | 430 | return 1; |
430 | else | ||
431 | return 1; | ||
432 | } | ||
433 | 431 | ||
434 | if (conn->link_mode & HCI_LM_ENCRYPT) | 432 | if (conn->link_mode & HCI_LM_ENCRYPT) |
435 | return hci_conn_auth(conn, sec_level, auth_type); | 433 | return hci_conn_auth(conn, sec_level, auth_type); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 15f40ea8d544..4e7cb88e5da9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -883,6 +883,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
883 | if (conn->type == ACL_LINK) { | 883 | if (conn->type == ACL_LINK) { |
884 | conn->state = BT_CONFIG; | 884 | conn->state = BT_CONFIG; |
885 | hci_conn_hold(conn); | 885 | hci_conn_hold(conn); |
886 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
886 | } else | 887 | } else |
887 | conn->state = BT_CONNECTED; | 888 | conn->state = BT_CONNECTED; |
888 | 889 | ||
@@ -1063,9 +1064,14 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1063 | hci_proto_connect_cfm(conn, ev->status); | 1064 | hci_proto_connect_cfm(conn, ev->status); |
1064 | hci_conn_put(conn); | 1065 | hci_conn_put(conn); |
1065 | } | 1066 | } |
1066 | } else | 1067 | } else { |
1067 | hci_auth_cfm(conn, ev->status); | 1068 | hci_auth_cfm(conn, ev->status); |
1068 | 1069 | ||
1070 | hci_conn_hold(conn); | ||
1071 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1072 | hci_conn_put(conn); | ||
1073 | } | ||
1074 | |||
1069 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { | 1075 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { |
1070 | if (!ev->status) { | 1076 | if (!ev->status) { |
1071 | struct hci_cp_set_conn_encrypt cp; | 1077 | struct hci_cp_set_conn_encrypt cp; |
@@ -1479,7 +1485,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
1479 | 1485 | ||
1480 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1486 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1481 | { | 1487 | { |
1488 | struct hci_ev_pin_code_req *ev = (void *) skb->data; | ||
1489 | struct hci_conn *conn; | ||
1490 | |||
1482 | BT_DBG("%s", hdev->name); | 1491 | BT_DBG("%s", hdev->name); |
1492 | |||
1493 | hci_dev_lock(hdev); | ||
1494 | |||
1495 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1496 | if (conn) { | ||
1497 | hci_conn_hold(conn); | ||
1498 | conn->disc_timeout = HCI_PAIRING_TIMEOUT; | ||
1499 | hci_conn_put(conn); | ||
1500 | } | ||
1501 | |||
1502 | hci_dev_unlock(hdev); | ||
1483 | } | 1503 | } |
1484 | 1504 | ||
1485 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1505 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1489,7 +1509,21 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | |||
1489 | 1509 | ||
1490 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1510 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1491 | { | 1511 | { |
1512 | struct hci_ev_link_key_notify *ev = (void *) skb->data; | ||
1513 | struct hci_conn *conn; | ||
1514 | |||
1492 | BT_DBG("%s", hdev->name); | 1515 | BT_DBG("%s", hdev->name); |
1516 | |||
1517 | hci_dev_lock(hdev); | ||
1518 | |||
1519 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1520 | if (conn) { | ||
1521 | hci_conn_hold(conn); | ||
1522 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1523 | hci_conn_put(conn); | ||
1524 | } | ||
1525 | |||
1526 | hci_dev_unlock(hdev); | ||
1493 | } | 1527 | } |
1494 | 1528 | ||
1495 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1529 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index ed82796d4a0f..b7c51082ddeb 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -9,8 +9,7 @@ | |||
9 | struct class *bt_class = NULL; | 9 | struct class *bt_class = NULL; |
10 | EXPORT_SYMBOL_GPL(bt_class); | 10 | EXPORT_SYMBOL_GPL(bt_class); |
11 | 11 | ||
12 | static struct workqueue_struct *btaddconn; | 12 | static struct workqueue_struct *bluetooth; |
13 | static struct workqueue_struct *btdelconn; | ||
14 | 13 | ||
15 | static inline char *link_typetostr(int type) | 14 | static inline char *link_typetostr(int type) |
16 | { | 15 | { |
@@ -88,9 +87,10 @@ static struct device_type bt_link = { | |||
88 | 87 | ||
89 | static void add_conn(struct work_struct *work) | 88 | static void add_conn(struct work_struct *work) |
90 | { | 89 | { |
91 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 90 | struct hci_conn *conn = container_of(work, struct hci_conn, work_add); |
92 | 91 | ||
93 | flush_workqueue(btdelconn); | 92 | /* ensure previous add/del is complete */ |
93 | flush_workqueue(bluetooth); | ||
94 | 94 | ||
95 | if (device_add(&conn->dev) < 0) { | 95 | if (device_add(&conn->dev) < 0) { |
96 | BT_ERR("Failed to register connection device"); | 96 | BT_ERR("Failed to register connection device"); |
@@ -114,9 +114,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn) | |||
114 | 114 | ||
115 | device_initialize(&conn->dev); | 115 | device_initialize(&conn->dev); |
116 | 116 | ||
117 | INIT_WORK(&conn->work, add_conn); | 117 | INIT_WORK(&conn->work_add, add_conn); |
118 | 118 | ||
119 | queue_work(btaddconn, &conn->work); | 119 | queue_work(bluetooth, &conn->work_add); |
120 | } | 120 | } |
121 | 121 | ||
122 | /* | 122 | /* |
@@ -131,9 +131,12 @@ static int __match_tty(struct device *dev, void *data) | |||
131 | 131 | ||
132 | static void del_conn(struct work_struct *work) | 132 | static void del_conn(struct work_struct *work) |
133 | { | 133 | { |
134 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 134 | struct hci_conn *conn = container_of(work, struct hci_conn, work_del); |
135 | struct hci_dev *hdev = conn->hdev; | 135 | struct hci_dev *hdev = conn->hdev; |
136 | 136 | ||
137 | /* ensure previous add/del is complete */ | ||
138 | flush_workqueue(bluetooth); | ||
139 | |||
137 | while (1) { | 140 | while (1) { |
138 | struct device *dev; | 141 | struct device *dev; |
139 | 142 | ||
@@ -156,9 +159,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn) | |||
156 | if (!device_is_registered(&conn->dev)) | 159 | if (!device_is_registered(&conn->dev)) |
157 | return; | 160 | return; |
158 | 161 | ||
159 | INIT_WORK(&conn->work, del_conn); | 162 | INIT_WORK(&conn->work_del, del_conn); |
160 | 163 | ||
161 | queue_work(btdelconn, &conn->work); | 164 | queue_work(bluetooth, &conn->work_del); |
162 | } | 165 | } |
163 | 166 | ||
164 | static inline char *host_typetostr(int type) | 167 | static inline char *host_typetostr(int type) |
@@ -435,20 +438,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | |||
435 | 438 | ||
436 | int __init bt_sysfs_init(void) | 439 | int __init bt_sysfs_init(void) |
437 | { | 440 | { |
438 | btaddconn = create_singlethread_workqueue("btaddconn"); | 441 | bluetooth = create_singlethread_workqueue("bluetooth"); |
439 | if (!btaddconn) | 442 | if (!bluetooth) |
440 | return -ENOMEM; | ||
441 | |||
442 | btdelconn = create_singlethread_workqueue("btdelconn"); | ||
443 | if (!btdelconn) { | ||
444 | destroy_workqueue(btaddconn); | ||
445 | return -ENOMEM; | 443 | return -ENOMEM; |
446 | } | ||
447 | 444 | ||
448 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 445 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
449 | if (IS_ERR(bt_class)) { | 446 | if (IS_ERR(bt_class)) { |
450 | destroy_workqueue(btdelconn); | 447 | destroy_workqueue(bluetooth); |
451 | destroy_workqueue(btaddconn); | ||
452 | return PTR_ERR(bt_class); | 448 | return PTR_ERR(bt_class); |
453 | } | 449 | } |
454 | 450 | ||
@@ -457,8 +453,7 @@ int __init bt_sysfs_init(void) | |||
457 | 453 | ||
458 | void bt_sysfs_cleanup(void) | 454 | void bt_sysfs_cleanup(void) |
459 | { | 455 | { |
460 | destroy_workqueue(btaddconn); | 456 | destroy_workqueue(bluetooth); |
461 | destroy_workqueue(btdelconn); | ||
462 | 457 | ||
463 | class_destroy(bt_class); | 458 | class_destroy(bt_class); |
464 | } | 459 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3953ac4214c8..e4a418fcb35b 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -788,15 +788,23 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, | |||
788 | return NF_STOLEN; | 788 | return NF_STOLEN; |
789 | } | 789 | } |
790 | 790 | ||
791 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) | ||
791 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | 792 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) |
792 | { | 793 | { |
793 | if (skb->protocol == htons(ETH_P_IP) && | 794 | if (skb->nfct != NULL && |
795 | (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) && | ||
794 | skb->len > skb->dev->mtu && | 796 | skb->len > skb->dev->mtu && |
795 | !skb_is_gso(skb)) | 797 | !skb_is_gso(skb)) |
796 | return ip_fragment(skb, br_dev_queue_push_xmit); | 798 | return ip_fragment(skb, br_dev_queue_push_xmit); |
797 | else | 799 | else |
798 | return br_dev_queue_push_xmit(skb); | 800 | return br_dev_queue_push_xmit(skb); |
799 | } | 801 | } |
802 | #else | ||
803 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | ||
804 | { | ||
805 | return br_dev_queue_push_xmit(skb); | ||
806 | } | ||
807 | #endif | ||
800 | 808 | ||
801 | /* PF_BRIDGE/POST_ROUTING ********************************************/ | 809 | /* PF_BRIDGE/POST_ROUTING ********************************************/ |
802 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | 810 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, |
diff --git a/net/core/datagram.c b/net/core/datagram.c index d0de644b378d..b01a76abe1d2 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -64,13 +64,25 @@ static inline int connection_based(struct sock *sk) | |||
64 | return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; | 64 | return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; |
65 | } | 65 | } |
66 | 66 | ||
67 | static int receiver_wake_function(wait_queue_t *wait, unsigned mode, int sync, | ||
68 | void *key) | ||
69 | { | ||
70 | unsigned long bits = (unsigned long)key; | ||
71 | |||
72 | /* | ||
73 | * Avoid a wakeup if event not interesting for us | ||
74 | */ | ||
75 | if (bits && !(bits & (POLLIN | POLLERR))) | ||
76 | return 0; | ||
77 | return autoremove_wake_function(wait, mode, sync, key); | ||
78 | } | ||
67 | /* | 79 | /* |
68 | * Wait for a packet.. | 80 | * Wait for a packet.. |
69 | */ | 81 | */ |
70 | static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | 82 | static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) |
71 | { | 83 | { |
72 | int error; | 84 | int error; |
73 | DEFINE_WAIT(wait); | 85 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); |
74 | 86 | ||
75 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 87 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); |
76 | 88 | ||
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 5ba533d234db..831fe1879dc0 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -253,9 +253,9 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
253 | indev = in ? in->name : nulldevname; | 253 | indev = in ? in->name : nulldevname; |
254 | outdev = out ? out->name : nulldevname; | 254 | outdev = out ? out->name : nulldevname; |
255 | 255 | ||
256 | rcu_read_lock_bh(); | 256 | xt_info_rdlock_bh(); |
257 | private = rcu_dereference(table->private); | 257 | private = table->private; |
258 | table_base = rcu_dereference(private->entries[smp_processor_id()]); | 258 | table_base = private->entries[smp_processor_id()]; |
259 | 259 | ||
260 | e = get_entry(table_base, private->hook_entry[hook]); | 260 | e = get_entry(table_base, private->hook_entry[hook]); |
261 | back = get_entry(table_base, private->underflow[hook]); | 261 | back = get_entry(table_base, private->underflow[hook]); |
@@ -273,6 +273,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
273 | 273 | ||
274 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + | 274 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + |
275 | (2 * skb->dev->addr_len); | 275 | (2 * skb->dev->addr_len); |
276 | |||
276 | ADD_COUNTER(e->counters, hdr_len, 1); | 277 | ADD_COUNTER(e->counters, hdr_len, 1); |
277 | 278 | ||
278 | t = arpt_get_target(e); | 279 | t = arpt_get_target(e); |
@@ -328,8 +329,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
328 | e = (void *)e + e->next_offset; | 329 | e = (void *)e + e->next_offset; |
329 | } | 330 | } |
330 | } while (!hotdrop); | 331 | } while (!hotdrop); |
331 | 332 | xt_info_rdunlock_bh(); | |
332 | rcu_read_unlock_bh(); | ||
333 | 333 | ||
334 | if (hotdrop) | 334 | if (hotdrop) |
335 | return NF_DROP; | 335 | return NF_DROP; |
@@ -711,9 +711,12 @@ static void get_counters(const struct xt_table_info *t, | |||
711 | /* Instead of clearing (by a previous call to memset()) | 711 | /* Instead of clearing (by a previous call to memset()) |
712 | * the counters and using adds, we set the counters | 712 | * the counters and using adds, we set the counters |
713 | * with data used by 'current' CPU | 713 | * with data used by 'current' CPU |
714 | * We dont care about preemption here. | 714 | * |
715 | * Bottom half has to be disabled to prevent deadlock | ||
716 | * if new softirq were to run and call ipt_do_table | ||
715 | */ | 717 | */ |
716 | curcpu = raw_smp_processor_id(); | 718 | local_bh_disable(); |
719 | curcpu = smp_processor_id(); | ||
717 | 720 | ||
718 | i = 0; | 721 | i = 0; |
719 | ARPT_ENTRY_ITERATE(t->entries[curcpu], | 722 | ARPT_ENTRY_ITERATE(t->entries[curcpu], |
@@ -726,73 +729,22 @@ static void get_counters(const struct xt_table_info *t, | |||
726 | if (cpu == curcpu) | 729 | if (cpu == curcpu) |
727 | continue; | 730 | continue; |
728 | i = 0; | 731 | i = 0; |
732 | xt_info_wrlock(cpu); | ||
729 | ARPT_ENTRY_ITERATE(t->entries[cpu], | 733 | ARPT_ENTRY_ITERATE(t->entries[cpu], |
730 | t->size, | 734 | t->size, |
731 | add_entry_to_counter, | 735 | add_entry_to_counter, |
732 | counters, | 736 | counters, |
733 | &i); | 737 | &i); |
738 | xt_info_wrunlock(cpu); | ||
734 | } | 739 | } |
735 | } | ||
736 | |||
737 | |||
738 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
739 | * and everything is OK. */ | ||
740 | static int | ||
741 | add_counter_to_entry(struct arpt_entry *e, | ||
742 | const struct xt_counters addme[], | ||
743 | unsigned int *i) | ||
744 | { | ||
745 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
746 | |||
747 | (*i)++; | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | /* Take values from counters and add them back onto the current cpu */ | ||
752 | static void put_counters(struct xt_table_info *t, | ||
753 | const struct xt_counters counters[]) | ||
754 | { | ||
755 | unsigned int i, cpu; | ||
756 | |||
757 | local_bh_disable(); | ||
758 | cpu = smp_processor_id(); | ||
759 | i = 0; | ||
760 | ARPT_ENTRY_ITERATE(t->entries[cpu], | ||
761 | t->size, | ||
762 | add_counter_to_entry, | ||
763 | counters, | ||
764 | &i); | ||
765 | local_bh_enable(); | 740 | local_bh_enable(); |
766 | } | 741 | } |
767 | 742 | ||
768 | static inline int | ||
769 | zero_entry_counter(struct arpt_entry *e, void *arg) | ||
770 | { | ||
771 | e->counters.bcnt = 0; | ||
772 | e->counters.pcnt = 0; | ||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static void | ||
777 | clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||
778 | { | ||
779 | unsigned int cpu; | ||
780 | const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||
781 | |||
782 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||
783 | for_each_possible_cpu(cpu) { | ||
784 | memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||
785 | ARPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||
786 | zero_entry_counter, NULL); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | static struct xt_counters *alloc_counters(struct xt_table *table) | 743 | static struct xt_counters *alloc_counters(struct xt_table *table) |
791 | { | 744 | { |
792 | unsigned int countersize; | 745 | unsigned int countersize; |
793 | struct xt_counters *counters; | 746 | struct xt_counters *counters; |
794 | struct xt_table_info *private = table->private; | 747 | struct xt_table_info *private = table->private; |
795 | struct xt_table_info *info; | ||
796 | 748 | ||
797 | /* We need atomic snapshot of counters: rest doesn't change | 749 | /* We need atomic snapshot of counters: rest doesn't change |
798 | * (other than comefrom, which userspace doesn't care | 750 | * (other than comefrom, which userspace doesn't care |
@@ -802,30 +754,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | |||
802 | counters = vmalloc_node(countersize, numa_node_id()); | 754 | counters = vmalloc_node(countersize, numa_node_id()); |
803 | 755 | ||
804 | if (counters == NULL) | 756 | if (counters == NULL) |
805 | goto nomem; | 757 | return ERR_PTR(-ENOMEM); |
806 | |||
807 | info = xt_alloc_table_info(private->size); | ||
808 | if (!info) | ||
809 | goto free_counters; | ||
810 | |||
811 | clone_counters(info, private); | ||
812 | |||
813 | mutex_lock(&table->lock); | ||
814 | xt_table_entry_swap_rcu(private, info); | ||
815 | synchronize_net(); /* Wait until smoke has cleared */ | ||
816 | 758 | ||
817 | get_counters(info, counters); | 759 | get_counters(private, counters); |
818 | put_counters(private, counters); | ||
819 | mutex_unlock(&table->lock); | ||
820 | |||
821 | xt_free_table_info(info); | ||
822 | 760 | ||
823 | return counters; | 761 | return counters; |
824 | |||
825 | free_counters: | ||
826 | vfree(counters); | ||
827 | nomem: | ||
828 | return ERR_PTR(-ENOMEM); | ||
829 | } | 762 | } |
830 | 763 | ||
831 | static int copy_entries_to_user(unsigned int total_size, | 764 | static int copy_entries_to_user(unsigned int total_size, |
@@ -1094,8 +1027,9 @@ static int __do_replace(struct net *net, const char *name, | |||
1094 | (newinfo->number <= oldinfo->initial_entries)) | 1027 | (newinfo->number <= oldinfo->initial_entries)) |
1095 | module_put(t->me); | 1028 | module_put(t->me); |
1096 | 1029 | ||
1097 | /* Get the old counters. */ | 1030 | /* Get the old counters, and synchronize with replace */ |
1098 | get_counters(oldinfo, counters); | 1031 | get_counters(oldinfo, counters); |
1032 | |||
1099 | /* Decrease module usage counts and free resource */ | 1033 | /* Decrease module usage counts and free resource */ |
1100 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1034 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1101 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | 1035 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, |
@@ -1165,10 +1099,23 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) | |||
1165 | return ret; | 1099 | return ret; |
1166 | } | 1100 | } |
1167 | 1101 | ||
1102 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1103 | * and everything is OK. */ | ||
1104 | static int | ||
1105 | add_counter_to_entry(struct arpt_entry *e, | ||
1106 | const struct xt_counters addme[], | ||
1107 | unsigned int *i) | ||
1108 | { | ||
1109 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1110 | |||
1111 | (*i)++; | ||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1168 | static int do_add_counters(struct net *net, void __user *user, unsigned int len, | 1115 | static int do_add_counters(struct net *net, void __user *user, unsigned int len, |
1169 | int compat) | 1116 | int compat) |
1170 | { | 1117 | { |
1171 | unsigned int i; | 1118 | unsigned int i, curcpu; |
1172 | struct xt_counters_info tmp; | 1119 | struct xt_counters_info tmp; |
1173 | struct xt_counters *paddc; | 1120 | struct xt_counters *paddc; |
1174 | unsigned int num_counters; | 1121 | unsigned int num_counters; |
@@ -1224,26 +1171,26 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len, | |||
1224 | goto free; | 1171 | goto free; |
1225 | } | 1172 | } |
1226 | 1173 | ||
1227 | mutex_lock(&t->lock); | 1174 | local_bh_disable(); |
1228 | private = t->private; | 1175 | private = t->private; |
1229 | if (private->number != num_counters) { | 1176 | if (private->number != num_counters) { |
1230 | ret = -EINVAL; | 1177 | ret = -EINVAL; |
1231 | goto unlock_up_free; | 1178 | goto unlock_up_free; |
1232 | } | 1179 | } |
1233 | 1180 | ||
1234 | preempt_disable(); | ||
1235 | i = 0; | 1181 | i = 0; |
1236 | /* Choose the copy that is on our node */ | 1182 | /* Choose the copy that is on our node */ |
1237 | loc_cpu_entry = private->entries[smp_processor_id()]; | 1183 | curcpu = smp_processor_id(); |
1184 | loc_cpu_entry = private->entries[curcpu]; | ||
1185 | xt_info_wrlock(curcpu); | ||
1238 | ARPT_ENTRY_ITERATE(loc_cpu_entry, | 1186 | ARPT_ENTRY_ITERATE(loc_cpu_entry, |
1239 | private->size, | 1187 | private->size, |
1240 | add_counter_to_entry, | 1188 | add_counter_to_entry, |
1241 | paddc, | 1189 | paddc, |
1242 | &i); | 1190 | &i); |
1243 | preempt_enable(); | 1191 | xt_info_wrunlock(curcpu); |
1244 | unlock_up_free: | 1192 | unlock_up_free: |
1245 | mutex_unlock(&t->lock); | 1193 | local_bh_enable(); |
1246 | |||
1247 | xt_table_unlock(t); | 1194 | xt_table_unlock(t); |
1248 | module_put(t->me); | 1195 | module_put(t->me); |
1249 | free: | 1196 | free: |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 810c0b62c7d4..2ec8d7290c40 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -338,10 +338,9 @@ ipt_do_table(struct sk_buff *skb, | |||
338 | tgpar.hooknum = hook; | 338 | tgpar.hooknum = hook; |
339 | 339 | ||
340 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 340 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
341 | 341 | xt_info_rdlock_bh(); | |
342 | rcu_read_lock_bh(); | 342 | private = table->private; |
343 | private = rcu_dereference(table->private); | 343 | table_base = private->entries[smp_processor_id()]; |
344 | table_base = rcu_dereference(private->entries[smp_processor_id()]); | ||
345 | 344 | ||
346 | e = get_entry(table_base, private->hook_entry[hook]); | 345 | e = get_entry(table_base, private->hook_entry[hook]); |
347 | 346 | ||
@@ -436,8 +435,7 @@ ipt_do_table(struct sk_buff *skb, | |||
436 | e = (void *)e + e->next_offset; | 435 | e = (void *)e + e->next_offset; |
437 | } | 436 | } |
438 | } while (!hotdrop); | 437 | } while (!hotdrop); |
439 | 438 | xt_info_rdunlock_bh(); | |
440 | rcu_read_unlock_bh(); | ||
441 | 439 | ||
442 | #ifdef DEBUG_ALLOW_ALL | 440 | #ifdef DEBUG_ALLOW_ALL |
443 | return NF_ACCEPT; | 441 | return NF_ACCEPT; |
@@ -896,10 +894,13 @@ get_counters(const struct xt_table_info *t, | |||
896 | 894 | ||
897 | /* Instead of clearing (by a previous call to memset()) | 895 | /* Instead of clearing (by a previous call to memset()) |
898 | * the counters and using adds, we set the counters | 896 | * the counters and using adds, we set the counters |
899 | * with data used by 'current' CPU | 897 | * with data used by 'current' CPU. |
900 | * We dont care about preemption here. | 898 | * |
899 | * Bottom half has to be disabled to prevent deadlock | ||
900 | * if new softirq were to run and call ipt_do_table | ||
901 | */ | 901 | */ |
902 | curcpu = raw_smp_processor_id(); | 902 | local_bh_disable(); |
903 | curcpu = smp_processor_id(); | ||
903 | 904 | ||
904 | i = 0; | 905 | i = 0; |
905 | IPT_ENTRY_ITERATE(t->entries[curcpu], | 906 | IPT_ENTRY_ITERATE(t->entries[curcpu], |
@@ -912,74 +913,22 @@ get_counters(const struct xt_table_info *t, | |||
912 | if (cpu == curcpu) | 913 | if (cpu == curcpu) |
913 | continue; | 914 | continue; |
914 | i = 0; | 915 | i = 0; |
916 | xt_info_wrlock(cpu); | ||
915 | IPT_ENTRY_ITERATE(t->entries[cpu], | 917 | IPT_ENTRY_ITERATE(t->entries[cpu], |
916 | t->size, | 918 | t->size, |
917 | add_entry_to_counter, | 919 | add_entry_to_counter, |
918 | counters, | 920 | counters, |
919 | &i); | 921 | &i); |
922 | xt_info_wrunlock(cpu); | ||
920 | } | 923 | } |
921 | |||
922 | } | ||
923 | |||
924 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
925 | * and everything is OK. */ | ||
926 | static int | ||
927 | add_counter_to_entry(struct ipt_entry *e, | ||
928 | const struct xt_counters addme[], | ||
929 | unsigned int *i) | ||
930 | { | ||
931 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
932 | |||
933 | (*i)++; | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | /* Take values from counters and add them back onto the current cpu */ | ||
938 | static void put_counters(struct xt_table_info *t, | ||
939 | const struct xt_counters counters[]) | ||
940 | { | ||
941 | unsigned int i, cpu; | ||
942 | |||
943 | local_bh_disable(); | ||
944 | cpu = smp_processor_id(); | ||
945 | i = 0; | ||
946 | IPT_ENTRY_ITERATE(t->entries[cpu], | ||
947 | t->size, | ||
948 | add_counter_to_entry, | ||
949 | counters, | ||
950 | &i); | ||
951 | local_bh_enable(); | 924 | local_bh_enable(); |
952 | } | 925 | } |
953 | 926 | ||
954 | |||
955 | static inline int | ||
956 | zero_entry_counter(struct ipt_entry *e, void *arg) | ||
957 | { | ||
958 | e->counters.bcnt = 0; | ||
959 | e->counters.pcnt = 0; | ||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static void | ||
964 | clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||
965 | { | ||
966 | unsigned int cpu; | ||
967 | const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||
968 | |||
969 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||
970 | for_each_possible_cpu(cpu) { | ||
971 | memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||
972 | IPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||
973 | zero_entry_counter, NULL); | ||
974 | } | ||
975 | } | ||
976 | |||
977 | static struct xt_counters * alloc_counters(struct xt_table *table) | 927 | static struct xt_counters * alloc_counters(struct xt_table *table) |
978 | { | 928 | { |
979 | unsigned int countersize; | 929 | unsigned int countersize; |
980 | struct xt_counters *counters; | 930 | struct xt_counters *counters; |
981 | struct xt_table_info *private = table->private; | 931 | struct xt_table_info *private = table->private; |
982 | struct xt_table_info *info; | ||
983 | 932 | ||
984 | /* We need atomic snapshot of counters: rest doesn't change | 933 | /* We need atomic snapshot of counters: rest doesn't change |
985 | (other than comefrom, which userspace doesn't care | 934 | (other than comefrom, which userspace doesn't care |
@@ -988,30 +937,11 @@ static struct xt_counters * alloc_counters(struct xt_table *table) | |||
988 | counters = vmalloc_node(countersize, numa_node_id()); | 937 | counters = vmalloc_node(countersize, numa_node_id()); |
989 | 938 | ||
990 | if (counters == NULL) | 939 | if (counters == NULL) |
991 | goto nomem; | 940 | return ERR_PTR(-ENOMEM); |
992 | 941 | ||
993 | info = xt_alloc_table_info(private->size); | 942 | get_counters(private, counters); |
994 | if (!info) | ||
995 | goto free_counters; | ||
996 | |||
997 | clone_counters(info, private); | ||
998 | |||
999 | mutex_lock(&table->lock); | ||
1000 | xt_table_entry_swap_rcu(private, info); | ||
1001 | synchronize_net(); /* Wait until smoke has cleared */ | ||
1002 | |||
1003 | get_counters(info, counters); | ||
1004 | put_counters(private, counters); | ||
1005 | mutex_unlock(&table->lock); | ||
1006 | |||
1007 | xt_free_table_info(info); | ||
1008 | 943 | ||
1009 | return counters; | 944 | return counters; |
1010 | |||
1011 | free_counters: | ||
1012 | vfree(counters); | ||
1013 | nomem: | ||
1014 | return ERR_PTR(-ENOMEM); | ||
1015 | } | 945 | } |
1016 | 946 | ||
1017 | static int | 947 | static int |
@@ -1306,8 +1236,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1306 | (newinfo->number <= oldinfo->initial_entries)) | 1236 | (newinfo->number <= oldinfo->initial_entries)) |
1307 | module_put(t->me); | 1237 | module_put(t->me); |
1308 | 1238 | ||
1309 | /* Get the old counters. */ | 1239 | /* Get the old counters, and synchronize with replace */ |
1310 | get_counters(oldinfo, counters); | 1240 | get_counters(oldinfo, counters); |
1241 | |||
1311 | /* Decrease module usage counts and free resource */ | 1242 | /* Decrease module usage counts and free resource */ |
1312 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1243 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1313 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | 1244 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, |
@@ -1377,11 +1308,23 @@ do_replace(struct net *net, void __user *user, unsigned int len) | |||
1377 | return ret; | 1308 | return ret; |
1378 | } | 1309 | } |
1379 | 1310 | ||
1311 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1312 | * and everything is OK. */ | ||
1313 | static int | ||
1314 | add_counter_to_entry(struct ipt_entry *e, | ||
1315 | const struct xt_counters addme[], | ||
1316 | unsigned int *i) | ||
1317 | { | ||
1318 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1319 | |||
1320 | (*i)++; | ||
1321 | return 0; | ||
1322 | } | ||
1380 | 1323 | ||
1381 | static int | 1324 | static int |
1382 | do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) | 1325 | do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) |
1383 | { | 1326 | { |
1384 | unsigned int i; | 1327 | unsigned int i, curcpu; |
1385 | struct xt_counters_info tmp; | 1328 | struct xt_counters_info tmp; |
1386 | struct xt_counters *paddc; | 1329 | struct xt_counters *paddc; |
1387 | unsigned int num_counters; | 1330 | unsigned int num_counters; |
@@ -1437,25 +1380,26 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat | |||
1437 | goto free; | 1380 | goto free; |
1438 | } | 1381 | } |
1439 | 1382 | ||
1440 | mutex_lock(&t->lock); | 1383 | local_bh_disable(); |
1441 | private = t->private; | 1384 | private = t->private; |
1442 | if (private->number != num_counters) { | 1385 | if (private->number != num_counters) { |
1443 | ret = -EINVAL; | 1386 | ret = -EINVAL; |
1444 | goto unlock_up_free; | 1387 | goto unlock_up_free; |
1445 | } | 1388 | } |
1446 | 1389 | ||
1447 | preempt_disable(); | ||
1448 | i = 0; | 1390 | i = 0; |
1449 | /* Choose the copy that is on our node */ | 1391 | /* Choose the copy that is on our node */ |
1450 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 1392 | curcpu = smp_processor_id(); |
1393 | loc_cpu_entry = private->entries[curcpu]; | ||
1394 | xt_info_wrlock(curcpu); | ||
1451 | IPT_ENTRY_ITERATE(loc_cpu_entry, | 1395 | IPT_ENTRY_ITERATE(loc_cpu_entry, |
1452 | private->size, | 1396 | private->size, |
1453 | add_counter_to_entry, | 1397 | add_counter_to_entry, |
1454 | paddc, | 1398 | paddc, |
1455 | &i); | 1399 | &i); |
1456 | preempt_enable(); | 1400 | xt_info_wrunlock(curcpu); |
1457 | unlock_up_free: | 1401 | unlock_up_free: |
1458 | mutex_unlock(&t->lock); | 1402 | local_bh_enable(); |
1459 | xt_table_unlock(t); | 1403 | xt_table_unlock(t); |
1460 | module_put(t->me); | 1404 | module_put(t->me); |
1461 | free: | 1405 | free: |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c40debe51b38..c4c60e9f068a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -3397,7 +3397,7 @@ int __init ip_rt_init(void) | |||
3397 | 0, | 3397 | 0, |
3398 | &rt_hash_log, | 3398 | &rt_hash_log, |
3399 | &rt_hash_mask, | 3399 | &rt_hash_mask, |
3400 | 0); | 3400 | rhash_entries ? 0 : 512 * 1024); |
3401 | memset(rt_hash_table, 0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket)); | 3401 | memset(rt_hash_table, 0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket)); |
3402 | rt_hash_lock_init(); | 3402 | rt_hash_lock_init(); |
3403 | 3403 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 800ae8542471..219e165aea10 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -365,9 +365,9 @@ ip6t_do_table(struct sk_buff *skb, | |||
365 | 365 | ||
366 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 366 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
367 | 367 | ||
368 | rcu_read_lock_bh(); | 368 | xt_info_rdlock_bh(); |
369 | private = rcu_dereference(table->private); | 369 | private = table->private; |
370 | table_base = rcu_dereference(private->entries[smp_processor_id()]); | 370 | table_base = private->entries[smp_processor_id()]; |
371 | 371 | ||
372 | e = get_entry(table_base, private->hook_entry[hook]); | 372 | e = get_entry(table_base, private->hook_entry[hook]); |
373 | 373 | ||
@@ -466,7 +466,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
466 | #ifdef CONFIG_NETFILTER_DEBUG | 466 | #ifdef CONFIG_NETFILTER_DEBUG |
467 | ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; | 467 | ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; |
468 | #endif | 468 | #endif |
469 | rcu_read_unlock_bh(); | 469 | xt_info_rdunlock_bh(); |
470 | 470 | ||
471 | #ifdef DEBUG_ALLOW_ALL | 471 | #ifdef DEBUG_ALLOW_ALL |
472 | return NF_ACCEPT; | 472 | return NF_ACCEPT; |
@@ -926,9 +926,12 @@ get_counters(const struct xt_table_info *t, | |||
926 | /* Instead of clearing (by a previous call to memset()) | 926 | /* Instead of clearing (by a previous call to memset()) |
927 | * the counters and using adds, we set the counters | 927 | * the counters and using adds, we set the counters |
928 | * with data used by 'current' CPU | 928 | * with data used by 'current' CPU |
929 | * We dont care about preemption here. | 929 | * |
930 | * Bottom half has to be disabled to prevent deadlock | ||
931 | * if new softirq were to run and call ipt_do_table | ||
930 | */ | 932 | */ |
931 | curcpu = raw_smp_processor_id(); | 933 | local_bh_disable(); |
934 | curcpu = smp_processor_id(); | ||
932 | 935 | ||
933 | i = 0; | 936 | i = 0; |
934 | IP6T_ENTRY_ITERATE(t->entries[curcpu], | 937 | IP6T_ENTRY_ITERATE(t->entries[curcpu], |
@@ -941,72 +944,22 @@ get_counters(const struct xt_table_info *t, | |||
941 | if (cpu == curcpu) | 944 | if (cpu == curcpu) |
942 | continue; | 945 | continue; |
943 | i = 0; | 946 | i = 0; |
947 | xt_info_wrlock(cpu); | ||
944 | IP6T_ENTRY_ITERATE(t->entries[cpu], | 948 | IP6T_ENTRY_ITERATE(t->entries[cpu], |
945 | t->size, | 949 | t->size, |
946 | add_entry_to_counter, | 950 | add_entry_to_counter, |
947 | counters, | 951 | counters, |
948 | &i); | 952 | &i); |
953 | xt_info_wrunlock(cpu); | ||
949 | } | 954 | } |
950 | } | ||
951 | |||
952 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
953 | * and everything is OK. */ | ||
954 | static int | ||
955 | add_counter_to_entry(struct ip6t_entry *e, | ||
956 | const struct xt_counters addme[], | ||
957 | unsigned int *i) | ||
958 | { | ||
959 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
960 | |||
961 | (*i)++; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | /* Take values from counters and add them back onto the current cpu */ | ||
966 | static void put_counters(struct xt_table_info *t, | ||
967 | const struct xt_counters counters[]) | ||
968 | { | ||
969 | unsigned int i, cpu; | ||
970 | |||
971 | local_bh_disable(); | ||
972 | cpu = smp_processor_id(); | ||
973 | i = 0; | ||
974 | IP6T_ENTRY_ITERATE(t->entries[cpu], | ||
975 | t->size, | ||
976 | add_counter_to_entry, | ||
977 | counters, | ||
978 | &i); | ||
979 | local_bh_enable(); | 955 | local_bh_enable(); |
980 | } | 956 | } |
981 | 957 | ||
982 | static inline int | ||
983 | zero_entry_counter(struct ip6t_entry *e, void *arg) | ||
984 | { | ||
985 | e->counters.bcnt = 0; | ||
986 | e->counters.pcnt = 0; | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static void | ||
991 | clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||
992 | { | ||
993 | unsigned int cpu; | ||
994 | const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||
995 | |||
996 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||
997 | for_each_possible_cpu(cpu) { | ||
998 | memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||
999 | IP6T_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||
1000 | zero_entry_counter, NULL); | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | static struct xt_counters *alloc_counters(struct xt_table *table) | 958 | static struct xt_counters *alloc_counters(struct xt_table *table) |
1005 | { | 959 | { |
1006 | unsigned int countersize; | 960 | unsigned int countersize; |
1007 | struct xt_counters *counters; | 961 | struct xt_counters *counters; |
1008 | struct xt_table_info *private = table->private; | 962 | struct xt_table_info *private = table->private; |
1009 | struct xt_table_info *info; | ||
1010 | 963 | ||
1011 | /* We need atomic snapshot of counters: rest doesn't change | 964 | /* We need atomic snapshot of counters: rest doesn't change |
1012 | (other than comefrom, which userspace doesn't care | 965 | (other than comefrom, which userspace doesn't care |
@@ -1015,30 +968,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | |||
1015 | counters = vmalloc_node(countersize, numa_node_id()); | 968 | counters = vmalloc_node(countersize, numa_node_id()); |
1016 | 969 | ||
1017 | if (counters == NULL) | 970 | if (counters == NULL) |
1018 | goto nomem; | 971 | return ERR_PTR(-ENOMEM); |
1019 | 972 | ||
1020 | info = xt_alloc_table_info(private->size); | 973 | get_counters(private, counters); |
1021 | if (!info) | ||
1022 | goto free_counters; | ||
1023 | |||
1024 | clone_counters(info, private); | ||
1025 | |||
1026 | mutex_lock(&table->lock); | ||
1027 | xt_table_entry_swap_rcu(private, info); | ||
1028 | synchronize_net(); /* Wait until smoke has cleared */ | ||
1029 | |||
1030 | get_counters(info, counters); | ||
1031 | put_counters(private, counters); | ||
1032 | mutex_unlock(&table->lock); | ||
1033 | |||
1034 | xt_free_table_info(info); | ||
1035 | 974 | ||
1036 | return counters; | 975 | return counters; |
1037 | |||
1038 | free_counters: | ||
1039 | vfree(counters); | ||
1040 | nomem: | ||
1041 | return ERR_PTR(-ENOMEM); | ||
1042 | } | 976 | } |
1043 | 977 | ||
1044 | static int | 978 | static int |
@@ -1334,8 +1268,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1334 | (newinfo->number <= oldinfo->initial_entries)) | 1268 | (newinfo->number <= oldinfo->initial_entries)) |
1335 | module_put(t->me); | 1269 | module_put(t->me); |
1336 | 1270 | ||
1337 | /* Get the old counters. */ | 1271 | /* Get the old counters, and synchronize with replace */ |
1338 | get_counters(oldinfo, counters); | 1272 | get_counters(oldinfo, counters); |
1273 | |||
1339 | /* Decrease module usage counts and free resource */ | 1274 | /* Decrease module usage counts and free resource */ |
1340 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1275 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1341 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | 1276 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, |
@@ -1405,11 +1340,24 @@ do_replace(struct net *net, void __user *user, unsigned int len) | |||
1405 | return ret; | 1340 | return ret; |
1406 | } | 1341 | } |
1407 | 1342 | ||
1343 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1344 | * and everything is OK. */ | ||
1345 | static int | ||
1346 | add_counter_to_entry(struct ip6t_entry *e, | ||
1347 | const struct xt_counters addme[], | ||
1348 | unsigned int *i) | ||
1349 | { | ||
1350 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1351 | |||
1352 | (*i)++; | ||
1353 | return 0; | ||
1354 | } | ||
1355 | |||
1408 | static int | 1356 | static int |
1409 | do_add_counters(struct net *net, void __user *user, unsigned int len, | 1357 | do_add_counters(struct net *net, void __user *user, unsigned int len, |
1410 | int compat) | 1358 | int compat) |
1411 | { | 1359 | { |
1412 | unsigned int i; | 1360 | unsigned int i, curcpu; |
1413 | struct xt_counters_info tmp; | 1361 | struct xt_counters_info tmp; |
1414 | struct xt_counters *paddc; | 1362 | struct xt_counters *paddc; |
1415 | unsigned int num_counters; | 1363 | unsigned int num_counters; |
@@ -1465,25 +1413,28 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, | |||
1465 | goto free; | 1413 | goto free; |
1466 | } | 1414 | } |
1467 | 1415 | ||
1468 | mutex_lock(&t->lock); | 1416 | |
1417 | local_bh_disable(); | ||
1469 | private = t->private; | 1418 | private = t->private; |
1470 | if (private->number != num_counters) { | 1419 | if (private->number != num_counters) { |
1471 | ret = -EINVAL; | 1420 | ret = -EINVAL; |
1472 | goto unlock_up_free; | 1421 | goto unlock_up_free; |
1473 | } | 1422 | } |
1474 | 1423 | ||
1475 | preempt_disable(); | ||
1476 | i = 0; | 1424 | i = 0; |
1477 | /* Choose the copy that is on our node */ | 1425 | /* Choose the copy that is on our node */ |
1478 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 1426 | curcpu = smp_processor_id(); |
1427 | xt_info_wrlock(curcpu); | ||
1428 | loc_cpu_entry = private->entries[curcpu]; | ||
1479 | IP6T_ENTRY_ITERATE(loc_cpu_entry, | 1429 | IP6T_ENTRY_ITERATE(loc_cpu_entry, |
1480 | private->size, | 1430 | private->size, |
1481 | add_counter_to_entry, | 1431 | add_counter_to_entry, |
1482 | paddc, | 1432 | paddc, |
1483 | &i); | 1433 | &i); |
1484 | preempt_enable(); | 1434 | xt_info_wrunlock(curcpu); |
1435 | |||
1485 | unlock_up_free: | 1436 | unlock_up_free: |
1486 | mutex_unlock(&t->lock); | 1437 | local_bh_enable(); |
1487 | xt_table_unlock(t); | 1438 | xt_table_unlock(t); |
1488 | module_put(t->me); | 1439 | module_put(t->me); |
1489 | free: | 1440 | free: |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 2329c5f50551..881203c4a142 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -275,6 +275,8 @@ config NF_CT_NETLINK | |||
275 | help | 275 | help |
276 | This option enables support for a netlink-based userspace interface | 276 | This option enables support for a netlink-based userspace interface |
277 | 277 | ||
278 | endif # NF_CONNTRACK | ||
279 | |||
278 | # transparent proxy support | 280 | # transparent proxy support |
279 | config NETFILTER_TPROXY | 281 | config NETFILTER_TPROXY |
280 | tristate "Transparent proxying support (EXPERIMENTAL)" | 282 | tristate "Transparent proxying support (EXPERIMENTAL)" |
@@ -290,8 +292,6 @@ config NETFILTER_TPROXY | |||
290 | 292 | ||
291 | To compile it as a module, choose M here. If unsure, say N. | 293 | To compile it as a module, choose M here. If unsure, say N. |
292 | 294 | ||
293 | endif # NF_CONNTRACK | ||
294 | |||
295 | config NETFILTER_XTABLES | 295 | config NETFILTER_XTABLES |
296 | tristate "Netfilter Xtables support (required for ip_tables)" | 296 | tristate "Netfilter Xtables support (required for ip_tables)" |
297 | default m if NETFILTER_ADVANCED=n | 297 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 50dac8dbe7d8..8e757dd53396 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -633,6 +633,8 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, | |||
633 | if (!nest_parms) | 633 | if (!nest_parms) |
634 | goto nla_put_failure; | 634 | goto nla_put_failure; |
635 | NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); | 635 | NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); |
636 | NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE, | ||
637 | ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]); | ||
636 | nla_nest_end(skb, nest_parms); | 638 | nla_nest_end(skb, nest_parms); |
637 | read_unlock_bh(&dccp_lock); | 639 | read_unlock_bh(&dccp_lock); |
638 | return 0; | 640 | return 0; |
@@ -644,6 +646,7 @@ nla_put_failure: | |||
644 | 646 | ||
645 | static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { | 647 | static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { |
646 | [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, | 648 | [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, |
649 | [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 }, | ||
647 | }; | 650 | }; |
648 | 651 | ||
649 | static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | 652 | static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) |
@@ -661,11 +664,21 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | |||
661 | return err; | 664 | return err; |
662 | 665 | ||
663 | if (!tb[CTA_PROTOINFO_DCCP_STATE] || | 666 | if (!tb[CTA_PROTOINFO_DCCP_STATE] || |
664 | nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) | 667 | !tb[CTA_PROTOINFO_DCCP_ROLE] || |
668 | nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX || | ||
669 | nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) { | ||
665 | return -EINVAL; | 670 | return -EINVAL; |
671 | } | ||
666 | 672 | ||
667 | write_lock_bh(&dccp_lock); | 673 | write_lock_bh(&dccp_lock); |
668 | ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); | 674 | ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); |
675 | if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { | ||
676 | ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; | ||
677 | ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; | ||
678 | } else { | ||
679 | ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER; | ||
680 | ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT; | ||
681 | } | ||
669 | write_unlock_bh(&dccp_lock); | 682 | write_unlock_bh(&dccp_lock); |
670 | return 0; | 683 | return 0; |
671 | } | 684 | } |
@@ -777,6 +790,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { | |||
777 | .print_conntrack = dccp_print_conntrack, | 790 | .print_conntrack = dccp_print_conntrack, |
778 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 791 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
779 | .to_nlattr = dccp_to_nlattr, | 792 | .to_nlattr = dccp_to_nlattr, |
793 | .nlattr_size = dccp_nlattr_size, | ||
780 | .from_nlattr = nlattr_to_dccp, | 794 | .from_nlattr = nlattr_to_dccp, |
781 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, | 795 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
782 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, | 796 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, |
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 4614696c1b88..0badedc542d3 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c | |||
@@ -204,6 +204,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = | |||
204 | .error = udplite_error, | 204 | .error = udplite_error, |
205 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 205 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
206 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, | 206 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
207 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, | ||
207 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, | 208 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
208 | .nla_policy = nf_ct_port_nla_policy, | 209 | .nla_policy = nf_ct_port_nla_policy, |
209 | #endif | 210 | #endif |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 509a95621f9f..150e5cf62f85 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -625,20 +625,6 @@ void xt_free_table_info(struct xt_table_info *info) | |||
625 | } | 625 | } |
626 | EXPORT_SYMBOL(xt_free_table_info); | 626 | EXPORT_SYMBOL(xt_free_table_info); |
627 | 627 | ||
628 | void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo, | ||
629 | struct xt_table_info *newinfo) | ||
630 | { | ||
631 | unsigned int cpu; | ||
632 | |||
633 | for_each_possible_cpu(cpu) { | ||
634 | void *p = oldinfo->entries[cpu]; | ||
635 | rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]); | ||
636 | newinfo->entries[cpu] = p; | ||
637 | } | ||
638 | |||
639 | } | ||
640 | EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu); | ||
641 | |||
642 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | 628 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ |
643 | struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, | 629 | struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, |
644 | const char *name) | 630 | const char *name) |
@@ -676,32 +662,43 @@ void xt_compat_unlock(u_int8_t af) | |||
676 | EXPORT_SYMBOL_GPL(xt_compat_unlock); | 662 | EXPORT_SYMBOL_GPL(xt_compat_unlock); |
677 | #endif | 663 | #endif |
678 | 664 | ||
665 | DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); | ||
666 | EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); | ||
667 | |||
668 | |||
679 | struct xt_table_info * | 669 | struct xt_table_info * |
680 | xt_replace_table(struct xt_table *table, | 670 | xt_replace_table(struct xt_table *table, |
681 | unsigned int num_counters, | 671 | unsigned int num_counters, |
682 | struct xt_table_info *newinfo, | 672 | struct xt_table_info *newinfo, |
683 | int *error) | 673 | int *error) |
684 | { | 674 | { |
685 | struct xt_table_info *oldinfo, *private; | 675 | struct xt_table_info *private; |
686 | 676 | ||
687 | /* Do the substitution. */ | 677 | /* Do the substitution. */ |
688 | mutex_lock(&table->lock); | 678 | local_bh_disable(); |
689 | private = table->private; | 679 | private = table->private; |
680 | |||
690 | /* Check inside lock: is the old number correct? */ | 681 | /* Check inside lock: is the old number correct? */ |
691 | if (num_counters != private->number) { | 682 | if (num_counters != private->number) { |
692 | duprintf("num_counters != table->private->number (%u/%u)\n", | 683 | duprintf("num_counters != table->private->number (%u/%u)\n", |
693 | num_counters, private->number); | 684 | num_counters, private->number); |
694 | mutex_unlock(&table->lock); | 685 | local_bh_enable(); |
695 | *error = -EAGAIN; | 686 | *error = -EAGAIN; |
696 | return NULL; | 687 | return NULL; |
697 | } | 688 | } |
698 | oldinfo = private; | ||
699 | rcu_assign_pointer(table->private, newinfo); | ||
700 | newinfo->initial_entries = oldinfo->initial_entries; | ||
701 | mutex_unlock(&table->lock); | ||
702 | 689 | ||
703 | synchronize_net(); | 690 | table->private = newinfo; |
704 | return oldinfo; | 691 | newinfo->initial_entries = private->initial_entries; |
692 | |||
693 | /* | ||
694 | * Even though table entries have now been swapped, other CPU's | ||
695 | * may still be using the old entries. This is okay, because | ||
696 | * resynchronization happens because of the locking done | ||
697 | * during the get_counters() routine. | ||
698 | */ | ||
699 | local_bh_enable(); | ||
700 | |||
701 | return private; | ||
705 | } | 702 | } |
706 | EXPORT_SYMBOL_GPL(xt_replace_table); | 703 | EXPORT_SYMBOL_GPL(xt_replace_table); |
707 | 704 | ||
@@ -734,7 +731,6 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, | |||
734 | 731 | ||
735 | /* Simplifies replace_table code. */ | 732 | /* Simplifies replace_table code. */ |
736 | table->private = bootstrap; | 733 | table->private = bootstrap; |
737 | mutex_init(&table->lock); | ||
738 | 734 | ||
739 | if (!xt_replace_table(table, 0, newinfo, &ret)) | 735 | if (!xt_replace_table(table, 0, newinfo, &ret)) |
740 | goto unlock; | 736 | goto unlock; |
@@ -1147,7 +1143,14 @@ static struct pernet_operations xt_net_ops = { | |||
1147 | 1143 | ||
1148 | static int __init xt_init(void) | 1144 | static int __init xt_init(void) |
1149 | { | 1145 | { |
1150 | int i, rv; | 1146 | unsigned int i; |
1147 | int rv; | ||
1148 | |||
1149 | for_each_possible_cpu(i) { | ||
1150 | struct xt_info_lock *lock = &per_cpu(xt_info_locks, i); | ||
1151 | spin_lock_init(&lock->lock); | ||
1152 | lock->readers = 0; | ||
1153 | } | ||
1151 | 1154 | ||
1152 | xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); | 1155 | xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); |
1153 | if (!xt) | 1156 | if (!xt) |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 791e030ea903..eb0ceb846527 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -474,7 +474,7 @@ static ssize_t recent_old_proc_write(struct file *file, | |||
474 | struct recent_table *t = pde->data; | 474 | struct recent_table *t = pde->data; |
475 | struct recent_entry *e; | 475 | struct recent_entry *e; |
476 | char buf[sizeof("+255.255.255.255")], *c = buf; | 476 | char buf[sizeof("+255.255.255.255")], *c = buf; |
477 | __be32 addr; | 477 | union nf_inet_addr addr = {}; |
478 | int add; | 478 | int add; |
479 | 479 | ||
480 | if (size > sizeof(buf)) | 480 | if (size > sizeof(buf)) |
@@ -506,14 +506,13 @@ static ssize_t recent_old_proc_write(struct file *file, | |||
506 | add = 1; | 506 | add = 1; |
507 | break; | 507 | break; |
508 | } | 508 | } |
509 | addr = in_aton(c); | 509 | addr.ip = in_aton(c); |
510 | 510 | ||
511 | spin_lock_bh(&recent_lock); | 511 | spin_lock_bh(&recent_lock); |
512 | e = recent_entry_lookup(t, (const void *)&addr, NFPROTO_IPV4, 0); | 512 | e = recent_entry_lookup(t, &addr, NFPROTO_IPV4, 0); |
513 | if (e == NULL) { | 513 | if (e == NULL) { |
514 | if (add) | 514 | if (add) |
515 | recent_entry_init(t, (const void *)&addr, | 515 | recent_entry_init(t, &addr, NFPROTO_IPV4, 0); |
516 | NFPROTO_IPV4, 0); | ||
517 | } else { | 516 | } else { |
518 | if (add) | 517 | if (add) |
519 | recent_entry_update(t, e); | 518 | recent_entry_update(t, e); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 82271720d970..5f1f86565f16 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -794,7 +794,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
794 | { | 794 | { |
795 | static xfrm_address_t saddr_wildcard = { }; | 795 | static xfrm_address_t saddr_wildcard = { }; |
796 | struct net *net = xp_net(pol); | 796 | struct net *net = xp_net(pol); |
797 | unsigned int h; | 797 | unsigned int h, h_wildcard; |
798 | struct hlist_node *entry; | 798 | struct hlist_node *entry; |
799 | struct xfrm_state *x, *x0, *to_put; | 799 | struct xfrm_state *x, *x0, *to_put; |
800 | int acquire_in_progress = 0; | 800 | int acquire_in_progress = 0; |
@@ -819,8 +819,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
819 | if (best) | 819 | if (best) |
820 | goto found; | 820 | goto found; |
821 | 821 | ||
822 | h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | 822 | h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); |
823 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { | 823 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { |
824 | if (x->props.family == family && | 824 | if (x->props.family == family && |
825 | x->props.reqid == tmpl->reqid && | 825 | x->props.reqid == tmpl->reqid && |
826 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 826 | !(x->props.flags & XFRM_STATE_WILDRECV) && |