diff options
| -rw-r--r-- | Documentation/workqueue.txt | 40 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 5 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-parport.c | 27 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 4 | ||||
| -rw-r--r-- | kernel/workqueue.c | 8 | ||||
| -rw-r--r-- | lib/xz/xz_dec_lzma2.c | 6 |
6 files changed, 69 insertions, 21 deletions
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt index 01c513fac40e..a0b577de918f 100644 --- a/Documentation/workqueue.txt +++ b/Documentation/workqueue.txt | |||
| @@ -12,6 +12,7 @@ CONTENTS | |||
| 12 | 4. Application Programming Interface (API) | 12 | 4. Application Programming Interface (API) |
| 13 | 5. Example Execution Scenarios | 13 | 5. Example Execution Scenarios |
| 14 | 6. Guidelines | 14 | 6. Guidelines |
| 15 | 7. Debugging | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 1. Introduction | 18 | 1. Introduction |
| @@ -379,3 +380,42 @@ If q1 has WQ_CPU_INTENSIVE set, | |||
| 379 | * Unless work items are expected to consume a huge amount of CPU | 380 | * Unless work items are expected to consume a huge amount of CPU |
| 380 | cycles, using a bound wq is usually beneficial due to the increased | 381 | cycles, using a bound wq is usually beneficial due to the increased |
| 381 | level of locality in wq operations and work item execution. | 382 | level of locality in wq operations and work item execution. |
| 383 | |||
| 384 | |||
| 385 | 7. Debugging | ||
| 386 | |||
| 387 | Because the work functions are executed by generic worker threads | ||
| 388 | there are a few tricks needed to shed some light on misbehaving | ||
| 389 | workqueue users. | ||
| 390 | |||
| 391 | Worker threads show up in the process list as: | ||
| 392 | |||
| 393 | root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1] | ||
| 394 | root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2] | ||
| 395 | root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0] | ||
| 396 | root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0] | ||
| 397 | |||
| 398 | If kworkers are going crazy (using too much cpu), there are two types | ||
| 399 | of possible problems: | ||
| 400 | |||
| 401 | 1. Something beeing scheduled in rapid succession | ||
| 402 | 2. A single work item that consumes lots of cpu cycles | ||
| 403 | |||
| 404 | The first one can be tracked using tracing: | ||
| 405 | |||
| 406 | $ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event | ||
| 407 | $ cat /sys/kernel/debug/tracing/trace_pipe > out.txt | ||
| 408 | (wait a few secs) | ||
| 409 | ^C | ||
| 410 | |||
| 411 | If something is busy looping on work queueing, it would be dominating | ||
| 412 | the output and the offender can be determined with the work item | ||
| 413 | function. | ||
| 414 | |||
| 415 | For the second type of problems it should be possible to just check | ||
| 416 | the stack trace of the offending worker thread. | ||
| 417 | |||
| 418 | $ cat /proc/THE_OFFENDING_KWORKER/stack | ||
| 419 | |||
| 420 | The work item's function should be trivially visible in the stack | ||
| 421 | trace. | ||
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 72c0415f6f94..455e909bc768 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
| @@ -134,10 +134,15 @@ | |||
| 134 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ | 134 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ |
| 135 | SMBHSTSTS_INTR) | 135 | SMBHSTSTS_INTR) |
| 136 | 136 | ||
| 137 | /* Older devices have their ID defined in <linux/pci_ids.h> */ | ||
| 138 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 | ||
| 139 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | ||
| 137 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ | 140 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ |
| 138 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 | 141 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 |
| 139 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 | 142 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 |
| 140 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 | 143 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 |
| 144 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 | ||
| 145 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 | ||
| 141 | 146 | ||
| 142 | struct i801_priv { | 147 | struct i801_priv { |
| 143 | struct i2c_adapter adapter; | 148 | struct i2c_adapter adapter; |
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 0eb1515541e7..2dbba163b102 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* ------------------------------------------------------------------------ * | 1 | /* ------------------------------------------------------------------------ * |
| 2 | * i2c-parport.c I2C bus over parallel port * | 2 | * i2c-parport.c I2C bus over parallel port * |
| 3 | * ------------------------------------------------------------------------ * | 3 | * ------------------------------------------------------------------------ * |
| 4 | Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> | 4 | Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org> |
| 5 | 5 | ||
| 6 | Based on older i2c-philips-par.c driver | 6 | Based on older i2c-philips-par.c driver |
| 7 | Copyright (C) 1995-2000 Simon G. Vogl | 7 | Copyright (C) 1995-2000 Simon G. Vogl |
| @@ -33,6 +33,8 @@ | |||
| 33 | #include <linux/i2c-algo-bit.h> | 33 | #include <linux/i2c-algo-bit.h> |
| 34 | #include <linux/i2c-smbus.h> | 34 | #include <linux/i2c-smbus.h> |
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/list.h> | ||
| 37 | #include <linux/mutex.h> | ||
| 36 | #include "i2c-parport.h" | 38 | #include "i2c-parport.h" |
| 37 | 39 | ||
| 38 | /* ----- Device list ------------------------------------------------------ */ | 40 | /* ----- Device list ------------------------------------------------------ */ |
| @@ -43,10 +45,11 @@ struct i2c_par { | |||
| 43 | struct i2c_algo_bit_data algo_data; | 45 | struct i2c_algo_bit_data algo_data; |
| 44 | struct i2c_smbus_alert_setup alert_data; | 46 | struct i2c_smbus_alert_setup alert_data; |
| 45 | struct i2c_client *ara; | 47 | struct i2c_client *ara; |
| 46 | struct i2c_par *next; | 48 | struct list_head node; |
| 47 | }; | 49 | }; |
| 48 | 50 | ||
| 49 | static struct i2c_par *adapter_list; | 51 | static LIST_HEAD(adapter_list); |
| 52 | static DEFINE_MUTEX(adapter_list_lock); | ||
| 50 | 53 | ||
| 51 | /* ----- Low-level parallel port access ----------------------------------- */ | 54 | /* ----- Low-level parallel port access ----------------------------------- */ |
| 52 | 55 | ||
| @@ -228,8 +231,9 @@ static void i2c_parport_attach (struct parport *port) | |||
| 228 | } | 231 | } |
| 229 | 232 | ||
| 230 | /* Add the new adapter to the list */ | 233 | /* Add the new adapter to the list */ |
| 231 | adapter->next = adapter_list; | 234 | mutex_lock(&adapter_list_lock); |
| 232 | adapter_list = adapter; | 235 | list_add_tail(&adapter->node, &adapter_list); |
| 236 | mutex_unlock(&adapter_list_lock); | ||
| 233 | return; | 237 | return; |
| 234 | 238 | ||
| 235 | ERROR1: | 239 | ERROR1: |
| @@ -241,11 +245,11 @@ ERROR0: | |||
| 241 | 245 | ||
| 242 | static void i2c_parport_detach (struct parport *port) | 246 | static void i2c_parport_detach (struct parport *port) |
| 243 | { | 247 | { |
| 244 | struct i2c_par *adapter, *prev; | 248 | struct i2c_par *adapter, *_n; |
| 245 | 249 | ||
| 246 | /* Walk the list */ | 250 | /* Walk the list */ |
| 247 | for (prev = NULL, adapter = adapter_list; adapter; | 251 | mutex_lock(&adapter_list_lock); |
| 248 | prev = adapter, adapter = adapter->next) { | 252 | list_for_each_entry_safe(adapter, _n, &adapter_list, node) { |
| 249 | if (adapter->pdev->port == port) { | 253 | if (adapter->pdev->port == port) { |
| 250 | if (adapter->ara) { | 254 | if (adapter->ara) { |
| 251 | parport_disable_irq(port); | 255 | parport_disable_irq(port); |
| @@ -259,14 +263,11 @@ static void i2c_parport_detach (struct parport *port) | |||
| 259 | 263 | ||
| 260 | parport_release(adapter->pdev); | 264 | parport_release(adapter->pdev); |
| 261 | parport_unregister_device(adapter->pdev); | 265 | parport_unregister_device(adapter->pdev); |
| 262 | if (prev) | 266 | list_del(&adapter->node); |
| 263 | prev->next = adapter->next; | ||
| 264 | else | ||
| 265 | adapter_list = adapter->next; | ||
| 266 | kfree(adapter); | 267 | kfree(adapter); |
| 267 | return; | ||
| 268 | } | 268 | } |
| 269 | } | 269 | } |
| 270 | mutex_unlock(&adapter_list_lock); | ||
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | static struct parport_driver i2c_parport_driver = { | 273 | static struct parport_driver i2c_parport_driver = { |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4e2c9150a785..8abe8d78c4bf 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2477,15 +2477,12 @@ | |||
| 2477 | #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 | 2477 | #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 |
| 2478 | #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 | 2478 | #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 |
| 2479 | #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 | 2479 | #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 |
| 2480 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 | ||
| 2481 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41 | 2480 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41 |
| 2482 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f | 2481 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f |
| 2483 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | ||
| 2484 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 | 2482 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 |
| 2485 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 | 2483 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 |
| 2486 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 | 2484 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 |
| 2487 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f | 2485 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f |
| 2488 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 | ||
| 2489 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 | 2486 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 |
| 2490 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 | 2487 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 |
| 2491 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 | 2488 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 |
| @@ -2696,7 +2693,6 @@ | |||
| 2696 | #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 | 2693 | #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 |
| 2697 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00 | 2694 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00 |
| 2698 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f | 2695 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f |
| 2699 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 | ||
| 2700 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f | 2696 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f |
| 2701 | #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 | 2697 | #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 |
| 2702 | #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 | 2698 | #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 8859a41806dd..e3378e8d3a5c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -1291,8 +1291,14 @@ __acquires(&gcwq->lock) | |||
| 1291 | return true; | 1291 | return true; |
| 1292 | spin_unlock_irq(&gcwq->lock); | 1292 | spin_unlock_irq(&gcwq->lock); |
| 1293 | 1293 | ||
| 1294 | /* CPU has come up in between, retry migration */ | 1294 | /* |
| 1295 | * We've raced with CPU hot[un]plug. Give it a breather | ||
| 1296 | * and retry migration. cond_resched() is required here; | ||
| 1297 | * otherwise, we might deadlock against cpu_stop trying to | ||
| 1298 | * bring down the CPU on non-preemptive kernel. | ||
| 1299 | */ | ||
| 1295 | cpu_relax(); | 1300 | cpu_relax(); |
| 1301 | cond_resched(); | ||
| 1296 | } | 1302 | } |
| 1297 | } | 1303 | } |
| 1298 | 1304 | ||
diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c index ea5fa4fe9d67..a6cdc969ea42 100644 --- a/lib/xz/xz_dec_lzma2.c +++ b/lib/xz/xz_dec_lzma2.c | |||
| @@ -969,6 +969,9 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, | |||
| 969 | */ | 969 | */ |
| 970 | tmp = b->in[b->in_pos++]; | 970 | tmp = b->in[b->in_pos++]; |
| 971 | 971 | ||
| 972 | if (tmp == 0x00) | ||
| 973 | return XZ_STREAM_END; | ||
| 974 | |||
| 972 | if (tmp >= 0xE0 || tmp == 0x01) { | 975 | if (tmp >= 0xE0 || tmp == 0x01) { |
| 973 | s->lzma2.need_props = true; | 976 | s->lzma2.need_props = true; |
| 974 | s->lzma2.need_dict_reset = false; | 977 | s->lzma2.need_dict_reset = false; |
| @@ -1001,9 +1004,6 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, | |||
| 1001 | lzma_reset(s); | 1004 | lzma_reset(s); |
| 1002 | } | 1005 | } |
| 1003 | } else { | 1006 | } else { |
| 1004 | if (tmp == 0x00) | ||
| 1005 | return XZ_STREAM_END; | ||
| 1006 | |||
| 1007 | if (tmp > 0x02) | 1007 | if (tmp > 0x02) |
| 1008 | return XZ_DATA_ERROR; | 1008 | return XZ_DATA_ERROR; |
| 1009 | 1009 | ||
