diff options
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) && |
