Update to 4.5-rc4
Drop many, many patches which went upstream. Refresh others for filename or context changes, and for removal of radeon UMS support. [rt] Disable until it is updated for 4.5 or later aufs: Update support patches to aufs4.x-rcN-20160215
This commit is contained in:
parent
daf081c8a9
commit
4b4fa14653
|
@ -1,7 +1,14 @@
|
|||
linux (4.4.1-1~exp2) UNRELEASED; urgency=medium
|
||||
linux (4.5~rc4-1~exp1) UNRELEASED; urgency=medium
|
||||
|
||||
* New upstream release candidate
|
||||
|
||||
[ Roger Shimizu ]
|
||||
* Enable TTY_PRINTK as module (Closes: #814540).
|
||||
|
||||
[ Ben Hutchings ]
|
||||
* [rt] Disable until it is updated for 4.5 or later
|
||||
* aufs: Update support patches to aufs4.x-rcN-20160215
|
||||
|
||||
-- Roger Shimizu <rogershimizu@gmail.com> Sun, 14 Feb 2016 00:32:40 +0900
|
||||
|
||||
linux (4.4.1-1~exp1) experimental; urgency=medium
|
||||
|
|
|
@ -32,7 +32,7 @@ featuresets:
|
|||
rt
|
||||
|
||||
[featureset-rt_base]
|
||||
enabled: true
|
||||
enabled: false
|
||||
|
||||
[description]
|
||||
part-long-up: This kernel is not suitable for SMP (multi-processor,
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
From: Kent Overstreet <kmo@daterainc.com>
|
||||
Date: Sun, 29 Nov 2015 17:18:33 -0800
|
||||
Subject: [2/8] bcache: Add a cond_resched() call to gc
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=c5f1e5adf956e3ba82d204c7c141a75da9fa449a
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
Tested-by: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/btree.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
|
||||
index 4a1179c..22b9e34 100644
|
||||
--- a/drivers/md/bcache/btree.c
|
||||
+++ b/drivers/md/bcache/btree.c
|
||||
@@ -1741,6 +1741,7 @@ static void bch_btree_gc(struct cache_set *c)
|
||||
do {
|
||||
ret = btree_root(gc_root, c, &op, &writes, &stats);
|
||||
closure_sync(&writes);
|
||||
+ cond_resched();
|
||||
|
||||
if (ret && ret != -EAGAIN)
|
||||
pr_warn("gc failed!");
|
|
@ -1,46 +0,0 @@
|
|||
From: Gabriel de Perthuis <g2p.code@gmail.com>
|
||||
Date: Sun, 29 Nov 2015 18:40:23 -0800
|
||||
Subject: [6/8] bcache: allows use of register in udev to avoid "device_busy"
|
||||
error.
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=d7076f21629f8f329bca4a44dc408d94670f49e2
|
||||
|
||||
Allows to use register, not register_quiet in udev to avoid "device_busy" error.
|
||||
The initial patch proposed at https://lkml.org/lkml/2013/8/26/549 by Gabriel de Perthuis
|
||||
<g2p.code@gmail.com> does not unlock the mutex and hangs the kernel.
|
||||
|
||||
See http://thread.gmane.org/gmane.linux.kernel.bcache.devel/2594 for the discussion.
|
||||
|
||||
Cc: Denis Bychkov <manover@gmail.com>
|
||||
Cc: Kent Overstreet <kent.overstreet@gmail.com>
|
||||
Cc: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Gabriel de Perthuis <g2p.code@gmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/super.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
|
||||
index 18f14a2..8d0ead9 100644
|
||||
--- a/drivers/md/bcache/super.c
|
||||
+++ b/drivers/md/bcache/super.c
|
||||
@@ -1938,6 +1938,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
|
||||
else
|
||||
err = "device busy";
|
||||
mutex_unlock(&bch_register_lock);
|
||||
+ if (attr == &ksysfs_register_quiet)
|
||||
+ goto out;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
@@ -1976,8 +1978,7 @@ out:
|
||||
err_close:
|
||||
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
||||
err:
|
||||
- if (attr != &ksysfs_register_quiet)
|
||||
- pr_info("error opening %s: %s", path, err);
|
||||
+ pr_info("error opening %s: %s", path, err);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
From: Kent Overstreet <kent.overstreet@gmail.com>
|
||||
Date: Sun, 29 Nov 2015 18:47:01 -0800
|
||||
Subject: [8/8] bcache: Change refill_dirty() to always scan entire disk if
|
||||
necessary
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=627ccd20b4ad3ba836472468208e2ac4dfadbf03
|
||||
|
||||
Previously, it would only scan the entire disk if it was starting from
|
||||
the very start of the disk - i.e. if the previous scan got to the end.
|
||||
|
||||
This was broken by refill_full_stripes(), which updates last_scanned so
|
||||
that refill_dirty was never triggering the searched_from_start path.
|
||||
|
||||
But if we change refill_dirty() to always scan the entire disk if
|
||||
necessary, regardless of what last_scanned was, the code gets cleaner
|
||||
and we fix that bug too.
|
||||
|
||||
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/writeback.c | 37 ++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 30 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
|
||||
index b23f88d..b9346cd 100644
|
||||
--- a/drivers/md/bcache/writeback.c
|
||||
+++ b/drivers/md/bcache/writeback.c
|
||||
@@ -323,6 +323,10 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
|
||||
|
||||
static bool dirty_pred(struct keybuf *buf, struct bkey *k)
|
||||
{
|
||||
+ struct cached_dev *dc = container_of(buf, struct cached_dev, writeback_keys);
|
||||
+
|
||||
+ BUG_ON(KEY_INODE(k) != dc->disk.id);
|
||||
+
|
||||
return KEY_DIRTY(k);
|
||||
}
|
||||
|
||||
@@ -372,11 +376,24 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Returns true if we scanned the entire disk
|
||||
+ */
|
||||
static bool refill_dirty(struct cached_dev *dc)
|
||||
{
|
||||
struct keybuf *buf = &dc->writeback_keys;
|
||||
+ struct bkey start = KEY(dc->disk.id, 0, 0);
|
||||
struct bkey end = KEY(dc->disk.id, MAX_KEY_OFFSET, 0);
|
||||
- bool searched_from_start = false;
|
||||
+ struct bkey start_pos;
|
||||
+
|
||||
+ /*
|
||||
+ * make sure keybuf pos is inside the range for this disk - at bringup
|
||||
+ * we might not be attached yet so this disk's inode nr isn't
|
||||
+ * initialized then
|
||||
+ */
|
||||
+ if (bkey_cmp(&buf->last_scanned, &start) < 0 ||
|
||||
+ bkey_cmp(&buf->last_scanned, &end) > 0)
|
||||
+ buf->last_scanned = start;
|
||||
|
||||
if (dc->partial_stripes_expensive) {
|
||||
refill_full_stripes(dc);
|
||||
@@ -384,14 +401,20 @@ static bool refill_dirty(struct cached_dev *dc)
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (bkey_cmp(&buf->last_scanned, &end) >= 0) {
|
||||
- buf->last_scanned = KEY(dc->disk.id, 0, 0);
|
||||
- searched_from_start = true;
|
||||
- }
|
||||
-
|
||||
+ start_pos = buf->last_scanned;
|
||||
bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred);
|
||||
|
||||
- return bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start;
|
||||
+ if (bkey_cmp(&buf->last_scanned, &end) < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ /*
|
||||
+ * If we get to the end start scanning again from the beginning, and
|
||||
+ * only scan up to where we initially started scanning from:
|
||||
+ */
|
||||
+ buf->last_scanned = start;
|
||||
+ bch_refill_keybuf(dc->disk.c, buf, &start_pos, dirty_pred);
|
||||
+
|
||||
+ return bkey_cmp(&buf->last_scanned, &start_pos) >= 0;
|
||||
}
|
||||
|
||||
static int bch_writeback_thread(void *arg)
|
|
@ -1,109 +0,0 @@
|
|||
From: Zheng Liu <wenqing.lz@taobao.com>
|
||||
Date: Sun, 29 Nov 2015 17:19:32 -0800
|
||||
Subject: [3/8] bcache: clear BCACHE_DEV_UNLINK_DONE flag when attaching a
|
||||
backing device
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=fecaee6f20ee122ad75402c53d8278f9bb142ddc
|
||||
|
||||
This bug can be reproduced by the following script:
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
bcache_sysfs="/sys/fs/bcache"
|
||||
|
||||
function clear_cache()
|
||||
{
|
||||
if [ ! -e $bcache_sysfs ]; then
|
||||
echo "no bcache sysfs"
|
||||
exit
|
||||
fi
|
||||
|
||||
cset_uuid=$(ls -l $bcache_sysfs|head -n 2|tail -n 1|awk '{print $9}')
|
||||
sudo sh -c "echo $cset_uuid > /sys/block/sdb/sdb1/bcache/detach"
|
||||
sleep 5
|
||||
sudo sh -c "echo $cset_uuid > /sys/block/sdb/sdb1/bcache/attach"
|
||||
}
|
||||
|
||||
for ((i=0;i<10;i++)); do
|
||||
clear_cache
|
||||
done
|
||||
|
||||
The warning messages look like below:
|
||||
[ 275.948611] ------------[ cut here ]------------
|
||||
[ 275.963840] WARNING: at fs/sysfs/dir.c:512 sysfs_add_one+0xb8/0xd0() (Tainted: P W
|
||||
--------------- )
|
||||
[ 275.979253] Hardware name: Tecal RH2285
|
||||
[ 275.994106] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:09.0/0000:08:00.0/host4/target4:2:1/4:2:1:0/block/sdb/sdb1/bcache/cache'
|
||||
[ 276.024105] Modules linked in: bcache tcp_diag inet_diag ipmi_devintf ipmi_si ipmi_msghandler
|
||||
bonding 8021q garp stp llc ipv6 ext3 jbd loop sg iomemory_vsl(P) bnx2 microcode serio_raw i2c_i801
|
||||
i2c_core iTCO_wdt iTCO_vendor_support i7core_edac edac_core shpchp ext4 jbd2 mbcache megaraid_sas
|
||||
pata_acpi ata_generic ata_piix dm_mod [last unloaded: scsi_wait_scan]
|
||||
[ 276.072643] Pid: 2765, comm: sh Tainted: P W --------------- 2.6.32 #1
|
||||
[ 276.089315] Call Trace:
|
||||
[ 276.105801] [<ffffffff81070fe7>] ? warn_slowpath_common+0x87/0xc0
|
||||
[ 276.122650] [<ffffffff810710d6>] ? warn_slowpath_fmt+0x46/0x50
|
||||
[ 276.139361] [<ffffffff81205c08>] ? sysfs_add_one+0xb8/0xd0
|
||||
[ 276.156012] [<ffffffff8120609b>] ? sysfs_do_create_link+0x12b/0x170
|
||||
[ 276.172682] [<ffffffff81206113>] ? sysfs_create_link+0x13/0x20
|
||||
[ 276.189282] [<ffffffffa03bda21>] ? bcache_device_link+0xc1/0x110 [bcache]
|
||||
[ 276.205993] [<ffffffffa03bfa08>] ? bch_cached_dev_attach+0x478/0x4f0 [bcache]
|
||||
[ 276.222794] [<ffffffffa03c4a17>] ? bch_cached_dev_store+0x627/0x780 [bcache]
|
||||
[ 276.239680] [<ffffffff8116783a>] ? alloc_pages_current+0xaa/0x110
|
||||
[ 276.256594] [<ffffffff81203b15>] ? sysfs_write_file+0xe5/0x170
|
||||
[ 276.273364] [<ffffffff811887b8>] ? vfs_write+0xb8/0x1a0
|
||||
[ 276.290133] [<ffffffff811890b1>] ? sys_write+0x51/0x90
|
||||
[ 276.306368] [<ffffffff8100c072>] ? system_call_fastpath+0x16/0x1b
|
||||
[ 276.322301] ---[ end trace 9f5d4fcdd0c3edfb ]---
|
||||
[ 276.338241] ------------[ cut here ]------------
|
||||
[ 276.354109] WARNING: at /home/wenqing.lz/bcache/bcache/super.c:720
|
||||
bcache_device_link+0xdf/0x110 [bcache]() (Tainted: P W --------------- )
|
||||
[ 276.386017] Hardware name: Tecal RH2285
|
||||
[ 276.401430] Couldn't create device <-> cache set symlinks
|
||||
[ 276.401759] Modules linked in: bcache tcp_diag inet_diag ipmi_devintf ipmi_si ipmi_msghandler
|
||||
bonding 8021q garp stp llc ipv6 ext3 jbd loop sg iomemory_vsl(P) bnx2 microcode serio_raw i2c_i801
|
||||
i2c_core iTCO_wdt iTCO_vendor_support i7core_edac edac_core shpchp ext4 jbd2 mbcache megaraid_sas
|
||||
pata_acpi ata_generic ata_piix dm_mod [last unloaded: scsi_wait_scan]
|
||||
[ 276.465477] Pid: 2765, comm: sh Tainted: P W --------------- 2.6.32 #1
|
||||
[ 276.482169] Call Trace:
|
||||
[ 276.498610] [<ffffffff81070fe7>] ? warn_slowpath_common+0x87/0xc0
|
||||
[ 276.515405] [<ffffffff810710d6>] ? warn_slowpath_fmt+0x46/0x50
|
||||
[ 276.532059] [<ffffffffa03bda3f>] ? bcache_device_link+0xdf/0x110 [bcache]
|
||||
[ 276.548808] [<ffffffffa03bfa08>] ? bch_cached_dev_attach+0x478/0x4f0 [bcache]
|
||||
[ 276.565569] [<ffffffffa03c4a17>] ? bch_cached_dev_store+0x627/0x780 [bcache]
|
||||
[ 276.582418] [<ffffffff8116783a>] ? alloc_pages_current+0xaa/0x110
|
||||
[ 276.599341] [<ffffffff81203b15>] ? sysfs_write_file+0xe5/0x170
|
||||
[ 276.616142] [<ffffffff811887b8>] ? vfs_write+0xb8/0x1a0
|
||||
[ 276.632607] [<ffffffff811890b1>] ? sys_write+0x51/0x90
|
||||
[ 276.648671] [<ffffffff8100c072>] ? system_call_fastpath+0x16/0x1b
|
||||
[ 276.664756] ---[ end trace 9f5d4fcdd0c3edfc ]---
|
||||
|
||||
We forget to clear BCACHE_DEV_UNLINK_DONE flag in bcache_device_attach()
|
||||
function when we attach a backing device first time. After detaching this
|
||||
backing device, this flag will be true and sysfs_remove_link() isn't called in
|
||||
bcache_device_unlink(). Then when we attach this backing device again,
|
||||
sysfs_create_link() will return EEXIST error in bcache_device_link().
|
||||
|
||||
So the fix is trival and we clear this flag in bcache_device_link().
|
||||
|
||||
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
|
||||
Tested-by: Joshua Schmid <jschmid@suse.com>
|
||||
Tested-by: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/super.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
|
||||
index 679a093..383f060 100644
|
||||
--- a/drivers/md/bcache/super.c
|
||||
+++ b/drivers/md/bcache/super.c
|
||||
@@ -685,6 +685,8 @@ static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
|
||||
WARN(sysfs_create_link(&d->kobj, &c->kobj, "cache") ||
|
||||
sysfs_create_link(&c->kobj, &d->kobj, d->name),
|
||||
"Couldn't create device <-> cache set symlinks");
|
||||
+
|
||||
+ clear_bit(BCACHE_DEV_UNLINK_DONE, &d->flags);
|
||||
}
|
||||
|
||||
static void bcache_device_detach(struct bcache_device *d)
|
|
@ -1,32 +0,0 @@
|
|||
From: Al Viro <viro@ZenIV.linux.org.uk>
|
||||
Date: Sun, 29 Nov 2015 17:20:59 -0800
|
||||
Subject: [4/8] bcache: fix a leak in bch_cached_dev_run()
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=4d4d8573a8451acc9f01cbea24b7e55f04a252fe
|
||||
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
Tested-by: Joshua Schmid <jschmid@suse.com>
|
||||
Tested-by: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/super.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
|
||||
index 383f060..43e911e 100644
|
||||
--- a/drivers/md/bcache/super.c
|
||||
+++ b/drivers/md/bcache/super.c
|
||||
@@ -849,8 +849,11 @@ void bch_cached_dev_run(struct cached_dev *dc)
|
||||
buf[SB_LABEL_SIZE] = '\0';
|
||||
env[2] = kasprintf(GFP_KERNEL, "CACHED_LABEL=%s", buf);
|
||||
|
||||
- if (atomic_xchg(&dc->running, 1))
|
||||
+ if (atomic_xchg(&dc->running, 1)) {
|
||||
+ kfree(env[1]);
|
||||
+ kfree(env[2]);
|
||||
return;
|
||||
+ }
|
||||
|
||||
if (!d->c &&
|
||||
BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
|
|
@ -1,67 +0,0 @@
|
|||
From: Zheng Liu <gnehzuil.liu@gmail.com>
|
||||
Date: Sun, 29 Nov 2015 17:17:05 -0800
|
||||
Subject: [1/8] bcache: fix a livelock when we cause a huge number of cache
|
||||
misses
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=2ef9ccbfcb90cf84bdba320a571b18b05c41101b
|
||||
|
||||
Subject : [PATCH v2] bcache: fix a livelock in btree lock
|
||||
Date : Wed, 25 Feb 2015 20:32:09 +0800 (02/25/2015 04:32:09 AM)
|
||||
|
||||
This commit tries to fix a livelock in bcache. This livelock might
|
||||
happen when we causes a huge number of cache misses simultaneously.
|
||||
|
||||
When we get a cache miss, bcache will execute the following path.
|
||||
|
||||
->cached_dev_make_request()
|
||||
->cached_dev_read()
|
||||
->cached_lookup()
|
||||
->bch->btree_map_keys()
|
||||
->btree_root() <------------------------
|
||||
->bch_btree_map_keys_recurse() |
|
||||
->cache_lookup_fn() |
|
||||
->cached_dev_cache_miss() |
|
||||
->bch_btree_insert_check_key() -|
|
||||
[If btree->seq is not equal to seq + 1, we should return
|
||||
EINTR and traverse btree again.]
|
||||
|
||||
In bch_btree_insert_check_key() function we first need to check upgrade
|
||||
flag (op->lock == -1), and when this flag is true we need to release
|
||||
read btree->lock and try to take write btree->lock. During taking and
|
||||
releasing this write lock, btree->seq will be monotone increased in
|
||||
order to prevent other threads modify this in cache miss (see btree.h:74).
|
||||
But if there are some cache misses caused by some requested, we could
|
||||
meet a livelock because btree->seq is always changed by others. Thus no
|
||||
one can make progress.
|
||||
|
||||
This commit will try to take write btree->lock if it encounters a race
|
||||
when we traverse btree. Although it sacrifice the scalability but we
|
||||
can ensure that only one can modify the btree.
|
||||
|
||||
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
|
||||
Tested-by: Joshua Schmid <jschmid@suse.com>
|
||||
Tested-by: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Joshua Schmid <jschmid@suse.com>
|
||||
Cc: Zhu Yanhai <zhu.yanhai@gmail.com>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/btree.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
|
||||
index 83392f8..4a1179c 100644
|
||||
--- a/drivers/md/bcache/btree.c
|
||||
+++ b/drivers/md/bcache/btree.c
|
||||
@@ -2162,8 +2162,10 @@ int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
|
||||
rw_lock(true, b, b->level);
|
||||
|
||||
if (b->key.ptr[0] != btree_ptr ||
|
||||
- b->seq != seq + 1)
|
||||
+ b->seq != seq + 1) {
|
||||
+ op->lock = b->level;
|
||||
goto out;
|
||||
+ }
|
||||
}
|
||||
|
||||
SET_KEY_PTRS(check_key, 1);
|
|
@ -1,32 +0,0 @@
|
|||
From: Stefan Bader <stefan.bader@canonical.com>
|
||||
Date: Sun, 29 Nov 2015 18:44:49 -0800
|
||||
Subject: [7/8] bcache: prevent crash on changing writeback_running
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=8d16ce540c94c9d366eb36fc91b7154d92d6397b
|
||||
|
||||
Added a safeguard in the shutdown case. At least while not being
|
||||
attached it is also possible to trigger a kernel bug by writing into
|
||||
writeback_running. This change adds the same check before trying to
|
||||
wake up the thread for that case.
|
||||
|
||||
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
|
||||
Cc: Kent Overstreet <kent.overstreet@gmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/writeback.h | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
|
||||
index 0a9dab1..073a042 100644
|
||||
--- a/drivers/md/bcache/writeback.h
|
||||
+++ b/drivers/md/bcache/writeback.h
|
||||
@@ -63,7 +63,8 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
|
||||
|
||||
static inline void bch_writeback_queue(struct cached_dev *dc)
|
||||
{
|
||||
- wake_up_process(dc->writeback_thread);
|
||||
+ if (!IS_ERR_OR_NULL(dc->writeback_thread))
|
||||
+ wake_up_process(dc->writeback_thread);
|
||||
}
|
||||
|
||||
static inline void bch_writeback_add(struct cached_dev *dc)
|
|
@ -1,35 +0,0 @@
|
|||
From: Zheng Liu <wenqing.lz@taobao.com>
|
||||
Date: Sun, 29 Nov 2015 17:21:57 -0800
|
||||
Subject: [5/8] bcache: unregister reboot notifier if bcache fails to
|
||||
unregister device
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/axboe/linux-block.git/commit?id=2ecf0cdb2b437402110ab57546e02abfa68a716b
|
||||
|
||||
In bcache_init() function it forgot to unregister reboot notifier if
|
||||
bcache fails to unregister a block device. This commit fixes this.
|
||||
|
||||
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
|
||||
Tested-by: Joshua Schmid <jschmid@suse.com>
|
||||
Tested-by: Eric Wheeler <bcache@linux.ewheeler.net>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@fb.com>
|
||||
---
|
||||
drivers/md/bcache/super.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
|
||||
index 43e911e..18f14a2 100644
|
||||
--- a/drivers/md/bcache/super.c
|
||||
+++ b/drivers/md/bcache/super.c
|
||||
@@ -2071,8 +2071,10 @@ static int __init bcache_init(void)
|
||||
closure_debug_init();
|
||||
|
||||
bcache_major = register_blkdev(0, "bcache");
|
||||
- if (bcache_major < 0)
|
||||
+ if (bcache_major < 0) {
|
||||
+ unregister_reboot_notifier(&reboot);
|
||||
return bcache_major;
|
||||
+ }
|
||||
|
||||
if (!(bcache_wq = create_workqueue("bcache")) ||
|
||||
!(bcache_kobj = kobject_create_and_add("bcache", fs_kobj)) ||
|
|
@ -16,7 +16,7 @@ correctness.
|
|||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -591,6 +591,7 @@ static int m88e1118_config_init(struct p
|
||||
@@ -681,6 +681,7 @@ static int m88e1118_config_init(struct p
|
||||
return phy_write(phydev, MII_BMCR, BMCR_RESET);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ correctness.
|
|||
static int m88e1149_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int err;
|
||||
@@ -616,7 +617,9 @@ static int m88e1149_config_init(struct p
|
||||
@@ -706,7 +707,9 @@ static int m88e1149_config_init(struct p
|
||||
|
||||
return phy_write(phydev, MII_BMCR, BMCR_RESET);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ correctness.
|
|||
static int m88e1145_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int err;
|
||||
@@ -682,6 +685,7 @@ static int m88e1145_config_init(struct p
|
||||
@@ -787,6 +790,7 @@ static int m88e1145_config_init(struct p
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,41 +42,41 @@ correctness.
|
|||
|
||||
/* marvell_read_status
|
||||
*
|
||||
@@ -975,6 +979,7 @@ static struct phy_driver marvell_drivers
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
@@ -1180,6 +1184,7 @@ static struct phy_driver marvell_drivers
|
||||
.get_strings = marvell_get_strings,
|
||||
.get_stats = marvell_get_stats,
|
||||
},
|
||||
+#if 0
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1145,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
@@ -990,6 +995,8 @@ static struct phy_driver marvell_drivers
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
@@ -1198,6 +1203,8 @@ static struct phy_driver marvell_drivers
|
||||
.get_strings = marvell_get_strings,
|
||||
.get_stats = marvell_get_stats,
|
||||
},
|
||||
+#endif
|
||||
+#if 0
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1149R,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
@@ -1005,6 +1012,8 @@ static struct phy_driver marvell_drivers
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
@@ -1216,6 +1223,8 @@ static struct phy_driver marvell_drivers
|
||||
.get_strings = marvell_get_strings,
|
||||
.get_stats = marvell_get_stats,
|
||||
},
|
||||
+#endif
|
||||
+#if 0
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1240,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
@@ -1020,6 +1029,7 @@ static struct phy_driver marvell_drivers
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
@@ -1234,6 +1243,7 @@ static struct phy_driver marvell_drivers
|
||||
.get_strings = marvell_get_strings,
|
||||
.get_stats = marvell_get_stats,
|
||||
},
|
||||
+#endif
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1116R,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
@@ -1073,9 +1083,9 @@ static struct mdio_device_id __maybe_unu
|
||||
@@ -1318,9 +1328,9 @@ static struct mdio_device_id __maybe_unu
|
||||
{ MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK },
|
||||
{ MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK },
|
||||
{ MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK },
|
||||
|
|
|
@ -122,7 +122,7 @@ upstream submission.
|
|||
release_firmware(firmware);
|
||||
--- a/drivers/bluetooth/bcm203x.c
|
||||
+++ b/drivers/bluetooth/bcm203x.c
|
||||
@@ -193,7 +193,6 @@ static int bcm203x_probe(struct usb_inte
|
||||
@@ -191,7 +191,6 @@ static int bcm203x_probe(struct usb_inte
|
||||
}
|
||||
|
||||
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
||||
|
@ -130,7 +130,7 @@ upstream submission.
|
|||
usb_free_urb(data->urb);
|
||||
return -EIO;
|
||||
}
|
||||
@@ -218,7 +217,6 @@ static int bcm203x_probe(struct usb_inte
|
||||
@@ -216,7 +215,6 @@ static int bcm203x_probe(struct usb_inte
|
||||
release_firmware(firmware);
|
||||
|
||||
if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) {
|
||||
|
@ -140,7 +140,7 @@ upstream submission.
|
|||
return -EIO;
|
||||
--- a/drivers/bluetooth/bfusb.c
|
||||
+++ b/drivers/bluetooth/bfusb.c
|
||||
@@ -653,10 +653,8 @@ static int bfusb_probe(struct usb_interf
|
||||
@@ -652,10 +652,8 @@ static int bfusb_probe(struct usb_interf
|
||||
skb_queue_head_init(&data->pending_q);
|
||||
skb_queue_head_init(&data->completed_q);
|
||||
|
||||
|
@ -154,7 +154,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/bluetooth/bt3c_cs.c
|
||||
+++ b/drivers/bluetooth/bt3c_cs.c
|
||||
@@ -565,10 +565,8 @@ static int bt3c_open(struct bt3c_info *i
|
||||
@@ -566,10 +566,8 @@ static int bt3c_open(struct bt3c_info *i
|
||||
|
||||
/* Load firmware */
|
||||
err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
|
||||
|
@ -233,7 +233,7 @@ upstream submission.
|
|||
where = 0;
|
||||
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
||||
@@ -1646,10 +1646,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, co
|
||||
@@ -1736,10 +1736,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, co
|
||||
|
||||
snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
|
||||
ret = request_firmware(&fw, f, device->dev);
|
||||
|
@ -300,33 +300,6 @@ upstream submission.
|
|||
release_firmware(rdev->pfp_fw);
|
||||
rdev->pfp_fw = NULL;
|
||||
release_firmware(rdev->me_fw);
|
||||
--- a/drivers/gpu/drm/radeon/r600_cp.c
|
||||
+++ b/drivers/gpu/drm/radeon/r600_cp.c
|
||||
@@ -376,10 +376,6 @@ out:
|
||||
platform_device_unregister(pdev);
|
||||
|
||||
if (err) {
|
||||
- if (err != -EINVAL)
|
||||
- printk(KERN_ERR
|
||||
- "r600_cp: Failed to load firmware \"%s\"\n",
|
||||
- fw_name);
|
||||
release_firmware(dev_priv->pfp_fw);
|
||||
dev_priv->pfp_fw = NULL;
|
||||
release_firmware(dev_priv->me_fw);
|
||||
--- a/drivers/gpu/drm/radeon/radeon_cp.c
|
||||
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
|
||||
@@ -530,10 +530,7 @@ static int radeon_cp_init_microcode(drm_
|
||||
|
||||
err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
- if (err) {
|
||||
- printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
|
||||
- fw_name);
|
||||
- } else if (dev_priv->me_fw->size % 8) {
|
||||
+ if (err == 0 && dev_priv->me_fw->size % 8) {
|
||||
printk(KERN_ERR
|
||||
"radeon_cp: Bogus length %zu in firmware \"%s\"\n",
|
||||
dev_priv->me_fw->size, fw_name);
|
||||
--- a/drivers/infiniband/hw/qib/qib_sd7220.c
|
||||
+++ b/drivers/infiniband/hw/qib/qib_sd7220.c
|
||||
@@ -406,10 +406,8 @@ int qib_sd7220_init(struct qib_devdata *
|
||||
|
@ -343,7 +316,7 @@ upstream submission.
|
|||
ret = qib_ibsd_ucode_loaded(dd->pport, fw);
|
||||
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
@@ -2209,10 +2209,8 @@ static int mxt_load_fw(struct device *de
|
||||
@@ -2193,10 +2193,8 @@ static int mxt_load_fw(struct device *de
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, fn, dev);
|
||||
|
@ -754,7 +727,7 @@ upstream submission.
|
|||
- printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
|
||||
+ if (ret == -ENOENT)
|
||||
+ printk(KERN_ERR "dvb-ttpci: firmware can be downloaded from"
|
||||
" http://www.linuxtv.org/download/dvb/firmware/\n");
|
||||
" https://linuxtv.org/download/dvb/firmware/\n");
|
||||
- } else
|
||||
- printk(KERN_ERR "dvb-ttpci: cannot request firmware"
|
||||
- " (error %i)\n", ret);
|
||||
|
@ -961,7 +934,7 @@ upstream submission.
|
|||
printk(KERN_ERR "ERROR: Firmware size mismatch "
|
||||
--- a/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
@@ -2165,11 +2165,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
@@ -2279,11 +2279,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
cinfo.rev, filename);
|
||||
|
||||
ret = request_firmware(&fw, filename, &dev->pci->dev);
|
||||
|
@ -1216,7 +1189,7 @@ upstream submission.
|
|||
if (bp->mips_firmware->size < sizeof(*mips_fw) ||
|
||||
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
@@ -13401,11 +13401,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
@@ -13398,11 +13398,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
|
||||
|
||||
rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
|
||||
|
@ -1231,7 +1204,7 @@ upstream submission.
|
|||
if (rc) {
|
||||
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||||
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||||
@@ -11335,11 +11335,8 @@ static int tg3_request_firmware(struct t
|
||||
@@ -11346,11 +11346,8 @@ static int tg3_request_firmware(struct t
|
||||
{
|
||||
const struct tg3_firmware_hdr *fw_hdr;
|
||||
|
||||
|
@ -1260,7 +1233,7 @@ upstream submission.
|
|||
*bfi_image_size = fw->size/sizeof(u32);
|
||||
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
|
||||
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
|
||||
@@ -1034,12 +1034,8 @@ int t3_get_edc_fw(struct cphy *phy, int
|
||||
@@ -1036,12 +1036,8 @@ int t3_get_edc_fw(struct cphy *phy, int
|
||||
fw_name = get_edc_fw_name(edc_idx);
|
||||
if (fw_name)
|
||||
ret = request_firmware(&fw, fw_name, &adapter->pdev->dev);
|
||||
|
@ -1274,7 +1247,7 @@ upstream submission.
|
|||
|
||||
/* check size, take checksum in account */
|
||||
if (fw->size > size + 4) {
|
||||
@@ -1076,11 +1072,8 @@ static int upgrade_fw(struct adapter *ad
|
||||
@@ -1078,11 +1074,8 @@ static int upgrade_fw(struct adapter *ad
|
||||
struct device *dev = &adap->pdev->dev;
|
||||
|
||||
ret = request_firmware(&fw, FW_FNAME, dev);
|
||||
|
@ -1287,7 +1260,7 @@ upstream submission.
|
|||
ret = t3_load_fw(adap, fw->data, fw->size);
|
||||
release_firmware(fw);
|
||||
|
||||
@@ -1125,11 +1118,8 @@ static int update_tpsram(struct adapter
|
||||
@@ -1127,11 +1120,8 @@ static int update_tpsram(struct adapter
|
||||
snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
|
||||
|
||||
ret = request_firmware(&tpsram, buf, dev);
|
||||
|
@ -1405,8 +1378,8 @@ upstream submission.
|
|||
kfree(i2400m_fw);
|
||||
i2400m_fw = (void *) ~0;
|
||||
} else
|
||||
--- a/drivers/net/wireless/at76c50x-usb.c
|
||||
+++ b/drivers/net/wireless/at76c50x-usb.c
|
||||
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
|
||||
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
|
||||
@@ -1622,13 +1622,8 @@ static struct fwentry *at76_load_firmwar
|
||||
|
||||
at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
|
||||
|
@ -1444,8 +1417,8 @@ upstream submission.
|
|||
carl9170_usb_firmware_failed(ar);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/atmel.c
|
||||
+++ b/drivers/net/wireless/atmel.c
|
||||
--- a/drivers/net/wireless/atmel/atmel.c
|
||||
+++ b/drivers/net/wireless/atmel/atmel.c
|
||||
@@ -3917,12 +3917,8 @@ static int reset_atmel_card(struct net_d
|
||||
strcpy(priv->firmware_id, "atmel_at76c502.bin");
|
||||
}
|
||||
|
@ -1460,8 +1433,8 @@ upstream submission.
|
|||
} else {
|
||||
int fw_index = 0;
|
||||
int success = 0;
|
||||
--- a/drivers/net/wireless/b43/main.c
|
||||
+++ b/drivers/net/wireless/b43/main.c
|
||||
--- a/drivers/net/wireless/broadcom/b43/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43/main.c
|
||||
@@ -2253,19 +2253,8 @@ int b43_do_request_fw(struct b43_request
|
||||
}
|
||||
err = request_firmware(&ctx->blob, ctx->fwname,
|
||||
|
@ -1483,8 +1456,8 @@ upstream submission.
|
|||
fw_ready:
|
||||
if (ctx->blob->size < sizeof(struct b43_fw_header))
|
||||
goto err_format;
|
||||
--- a/drivers/net/wireless/b43legacy/main.c
|
||||
+++ b/drivers/net/wireless/b43legacy/main.c
|
||||
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
@@ -1554,11 +1554,8 @@ static int do_request_fw(struct b43legac
|
||||
} else {
|
||||
err = request_firmware(fw, path, dev->dev->dev);
|
||||
|
@ -1498,8 +1471,8 @@ upstream submission.
|
|||
if ((*fw)->size < sizeof(struct b43legacy_fw_header))
|
||||
goto err_format;
|
||||
hdr = (struct b43legacy_fw_header *)((*fw)->data);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -378,19 +378,13 @@ static int brcms_request_fw(struct brcms
|
||||
sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
|
||||
UCODE_LOADER_API_VER);
|
||||
|
@ -1522,9 +1495,9 @@ upstream submission.
|
|||
wl->fw.hdr_num_entries[i] =
|
||||
wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
|
||||
}
|
||||
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
@@ -8411,12 +8411,8 @@ static int ipw2100_get_firmware(struct i
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
||||
@@ -8418,12 +8418,8 @@ static int ipw2100_get_firmware(struct i
|
||||
|
||||
rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
|
||||
|
||||
|
@ -1538,8 +1511,8 @@ upstream submission.
|
|||
IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data,
|
||||
fw->fw_entry->size);
|
||||
|
||||
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
|
||||
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
@@ -3418,10 +3418,8 @@ static int ipw_get_fw(struct ipw_priv *p
|
||||
|
||||
/* ask firmware_class module to get the boot firmware off disk */
|
||||
|
@ -1552,8 +1525,8 @@ upstream submission.
|
|||
|
||||
if ((*raw)->size < sizeof(*fw)) {
|
||||
IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size);
|
||||
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
|
||||
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
|
||||
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
|
||||
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
|
||||
@@ -1861,7 +1861,6 @@ il3945_read_ucode(struct il_priv *il)
|
||||
sprintf(buf, "%s%u%s", name_pre, idx, ".ucode");
|
||||
ret = request_firmware(&ucode_raw, buf, &il->pci_dev->dev);
|
||||
|
@ -1562,9 +1535,9 @@ upstream submission.
|
|||
if (ret == -ENOENT)
|
||||
continue;
|
||||
else
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
@@ -1201,13 +1201,8 @@ static void iwl_req_fw_callback(const st
|
||||
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
|
||||
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
|
||||
@@ -1206,13 +1206,8 @@ static void iwl_req_fw_callback(const st
|
||||
if (!pieces)
|
||||
return;
|
||||
|
||||
|
@ -1579,8 +1552,8 @@ upstream submission.
|
|||
|
||||
IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
|
||||
drv->firmware_name, ucode_raw->size);
|
||||
--- a/drivers/net/wireless/libertas_tf/if_usb.c
|
||||
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
|
||||
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
|
||||
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
|
||||
@@ -824,8 +824,6 @@ static int if_usb_prog_firmware(struct i
|
||||
kernel_param_lock(THIS_MODULE);
|
||||
ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
|
||||
|
@ -1590,8 +1563,8 @@ upstream submission.
|
|||
kernel_param_unlock(THIS_MODULE);
|
||||
goto done;
|
||||
}
|
||||
--- a/drivers/net/wireless/mwifiex/main.c
|
||||
+++ b/drivers/net/wireless/mwifiex/main.c
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/main.c
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
|
||||
@@ -508,11 +508,8 @@ static void mwifiex_fw_dpc(const struct
|
||||
bool init_failed = false;
|
||||
struct wireless_dev *wdev;
|
||||
|
@ -1605,8 +1578,8 @@ upstream submission.
|
|||
|
||||
memset(&fw, 0, sizeof(struct mwifiex_fw_image));
|
||||
adapter->firmware = firmware;
|
||||
--- a/drivers/net/wireless/mwl8k.c
|
||||
+++ b/drivers/net/wireless/mwl8k.c
|
||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||
+++ b/drivers/net/wireless/marvell/mwl8k.c
|
||||
@@ -5712,16 +5712,12 @@ static int mwl8k_firmware_load_success(s
|
||||
static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
|
||||
{
|
||||
|
@ -1650,8 +1623,8 @@ upstream submission.
|
|||
|
||||
if (nowait)
|
||||
return rc;
|
||||
--- a/drivers/net/wireless/orinoco/fw.c
|
||||
+++ b/drivers/net/wireless/orinoco/fw.c
|
||||
--- a/drivers/net/wireless/intersil/orinoco/fw.c
|
||||
+++ b/drivers/net/wireless/intersil/orinoco/fw.c
|
||||
@@ -132,7 +132,6 @@ orinoco_dl_firmware(struct orinoco_priva
|
||||
err = request_firmware(&fw_entry, firmware, priv->dev);
|
||||
|
||||
|
@ -1684,8 +1657,8 @@ upstream submission.
|
|||
} else
|
||||
fw_entry = orinoco_cached_fw_get(priv, false);
|
||||
|
||||
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
|
||||
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
|
||||
@@ -1669,7 +1669,6 @@ static int ezusb_probe(struct usb_interf
|
||||
if (ezusb_firmware_download(upriv, &firmware) < 0)
|
||||
goto error;
|
||||
|
@ -1694,8 +1667,8 @@ upstream submission.
|
|||
goto error;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/p54/p54pci.c
|
||||
+++ b/drivers/net/wireless/p54/p54pci.c
|
||||
--- a/drivers/net/wireless/intersil/p54/p54pci.c
|
||||
+++ b/drivers/net/wireless/intersil/p54/p54pci.c
|
||||
@@ -499,7 +499,6 @@ static void p54p_firmware_step2(const st
|
||||
int err;
|
||||
|
||||
|
@ -1704,8 +1677,8 @@ upstream submission.
|
|||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
--- a/drivers/net/wireless/p54/p54spi.c
|
||||
+++ b/drivers/net/wireless/p54/p54spi.c
|
||||
--- a/drivers/net/wireless/intersil/p54/p54spi.c
|
||||
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
|
||||
@@ -170,10 +170,8 @@ static int p54spi_request_firmware(struc
|
||||
/* FIXME: should driver use it's own struct device? */
|
||||
ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev);
|
||||
|
@ -1718,8 +1691,8 @@ upstream submission.
|
|||
|
||||
ret = p54_parse_firmware(dev, priv->firmware);
|
||||
if (ret) {
|
||||
--- a/drivers/net/wireless/p54/p54usb.c
|
||||
+++ b/drivers/net/wireless/p54/p54usb.c
|
||||
--- a/drivers/net/wireless/intersil/p54/p54usb.c
|
||||
+++ b/drivers/net/wireless/intersil/p54/p54usb.c
|
||||
@@ -929,7 +929,6 @@ static void p54u_load_firmware_cb(const
|
||||
err = p54u_start_ops(priv);
|
||||
} else {
|
||||
|
@ -1728,8 +1701,8 @@ upstream submission.
|
|||
}
|
||||
|
||||
if (err) {
|
||||
--- a/drivers/net/wireless/prism54/islpci_dev.c
|
||||
+++ b/drivers/net/wireless/prism54/islpci_dev.c
|
||||
--- a/drivers/net/wireless/intersil/prism54/islpci_dev.c
|
||||
+++ b/drivers/net/wireless/intersil/prism54/islpci_dev.c
|
||||
@@ -92,12 +92,9 @@ isl_upload_firmware(islpci_private *priv
|
||||
const u32 *fw_ptr;
|
||||
|
||||
|
@ -1745,8 +1718,8 @@ upstream submission.
|
|||
/* prepare the Direct Memory Base register */
|
||||
reg = ISL38XX_DEV_FIRMWARE_ADDRES;
|
||||
|
||||
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
|
||||
@@ -49,10 +49,8 @@ static int rt2x00lib_request_firmware(st
|
||||
rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
|
||||
|
||||
|
@ -1807,7 +1780,7 @@ upstream submission.
|
|||
wl1251_error("nvs size is not multiple of 32 bits: %zu",
|
||||
--- a/drivers/net/wireless/ti/wlcore/main.c
|
||||
+++ b/drivers/net/wireless/ti/wlcore/main.c
|
||||
@@ -762,10 +762,8 @@ static int wl12xx_fetch_firmware(struct
|
||||
@@ -747,10 +747,8 @@ static int wl12xx_fetch_firmware(struct
|
||||
|
||||
ret = request_firmware(&fw, fw_name, wl->dev);
|
||||
|
||||
|
@ -1819,8 +1792,8 @@ upstream submission.
|
|||
|
||||
if (fw->size % 4) {
|
||||
wl1271_error("firmware size is not multiple of 32 bits: %zu",
|
||||
--- a/drivers/net/wireless/zd1201.c
|
||||
+++ b/drivers/net/wireless/zd1201.c
|
||||
--- a/drivers/net/wireless/zydas/zd1201.c
|
||||
+++ b/drivers/net/wireless/zydas/zd1201.c
|
||||
@@ -65,8 +65,6 @@ static int zd1201_fw_upload(struct usb_d
|
||||
|
||||
err = request_firmware(&fw_entry, fwfile, &dev->dev);
|
||||
|
@ -1830,8 +1803,8 @@ upstream submission.
|
|||
dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
|
||||
return err;
|
||||
}
|
||||
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
|
||||
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
|
||||
--- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
|
||||
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
|
||||
@@ -120,16 +120,9 @@ static void int_urb_complete(struct urb
|
||||
static int request_fw_file(
|
||||
const struct firmware **fw, const char *name, struct device *device)
|
||||
|
@ -1916,7 +1889,7 @@ upstream submission.
|
|||
if (err) {
|
||||
--- a/drivers/scsi/bfa/bfad.c
|
||||
+++ b/drivers/scsi/bfa/bfad.c
|
||||
@@ -1762,7 +1762,6 @@ bfad_read_firmware(struct pci_dev *pdev,
|
||||
@@ -1758,7 +1758,6 @@ bfad_read_firmware(struct pci_dev *pdev,
|
||||
const struct firmware *fw;
|
||||
|
||||
if (request_firmware(&fw, fw_name, &pdev->dev)) {
|
||||
|
@ -1926,9 +1899,9 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/scsi/ipr.c
|
||||
+++ b/drivers/scsi/ipr.c
|
||||
@@ -4011,10 +4011,8 @@ static ssize_t ipr_store_update_fw(struc
|
||||
len = snprintf(fname, 99, "%s", buf);
|
||||
fname[len-1] = '\0';
|
||||
@@ -4009,10 +4009,8 @@ static ssize_t ipr_store_update_fw(struc
|
||||
|
||||
snprintf(fname, sizeof(fname), "%s", buf);
|
||||
|
||||
- if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) {
|
||||
- dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname);
|
||||
|
@ -1964,7 +1937,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/scsi/qla2xxx/qla_init.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_init.c
|
||||
@@ -5520,8 +5520,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
@@ -5540,8 +5540,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -1973,7 +1946,7 @@ upstream submission.
|
|||
ql_log(ql_log_info, vha, 0x0084,
|
||||
"Firmware images can be retrieved from: "QLA_FW_URL ".\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
@@ -5623,8 +5621,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
@@ -5643,8 +5641,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -1999,7 +1972,7 @@ upstream submission.
|
|||
if (qla82xx_validate_firmware_blob(vha,
|
||||
--- a/drivers/scsi/qla2xxx/qla_os.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
||||
@@ -5364,8 +5364,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
@@ -5529,8 +5529,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
goto out;
|
||||
|
||||
if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
|
||||
|
@ -2148,7 +2121,7 @@ upstream submission.
|
|||
for (i = 0; i < numsects; i++) {
|
||||
--- a/drivers/staging/vt6656/firmware.c
|
||||
+++ b/drivers/staging/vt6656/firmware.c
|
||||
@@ -53,11 +53,8 @@ int vnt_download_firmware(struct vnt_pri
|
||||
@@ -49,11 +49,8 @@ int vnt_download_firmware(struct vnt_pri
|
||||
dev_dbg(dev, "---->Download firmware\n");
|
||||
|
||||
rc = request_firmware(&fw, FIRMWARE_NAME, dev);
|
||||
|
@ -2178,7 +2151,7 @@ upstream submission.
|
|||
positive, skip this board */
|
||||
--- a/drivers/tty/moxa.c
|
||||
+++ b/drivers/tty/moxa.c
|
||||
@@ -867,13 +867,8 @@ static int moxa_init_board(struct moxa_b
|
||||
@@ -866,13 +866,8 @@ static int moxa_init_board(struct moxa_b
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, file, dev);
|
||||
|
@ -2195,7 +2168,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/tty/serial/icom.c
|
||||
+++ b/drivers/tty/serial/icom.c
|
||||
@@ -375,7 +375,6 @@ static void load_code(struct icom_port *
|
||||
@@ -374,7 +374,6 @@ static void load_code(struct icom_port *
|
||||
|
||||
/* Load Call Setup into Adapter */
|
||||
if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
|
||||
|
@ -2203,7 +2176,7 @@ upstream submission.
|
|||
status = -1;
|
||||
goto load_code_exit;
|
||||
}
|
||||
@@ -395,7 +394,6 @@ static void load_code(struct icom_port *
|
||||
@@ -394,7 +393,6 @@ static void load_code(struct icom_port *
|
||||
|
||||
/* Load Resident DCE portion of Adapter */
|
||||
if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
|
||||
|
@ -2211,7 +2184,7 @@ upstream submission.
|
|||
status = -1;
|
||||
goto load_code_exit;
|
||||
}
|
||||
@@ -440,7 +438,6 @@ static void load_code(struct icom_port *
|
||||
@@ -439,7 +437,6 @@ static void load_code(struct icom_port *
|
||||
}
|
||||
|
||||
if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
|
||||
|
@ -2560,7 +2533,7 @@ upstream submission.
|
|||
filename, emu->firmware->size);
|
||||
--- a/sound/pci/hda/hda_intel.c
|
||||
+++ b/sound/pci/hda/hda_intel.c
|
||||
@@ -1738,10 +1738,8 @@ static void azx_firmware_cb(const struct
|
||||
@@ -1831,10 +1831,8 @@ static void azx_firmware_cb(const struct
|
||||
struct azx *chip = card->private_data;
|
||||
struct pci_dev *pci = chip->pci;
|
||||
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
From: Vladis Dronov <vdronov@redhat.com>
|
||||
Date: Mon, 16 Nov 2015 15:55:11 -0200
|
||||
Subject: [media] usbvision: fix crash on detecting device with invalid
|
||||
configuration
|
||||
Origin: http://git.linuxtv.org/cgit.cgi/media_tree.git/commit?id=fa52bd506f274b7619955917abfde355e3d19ffe
|
||||
|
||||
The usbvision driver crashes when a specially crafted usb device with invalid
|
||||
number of interfaces or endpoints is detected. This fix adds checks that the
|
||||
device has proper configuration expected by the driver.
|
||||
|
||||
Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
|
||||
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
---
|
||||
drivers/media/usb/usbvision/usbvision-video.c | 16 +++++++++++++++-
|
||||
1 file changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/usb/usbvision/usbvision-video.c
|
||||
+++ b/drivers/media/usb/usbvision/usbvision-video.c
|
||||
@@ -1542,9 +1542,23 @@ static int usbvision_probe(struct usb_in
|
||||
|
||||
if (usbvision_device_data[model].interface >= 0)
|
||||
interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
|
||||
- else
|
||||
+ else if (ifnum < dev->actconfig->desc.bNumInterfaces)
|
||||
interface = &dev->actconfig->interface[ifnum]->altsetting[0];
|
||||
+ else {
|
||||
+ dev_err(&intf->dev, "interface %d is invalid, max is %d\n",
|
||||
+ ifnum, dev->actconfig->desc.bNumInterfaces - 1);
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_usb;
|
||||
+ }
|
||||
+
|
||||
+ if (interface->desc.bNumEndpoints < 2) {
|
||||
+ dev_err(&intf->dev, "interface %d has %d endpoints, but must"
|
||||
+ " have minimum 2\n", ifnum, interface->desc.bNumEndpoints);
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_usb;
|
||||
+ }
|
||||
endpoint = &interface->endpoint[1].desc;
|
||||
+
|
||||
if (!usb_endpoint_xfer_isoc(endpoint)) {
|
||||
dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
|
||||
__func__, ifnum);
|
|
@ -1,237 +0,0 @@
|
|||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Mon, 18 Jan 2016 16:36:09 +0100
|
||||
Subject: pipe: limit the per-user amount of pages allocated in pipes
|
||||
Origin: https://git.kernel.org/linus/759c01142a5d0f364a462346168a56de28a80f52
|
||||
|
||||
On no-so-small systems, it is possible for a single process to cause an
|
||||
OOM condition by filling large pipes with data that are never read. A
|
||||
typical process filling 4000 pipes with 1 MB of data will use 4 GB of
|
||||
memory. On small systems it may be tricky to set the pipe max size to
|
||||
prevent this from happening.
|
||||
|
||||
This patch makes it possible to enforce a per-user soft limit above
|
||||
which new pipes will be limited to a single page, effectively limiting
|
||||
them to 4 kB each, as well as a hard limit above which no new pipes may
|
||||
be created for this user. This has the effect of protecting the system
|
||||
against memory abuse without hurting other users, and still allowing
|
||||
pipes to work correctly though with less data at once.
|
||||
|
||||
The limit are controlled by two new sysctls : pipe-user-pages-soft, and
|
||||
pipe-user-pages-hard. Both may be disabled by setting them to zero. The
|
||||
default soft limit allows the default number of FDs per process (1024)
|
||||
to create pipes of the default size (64kB), thus reaching a limit of 64MB
|
||||
before starting to create only smaller pipes. With 256 processes limited
|
||||
to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB =
|
||||
1084 MB of memory allocated for a user. The hard limit is disabled by
|
||||
default to avoid breaking existing applications that make intensive use
|
||||
of pipes (eg: for splicing).
|
||||
|
||||
Reported-by: socketpair@gmail.com
|
||||
Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
|
||||
Mitigates: CVE-2013-4312 (Linux 2.0+)
|
||||
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
Documentation/sysctl/fs.txt | 23 ++++++++++++++++++++++
|
||||
fs/pipe.c | 47 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
include/linux/pipe_fs_i.h | 4 ++++
|
||||
include/linux/sched.h | 1 +
|
||||
kernel/sysctl.c | 14 ++++++++++++++
|
||||
5 files changed, 87 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Documentation/sysctl/fs.txt
|
||||
+++ b/Documentation/sysctl/fs.txt
|
||||
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/
|
||||
- nr_open
|
||||
- overflowuid
|
||||
- overflowgid
|
||||
+- pipe-user-pages-hard
|
||||
+- pipe-user-pages-soft
|
||||
- protected_hardlinks
|
||||
- protected_symlinks
|
||||
- suid_dumpable
|
||||
@@ -159,6 +161,27 @@ The default is 65534.
|
||||
|
||||
==============================================================
|
||||
|
||||
+pipe-user-pages-hard:
|
||||
+
|
||||
+Maximum total number of pages a non-privileged user may allocate for pipes.
|
||||
+Once this limit is reached, no new pipes may be allocated until usage goes
|
||||
+below the limit again. When set to 0, no limit is applied, which is the default
|
||||
+setting.
|
||||
+
|
||||
+==============================================================
|
||||
+
|
||||
+pipe-user-pages-soft:
|
||||
+
|
||||
+Maximum total number of pages a non-privileged user may allocate for pipes
|
||||
+before the pipe size gets limited to a single page. Once this limit is reached,
|
||||
+new pipes will be limited to a single page in size for this user in order to
|
||||
+limit total memory usage, and trying to increase them using fcntl() will be
|
||||
+denied until usage goes below the limit again. The default value allows to
|
||||
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
|
||||
+applied.
|
||||
+
|
||||
+==============================================================
|
||||
+
|
||||
protected_hardlinks:
|
||||
|
||||
A long-standing class of security issues is the hardlink-based
|
||||
--- a/fs/pipe.c
|
||||
+++ b/fs/pipe.c
|
||||
@@ -38,6 +38,12 @@ unsigned int pipe_max_size = 1048576;
|
||||
*/
|
||||
unsigned int pipe_min_size = PAGE_SIZE;
|
||||
|
||||
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
|
||||
+ * matches default values.
|
||||
+ */
|
||||
+unsigned long pipe_user_pages_hard;
|
||||
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
|
||||
+
|
||||
/*
|
||||
* We use a start+len construction, which provides full use of the
|
||||
* allocated memory.
|
||||
@@ -584,20 +590,49 @@ pipe_fasync(int fd, struct file *filp, i
|
||||
return retval;
|
||||
}
|
||||
|
||||
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
|
||||
+ unsigned long old, unsigned long new)
|
||||
+{
|
||||
+ atomic_long_add(new - old, &pipe->user->pipe_bufs);
|
||||
+}
|
||||
+
|
||||
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
|
||||
+{
|
||||
+ return pipe_user_pages_soft &&
|
||||
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
|
||||
+}
|
||||
+
|
||||
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
|
||||
+{
|
||||
+ return pipe_user_pages_hard &&
|
||||
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
|
||||
+}
|
||||
+
|
||||
struct pipe_inode_info *alloc_pipe_info(void)
|
||||
{
|
||||
struct pipe_inode_info *pipe;
|
||||
|
||||
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
|
||||
if (pipe) {
|
||||
- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
|
||||
+ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
|
||||
+ struct user_struct *user = get_current_user();
|
||||
+
|
||||
+ if (!too_many_pipe_buffers_hard(user)) {
|
||||
+ if (too_many_pipe_buffers_soft(user))
|
||||
+ pipe_bufs = 1;
|
||||
+ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
|
||||
+ }
|
||||
+
|
||||
if (pipe->bufs) {
|
||||
init_waitqueue_head(&pipe->wait);
|
||||
pipe->r_counter = pipe->w_counter = 1;
|
||||
- pipe->buffers = PIPE_DEF_BUFFERS;
|
||||
+ pipe->buffers = pipe_bufs;
|
||||
+ pipe->user = user;
|
||||
+ account_pipe_buffers(pipe, 0, pipe_bufs);
|
||||
mutex_init(&pipe->mutex);
|
||||
return pipe;
|
||||
}
|
||||
+ free_uid(user);
|
||||
kfree(pipe);
|
||||
}
|
||||
|
||||
@@ -608,6 +643,8 @@ void free_pipe_info(struct pipe_inode_in
|
||||
{
|
||||
int i;
|
||||
|
||||
+ account_pipe_buffers(pipe, pipe->buffers, 0);
|
||||
+ free_uid(pipe->user);
|
||||
for (i = 0; i < pipe->buffers; i++) {
|
||||
struct pipe_buffer *buf = pipe->bufs + i;
|
||||
if (buf->ops)
|
||||
@@ -996,6 +1033,7 @@ static long pipe_set_size(struct pipe_in
|
||||
memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
|
||||
}
|
||||
|
||||
+ account_pipe_buffers(pipe, pipe->buffers, nr_pages);
|
||||
pipe->curbuf = 0;
|
||||
kfree(pipe->bufs);
|
||||
pipe->bufs = bufs;
|
||||
@@ -1067,6 +1105,11 @@ long pipe_fcntl(struct file *file, unsig
|
||||
if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
+ } else if ((too_many_pipe_buffers_hard(pipe->user) ||
|
||||
+ too_many_pipe_buffers_soft(pipe->user)) &&
|
||||
+ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
|
||||
+ ret = -EPERM;
|
||||
+ goto out;
|
||||
}
|
||||
ret = pipe_set_size(pipe, nr_pages);
|
||||
break;
|
||||
--- a/include/linux/pipe_fs_i.h
|
||||
+++ b/include/linux/pipe_fs_i.h
|
||||
@@ -42,6 +42,7 @@ struct pipe_buffer {
|
||||
* @fasync_readers: reader side fasync
|
||||
* @fasync_writers: writer side fasync
|
||||
* @bufs: the circular array of pipe buffers
|
||||
+ * @user: the user who created this pipe
|
||||
**/
|
||||
struct pipe_inode_info {
|
||||
struct mutex mutex;
|
||||
@@ -57,6 +58,7 @@ struct pipe_inode_info {
|
||||
struct fasync_struct *fasync_readers;
|
||||
struct fasync_struct *fasync_writers;
|
||||
struct pipe_buffer *bufs;
|
||||
+ struct user_struct *user;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info
|
||||
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
|
||||
|
||||
extern unsigned int pipe_max_size, pipe_min_size;
|
||||
+extern unsigned long pipe_user_pages_hard;
|
||||
+extern unsigned long pipe_user_pages_soft;
|
||||
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
|
||||
|
||||
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -831,6 +831,7 @@ struct user_struct {
|
||||
#endif
|
||||
unsigned long locked_shm; /* How many pages of mlocked shm ? */
|
||||
unsigned long unix_inflight; /* How many files in flight in unix sockets */
|
||||
+ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
|
||||
|
||||
#ifdef CONFIG_KEYS
|
||||
struct key *uid_keyring; /* UID specific keyring */
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -1714,6 +1714,20 @@ static struct ctl_table fs_table[] = {
|
||||
.proc_handler = &pipe_proc_fn,
|
||||
.extra1 = &pipe_min_size,
|
||||
},
|
||||
+ {
|
||||
+ .procname = "pipe-user-pages-hard",
|
||||
+ .data = &pipe_user_pages_hard,
|
||||
+ .maxlen = sizeof(pipe_user_pages_hard),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_doulongvec_minmax,
|
||||
+ },
|
||||
+ {
|
||||
+ .procname = "pipe-user-pages-soft",
|
||||
+ .data = &pipe_user_pages_soft,
|
||||
+ .maxlen = sizeof(pipe_user_pages_soft),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_doulongvec_minmax,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
|
@ -34,8 +34,6 @@ Signed-off-by: Jann Horn <jann@thejh.net>
|
|||
kernel/ptrace.c | 33 ++++++++++++++++++++++++++++-----
|
||||
1 file changed, 28 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
|
||||
index b760bae..260a08d 100644
|
||||
--- a/kernel/ptrace.c
|
||||
+++ b/kernel/ptrace.c
|
||||
@@ -20,6 +20,7 @@
|
||||
|
@ -46,7 +44,7 @@ index b760bae..260a08d 100644
|
|||
#include <linux/syscalls.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/regset.h>
|
||||
@@ -207,12 +208,34 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
|
||||
@@ -207,12 +208,34 @@ static int ptrace_check_attach(struct ta
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -84,16 +82,16 @@ index b760bae..260a08d 100644
|
|||
}
|
||||
|
||||
/* Returns 0 on success, -errno on denial. */
|
||||
@@ -241,7 +264,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
||||
gid_eq(cred->gid, tcred->sgid) &&
|
||||
gid_eq(cred->gid, tcred->gid))
|
||||
@@ -264,7 +287,7 @@ static int __ptrace_may_access(struct ta
|
||||
gid_eq(caller_gid, tcred->sgid) &&
|
||||
gid_eq(caller_gid, tcred->gid))
|
||||
goto ok;
|
||||
- if (ptrace_has_cap(tcred->user_ns, mode))
|
||||
+ if (ptrace_has_cap(tcred, mode))
|
||||
goto ok;
|
||||
rcu_read_unlock();
|
||||
return -EPERM;
|
||||
@@ -252,7 +275,7 @@ ok:
|
||||
@@ -275,7 +298,7 @@ ok:
|
||||
dumpable = get_dumpable(task->mm);
|
||||
rcu_read_lock();
|
||||
if (dumpable != SUID_DUMP_USER &&
|
||||
|
|
|
@ -18,12 +18,10 @@ firmware for the memory controller and other sub-blocks.
|
|||
radeon attempts to gracefully fall back and disable some features if
|
||||
the firmware is not available, but becomes unstable - the framebuffer
|
||||
and/or system memory may be corrupted, or the display may stay black.
|
||||
This does not seem to happen if KMS is disabled, but with both KMS
|
||||
and GPU acceleration disabled radeon is not doing anything useful!
|
||||
|
||||
Therefore, perform a basic check for the existence of
|
||||
/lib/firmware/radeon when a device is probed, and abort if it is
|
||||
missing, except for the pre-R600 KMS case.
|
||||
missing, except for the pre-R600 case.
|
||||
|
||||
---
|
||||
--- a/drivers/gpu/drm/radeon/radeon_drv.c
|
||||
|
@ -37,7 +35,7 @@ missing, except for the pre-R600 KMS case.
|
|||
|
||||
/*
|
||||
* KMS wrapper.
|
||||
@@ -362,6 +365,42 @@ static struct drm_driver driver_old = {
|
||||
@@ -293,6 +295,29 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
|
||||
|
||||
static struct drm_driver kms_driver;
|
||||
|
||||
|
@ -63,24 +61,11 @@ missing, except for the pre-R600 KMS case.
|
|||
+ return false;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_DRM_RADEON_UMS
|
||||
+static int
|
||||
+radeon_ums_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
+{
|
||||
+ if (!radeon_firmware_installed()) {
|
||||
+ DRM_ERROR("radeon DRM requires firmware-linux-nonfree.\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
|
||||
{
|
||||
struct apertures_struct *ap;
|
||||
@@ -388,6 +427,12 @@ static int radeon_pci_probe(struct pci_d
|
||||
@@ -319,6 +344,12 @@ static int radeon_pci_probe(struct pci_d
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -93,11 +78,3 @@ missing, except for the pre-R600 KMS case.
|
|||
/* Get rid of things like offb */
|
||||
ret = radeon_kick_out_firmware_fb(pdev);
|
||||
if (ret)
|
||||
@@ -610,6 +655,7 @@ static struct pci_driver *pdriver;
|
||||
static struct pci_driver radeon_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
+ .probe = radeon_ums_pci_probe,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
From: Ben Hutchings <ben@decadent.org.uk>
|
||||
Date: Sat, 02 Jan 2016 03:03:27 +0000
|
||||
Subject: Revert "xhci: don't finish a TD if we get a short transfer event mid TD"
|
||||
Bug-Debian: https://bugs.debian.org/808602
|
||||
Bug-Debian: https://bugs.debian.org/808953
|
||||
|
||||
This reverts commit e210c422b6fdd2dc123bedc588f399aefd8bf9de. It
|
||||
caused serious regressions as referenced above.
|
||||
|
||||
---
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -2192,10 +2192,6 @@ static int process_bulk_intr_td(struct x
|
||||
}
|
||||
/* Fast path - was this the last TRB in the TD for this URB? */
|
||||
} else if (event_trb == td->last_trb) {
|
||||
- if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
|
||||
- return finish_td(xhci, td, event_trb, event, ep,
|
||||
- status, false);
|
||||
-
|
||||
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
@@ -2247,12 +2243,6 @@ static int process_bulk_intr_td(struct x
|
||||
td->urb->actual_length +=
|
||||
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
-
|
||||
- if (trb_comp_code == COMP_SHORT_TX) {
|
||||
- xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
|
||||
- td->urb_length_set = true;
|
||||
- return 0;
|
||||
- }
|
||||
}
|
||||
|
||||
return finish_td(xhci, td, event_trb, event, ep, status, false);
|
|
@ -1,149 +0,0 @@
|
|||
From: Eli Cooper <elicooper@gmx.com>
|
||||
Date: Mon, 18 Jan 2016 19:30:19 +0800
|
||||
Subject: rt2x00: fix monitor mode regression
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/wireless/wireless-testing.git/commit?id=262c741e0825b29447a9e53b6582afd6b14c3706
|
||||
|
||||
Since commit df1404650ccb ("mac80211: remove support for IFF_PROMISC")
|
||||
monitor mode for rt2x00 has been made effectively useless because the
|
||||
hardware filter is configured to drop packets whose intended recipient is
|
||||
not the device, regardless of the presence of monitor mode interfaces.
|
||||
|
||||
This patch fixes this regression by adding explicit monitor mode support,
|
||||
and by configuring the hardware filter accordingly.
|
||||
|
||||
Signed-off-by: Eli Cooper <elicooper@gmx.com>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
[bwh: Backported to 4.3: adjust filenames]
|
||||
---
|
||||
drivers/net/wireless/rt2x00/rt2400pci.c | 4 +++-
|
||||
drivers/net/wireless/rt2x00/rt2500pci.c | 4 +++-
|
||||
drivers/net/wireless/rt2x00/rt2500usb.c | 4 +++-
|
||||
drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
|
||||
drivers/net/wireless/rt2x00/rt2x00.h | 1 +
|
||||
drivers/net/wireless/rt2x00/rt2x00config.c | 5 +++++
|
||||
drivers/net/wireless/rt2x00/rt2x00mac.c | 5 -----
|
||||
drivers/net/wireless/rt2x00/rt61pci.c | 4 +++-
|
||||
drivers/net/wireless/rt2x00/rt73usb.c | 4 +++-
|
||||
9 files changed, 23 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
|
||||
@@ -273,8 +273,10 @@ static void rt2400pci_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
|
||||
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
|
||||
@@ -274,8 +274,10 @@ static void rt2500pci_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_MCAST,
|
||||
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
|
||||
@@ -434,8 +434,10 @@ static void rt2500usb_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
|
||||
@@ -1490,7 +1490,8 @@ void rt2800_config_filter(struct rt2x00_
|
||||
!(filter_flags & FIF_FCSFAIL));
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR,
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
- rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1);
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
|
||||
@@ -669,6 +669,7 @@ enum rt2x00_state_flags {
|
||||
CONFIG_POWERSAVING,
|
||||
CONFIG_HT_DISABLED,
|
||||
CONFIG_QOS_DISABLED,
|
||||
+ CONFIG_MONITORING,
|
||||
|
||||
/*
|
||||
* Mark we currently are sequentially reading TX_STA_FIFO register
|
||||
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
|
||||
@@ -277,6 +277,11 @@ void rt2x00lib_config(struct rt2x00_dev
|
||||
else
|
||||
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
|
||||
|
||||
+ if (conf->flags & IEEE80211_CONF_MONITOR)
|
||||
+ set_bit(CONFIG_MONITORING, &rt2x00dev->flags);
|
||||
+ else
|
||||
+ clear_bit(CONFIG_MONITORING, &rt2x00dev->flags);
|
||||
+
|
||||
rt2x00dev->curr_band = conf->chandef.chan->band;
|
||||
rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
|
||||
rt2x00dev->tx_power = conf->power_level;
|
||||
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
|
||||
@@ -385,11 +385,6 @@ void rt2x00mac_configure_filter(struct i
|
||||
*total_flags |= FIF_PSPOLL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Check if there is any work left for us.
|
||||
- */
|
||||
- if (rt2x00dev->packet_filter == *total_flags)
|
||||
- return;
|
||||
rt2x00dev->packet_filter = *total_flags;
|
||||
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
|
||||
--- a/drivers/net/wireless/rt2x00/rt61pci.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
|
||||
@@ -530,8 +530,10 @@ static void rt61pci_config_filter(struct
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
|
||||
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
|
||||
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/rt2x00/rt73usb.c
|
||||
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
|
||||
@@ -480,8 +480,10 @@ static void rt73usb_config_filter(struct
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
|
||||
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
|
||||
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
|
||||
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
|
|
@ -1,82 +0,0 @@
|
|||
From: Alan Stern <stern@rowland.harvard.edu>
|
||||
Subject: SCSI: fix crashes in sd and sr runtime PM
|
||||
Date: Wed, 20 Jan 2016 11:26:01 -0500 (EST)
|
||||
Origin: http://article.gmane.org/gmane.linux.scsi/109795
|
||||
Bug-Debian: https://bugs.debian.org/801925
|
||||
|
||||
Runtime suspend during driver probe and removal can cause problems.
|
||||
The driver's runtime_suspend or runtime_resume callbacks may invoked
|
||||
before the driver has finished binding to the device or after the
|
||||
driver has unbound from the device.
|
||||
|
||||
This problem shows up with the sd and sr drivers, and can cause disk
|
||||
or CD/DVD drives to become unusable as a result. The fix is simple.
|
||||
The drivers store a pointer to the scsi_disk or scsi_cd structure as
|
||||
their private device data when probing is finished, so we simply have
|
||||
to be sure to clear the private data during removal and test it during
|
||||
runtime suspend/resume.
|
||||
|
||||
This fixes <https://bugs.debian.org/801925>.
|
||||
|
||||
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Reported-by: Paul Menzel <paul.menzel@giantmonkey.de>
|
||||
Reported-by: Erich Schubert <erich@debian.org>
|
||||
Reported-by: Alexandre Rossi <alexandre.rossi@gmail.com>
|
||||
Tested-by: Paul Menzel <paul.menzel@giantmonkey.de>
|
||||
CC: "James E.J. Bottomley" <JBottomley@odin.com>
|
||||
CC: Ben Hutchings <ben@decadent.org.uk>
|
||||
CC: <stable@vger.kernel.org>
|
||||
|
||||
---
|
||||
|
||||
|
||||
[as1795]
|
||||
|
||||
|
||||
drivers/scsi/sd.c | 7 +++++--
|
||||
drivers/scsi/sr.c | 4 ++++
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/scsi/sd.c
|
||||
+++ b/drivers/scsi/sd.c
|
||||
@@ -3142,8 +3142,8 @@ static int sd_suspend_common(struct devi
|
||||
struct scsi_disk *sdkp = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
- if (!sdkp)
|
||||
- return 0; /* this can happen */
|
||||
+ if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
|
||||
+ return 0;
|
||||
|
||||
if (sdkp->WCE && sdkp->media_present) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
|
||||
@@ -3182,6 +3182,9 @@ static int sd_resume(struct device *dev)
|
||||
{
|
||||
struct scsi_disk *sdkp = dev_get_drvdata(dev);
|
||||
|
||||
+ if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
|
||||
+ return 0;
|
||||
+
|
||||
if (!sdkp->device->manage_start_stop)
|
||||
return 0;
|
||||
|
||||
--- a/drivers/scsi/sr.c
|
||||
+++ b/drivers/scsi/sr.c
|
||||
@@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct dev
|
||||
{
|
||||
struct scsi_cd *cd = dev_get_drvdata(dev);
|
||||
|
||||
+ if (!cd) /* E.g.: runtime suspend following sr_remove() */
|
||||
+ return 0;
|
||||
+
|
||||
if (cd->media_present)
|
||||
return -EBUSY;
|
||||
else
|
||||
@@ -985,6 +988,7 @@ static int sr_remove(struct device *dev)
|
||||
scsi_autopm_get_device(cd->device);
|
||||
|
||||
del_gendisk(cd->disk);
|
||||
+ dev_set_drvdata(dev, NULL);
|
||||
|
||||
mutex_lock(&sr_ref_mutex);
|
||||
kref_put(&cd->kref, sr_kref_release);
|
|
@ -1,63 +0,0 @@
|
|||
From: Peter Hurley <peter@hurleysoftware.com>
|
||||
Subject: tty: Fix unsafe ldisc reference via ioctl(TIOCGETD)
|
||||
Date: Sun, 10 Jan 2016 22:40:55 -0800
|
||||
Origin: http://article.gmane.org/gmane.linux.kernel/2123249
|
||||
|
||||
ioctl(TIOCGETD) retrieves the line discipline id directly from the
|
||||
ldisc because the line discipline id (c_line) in termios is untrustworthy;
|
||||
userspace may have set termios via ioctl(TCSETS*) without actually
|
||||
changing the line discipline via ioctl(TIOCSETD).
|
||||
|
||||
However, directly accessing the current ldisc via tty->ldisc is
|
||||
unsafe; the ldisc ptr dereferenced may be stale if the line discipline
|
||||
is changing via ioctl(TIOCSETD) or hangup.
|
||||
|
||||
Wait for the line discipline reference (just like read() or write())
|
||||
to retrieve the "current" line discipline id.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
|
||||
---
|
||||
drivers/tty/tty_io.c | 24 +++++++++++++++++++++++-
|
||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/tty/tty_io.c
|
||||
+++ b/drivers/tty/tty_io.c
|
||||
@@ -2654,6 +2654,28 @@ static int tiocsetd(struct tty_struct *t
|
||||
}
|
||||
|
||||
/**
|
||||
+ * tiocgetd - get line discipline
|
||||
+ * @tty: tty device
|
||||
+ * @p: pointer to user data
|
||||
+ *
|
||||
+ * Retrieves the line discipline id directly from the ldisc.
|
||||
+ *
|
||||
+ * Locking: waits for ldisc reference (in case the line discipline
|
||||
+ * is changing or the tty is being hungup)
|
||||
+ */
|
||||
+
|
||||
+static int tiocgetd(struct tty_struct *tty, int __user *p)
|
||||
+{
|
||||
+ struct tty_ldisc *ld;
|
||||
+ int ret;
|
||||
+
|
||||
+ ld = tty_ldisc_ref_wait(tty);
|
||||
+ ret = put_user(ld->ops->num, p);
|
||||
+ tty_ldisc_deref(ld);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* send_break - performed time break
|
||||
* @tty: device to break on
|
||||
* @duration: timeout in mS
|
||||
@@ -2879,7 +2901,7 @@ long tty_ioctl(struct file *file, unsign
|
||||
case TIOCGSID:
|
||||
return tiocgsid(tty, real_tty, p);
|
||||
case TIOCGETD:
|
||||
- return put_user(tty->ldisc->ops->num, (int __user *)p);
|
||||
+ return tiocgetd(tty, p);
|
||||
case TIOCSETD:
|
||||
return tiocsetd(tty, p);
|
||||
case TIOCVHANGUP:
|
|
@ -1,31 +0,0 @@
|
|||
From: Vladis Dronov <vdronov@redhat.com>
|
||||
Subject: usb: serial: visor: fix crash on detecting device without write_urbs
|
||||
Date: Tue, 12 Jan 2016 15:10:50 +0100
|
||||
Origin: http://article.gmane.org/gmane.linux.usb.general/136045
|
||||
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1296466
|
||||
|
||||
The visor driver crashes in clie_5_attach() when a specially crafted USB
|
||||
device without bulk-out endpoint is detected. This fix adds a check that
|
||||
the device has proper configuration expected by the driver.
|
||||
|
||||
Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
|
||||
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
|
||||
---
|
||||
drivers/usb/serial/visor.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/usb/serial/visor.c
|
||||
+++ b/drivers/usb/serial/visor.c
|
||||
@@ -597,8 +597,10 @@ static int clie_5_attach(struct usb_seri
|
||||
*/
|
||||
|
||||
/* some sanity check */
|
||||
- if (serial->num_ports < 2)
|
||||
- return -1;
|
||||
+ if (serial->num_bulk_out < 2) {
|
||||
+ dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
|
||||
/* port 0 now uses the modified endpoint Address */
|
||||
port = serial->port[0];
|
|
@ -1,33 +0,0 @@
|
|||
From: Oliver Neukum <oneukum@suse.com>
|
||||
Date: Tue, 27 Oct 2015 09:51:34 -0200
|
||||
Subject: [media] usbvision fix overflow of interfaces array
|
||||
Origin: http://git.linuxtv.org/cgit.cgi/media_tree.git/commit?id=588afcc1c0e45358159090d95bf7b246fb67565f
|
||||
|
||||
This fixes the crash reported in:
|
||||
http://seclists.org/bugtraq/2015/Oct/35
|
||||
The interface number needs a sanity check.
|
||||
|
||||
Signed-off-by: Oliver Neukum <oneukum@suse.com>
|
||||
Cc: Vladis Dronov <vdronov@redhat.com>
|
||||
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
---
|
||||
drivers/media/usb/usbvision/usbvision-video.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/media/usb/usbvision/usbvision-video.c
|
||||
+++ b/drivers/media/usb/usbvision/usbvision-video.c
|
||||
@@ -1533,6 +1533,13 @@ static int usbvision_probe(struct usb_in
|
||||
printk(KERN_INFO "%s: %s found\n", __func__,
|
||||
usbvision_device_data[model].model_string);
|
||||
|
||||
+ /*
|
||||
+ * this is a security check.
|
||||
+ * an exploit using an incorrect bInterfaceNumber is known
|
||||
+ */
|
||||
+ if (ifnum >= USB_MAXINTERFACES || !dev->actconfig->interface[ifnum])
|
||||
+ return -ENODEV;
|
||||
+
|
||||
if (usbvision_device_data[model].interface >= 0)
|
||||
interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
|
||||
else
|
|
@ -1,40 +0,0 @@
|
|||
From: LABBE Corentin <clabbe.montjoie@gmail.com>
|
||||
Date: Mon, 16 Nov 2015 09:35:54 +0100
|
||||
Subject: crypto: sun4i-ss - add missing statesize
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/herbert/cryptodev-2.6.git/commit?id=4f9ea86604e3ba64edd2817795798168fbb3c1a6
|
||||
Bug-Debian: https://bugs.debian.org/808625
|
||||
|
||||
sun4i-ss implementaton of md5/sha1 is via ahash algorithms.
|
||||
Commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero")
|
||||
made impossible to load them without giving statesize. This patch
|
||||
specifiy statesize for sha1 and md5.
|
||||
|
||||
Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
|
||||
Cc: <stable@vger.kernel.org> # v4.3+
|
||||
Tested-by: Chen-Yu Tsai <wens@csie.org>
|
||||
Signed-off-by: LABBE Corentin <clabbe.montjoie@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/sunxi-ss/sun4i-ss-core.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
||||
index eab6fe2..107cd2a 100644
|
||||
--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
||||
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
||||
@@ -39,6 +39,7 @@ static struct sun4i_ss_alg_template ss_algs[] = {
|
||||
.import = sun4i_hash_import_md5,
|
||||
.halg = {
|
||||
.digestsize = MD5_DIGEST_SIZE,
|
||||
+ .statesize = sizeof(struct md5_state),
|
||||
.base = {
|
||||
.cra_name = "md5",
|
||||
.cra_driver_name = "md5-sun4i-ss",
|
||||
@@ -66,6 +67,7 @@ static struct sun4i_ss_alg_template ss_algs[] = {
|
||||
.import = sun4i_hash_import_sha1,
|
||||
.halg = {
|
||||
.digestsize = SHA1_DIGEST_SIZE,
|
||||
+ .statesize = sizeof(struct sha1_state),
|
||||
.base = {
|
||||
.cra_name = "sha1",
|
||||
.cra_driver_name = "sha1-sun4i-ss",
|
|
@ -1,140 +0,0 @@
|
|||
From: "Maciej W. Rozycki" <macro@imgtec.com>
|
||||
Date: Fri, 22 Jan 2016 05:20:26 +0000
|
||||
Subject: MIPS: math-emu: Correctly handle NOP emulation
|
||||
Origin: https://git.kernel.org/linus/e4553573b37c3f72533683cb5f3a1ad300b18d37
|
||||
|
||||
Fix an issue introduced with commit 9ab4471c9f1b ("MIPS: math-emu:
|
||||
Correct delay-slot exception propagation") where the emulation of a NOP
|
||||
instruction signals the need to terminate the emulation loop. This in
|
||||
turn, if the PC has not changed from the entry to the loop, will cause
|
||||
the kernel to terminate the program with SIGILL.
|
||||
|
||||
Consider this program:
|
||||
|
||||
static double div(double d)
|
||||
{
|
||||
do
|
||||
d /= 2.0;
|
||||
while (d > .5);
|
||||
return d;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return div(argc);
|
||||
}
|
||||
|
||||
which gets compiled to the following binary code:
|
||||
|
||||
00400490 <main>:
|
||||
400490: 44840000 mtc1 a0,$f0
|
||||
400494: 3c020040 lui v0,0x40
|
||||
400498: d44207f8 ldc1 $f2,2040(v0)
|
||||
40049c: 46800021 cvt.d.w $f0,$f0
|
||||
4004a0: 46220002 mul.d $f0,$f0,$f2
|
||||
4004a4: 4620103c c.lt.d $f2,$f0
|
||||
4004a8: 4501fffd bc1t 4004a0 <main+0x10>
|
||||
4004ac: 00000000 nop
|
||||
4004b0: 4620000d trunc.w.d $f0,$f0
|
||||
4004b4: 03e00008 jr ra
|
||||
4004b8: 44020000 mfc1 v0,$f0
|
||||
4004bc: 00000000 nop
|
||||
|
||||
Where the FPU emulator is used, depending on the number of command-line
|
||||
arguments this code will either run to completion or terminate with
|
||||
SIGILL.
|
||||
|
||||
If no arguments are specified, then BC1T will not be taken, NOP will not
|
||||
be emulated and code will complete successfully.
|
||||
|
||||
If one argument is specified, then BC1T will be taken once and NOP will
|
||||
be emulated. At this point the entry PC value will be 0x400498 and the
|
||||
new PC value, set by `mips_dsemul' will be 0x4004a0, the target of BC1T.
|
||||
The emulation loop will terminate, but SIGILL will not be issued,
|
||||
because the PC has changed. The FPU emulator will be entered again and
|
||||
on the second execution BC1T will not be taken, NOP will not be emulated
|
||||
and code will complete successfully.
|
||||
|
||||
If two or more arguments are specified, then the first execution of BC1T
|
||||
will proceed as above. Upon reentering the FPU emulator the emulation
|
||||
loop will continue to BC1T, at which point the branch will be taken and
|
||||
NOP emulated again. At this point however the entry PC value will be
|
||||
0x4004a0, the same as the target of BC1T. This will make the emulator
|
||||
conclude that execution has not advanced and therefore an unsupported
|
||||
FPU instruction has been encountered, and SIGILL will be sent to the
|
||||
process.
|
||||
|
||||
Fix the problem by extending the internal API of `mips_dsemul', making
|
||||
it return -1 if no delay slot emulation frame has been made, the
|
||||
instruction has been handled and execution of the emulation loop needs
|
||||
to continue as if nothing happened. Remove code from `mips_dsemul' to
|
||||
reproduce steps made by the emulation loop at the conclusion of each
|
||||
iteration, as those will be reached normally now. Adjust call sites
|
||||
accordingly. Document the API.
|
||||
|
||||
Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/12172/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/math-emu/cp1emu.c | 4 ++++
|
||||
arch/mips/math-emu/dsemul.c | 14 ++++++++------
|
||||
2 files changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
|
||||
index 32f0e19..cdfd44f 100644
|
||||
--- a/arch/mips/math-emu/cp1emu.c
|
||||
+++ b/arch/mips/math-emu/cp1emu.c
|
||||
@@ -1266,6 +1266,8 @@ branch_common:
|
||||
*/
|
||||
sig = mips_dsemul(xcp, ir,
|
||||
contpc);
|
||||
+ if (sig < 0)
|
||||
+ break;
|
||||
if (sig)
|
||||
xcp->cp0_epc = bcpc;
|
||||
/*
|
||||
@@ -1319,6 +1321,8 @@ branch_common:
|
||||
* instruction in the dslot
|
||||
*/
|
||||
sig = mips_dsemul(xcp, ir, contpc);
|
||||
+ if (sig < 0)
|
||||
+ break;
|
||||
if (sig)
|
||||
xcp->cp0_epc = bcpc;
|
||||
/* SIGILL forces out of the emulation loop. */
|
||||
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
|
||||
index cbb36c1..70e4824 100644
|
||||
--- a/arch/mips/math-emu/dsemul.c
|
||||
+++ b/arch/mips/math-emu/dsemul.c
|
||||
@@ -31,18 +31,20 @@ struct emuframe {
|
||||
unsigned long epc;
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Set up an emulation frame for instruction IR, from a delay slot of
|
||||
+ * a branch jumping to CPC. Return 0 if successful, -1 if no emulation
|
||||
+ * required, otherwise a signal number causing a frame setup failure.
|
||||
+ */
|
||||
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
|
||||
{
|
||||
struct emuframe __user *fr;
|
||||
int err;
|
||||
|
||||
+ /* NOP is easy */
|
||||
if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
|
||||
- (ir == 0)) {
|
||||
- /* NOP is easy */
|
||||
- regs->cp0_epc = cpc;
|
||||
- clear_delay_slot(regs);
|
||||
- return 0;
|
||||
- }
|
||||
+ (ir == 0))
|
||||
+ return -1;
|
||||
|
||||
pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
|
||||
|
||||
--
|
||||
2.7.0.rc3
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
From: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
Date: Fri, 23 Oct 2015 10:56:12 +0200
|
||||
Subject: drm/i915: shut up gen8+ SDE irq dmesg noise
|
||||
Origin: http://cgit.freedesktop.org/drm-intel/commit?id=97e5ed1111dcc5300a0f59a55248cd243937a8ab
|
||||
|
||||
We get tons of cases where the master interrupt handler apparently set
|
||||
a bit, with the SDEIIR disagreeing. No idea what's going on there, but
|
||||
it's consistent on gen8+, no one seems to care about it and it's
|
||||
making CI results flaky.
|
||||
|
||||
Shut it up.
|
||||
|
||||
No idea what's going on here, but we've had fun with PCH interrupts
|
||||
before:
|
||||
|
||||
commit 44498aea293b37af1d463acd9658cdce1ecdf427
|
||||
Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
|
||||
Date: Fri Feb 22 17:05:28 2013 -0300
|
||||
|
||||
drm/i915: also disable south interrupts when handling them
|
||||
|
||||
Note that there's a regression report in Bugzilla, and other
|
||||
regression reports on the mailing lists keep croping up. But no ill
|
||||
effects have ever been reported. But for paranoia still keep the
|
||||
message at a debug level as a breadcrumb, just in case.
|
||||
|
||||
This message was introduced in
|
||||
|
||||
commit 38cc46d73ed99dd7002f1406002e52d7975d16cc
|
||||
Author: Oscar Mateo <oscar.mateo@intel.com>
|
||||
Date: Mon Jun 16 16:10:59 2014 +0100
|
||||
|
||||
drm/i915/bdw: Ack interrupts before handling them (GEN8)
|
||||
|
||||
v2: Improve commit message a bit.
|
||||
|
||||
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
|
||||
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1445590572-23631-2-git-send-email-daniel.vetter@ffwll.ch
|
||||
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92084
|
||||
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80896
|
||||
Acked-by: Mika Kuoppala <mika.kuoppala@intel.com>
|
||||
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
[bwh: Adjust context]
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_irq.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_irq.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_irq.c
|
||||
@@ -2354,9 +2354,13 @@ static irqreturn_t gen8_irq_handler(int
|
||||
spt_irq_handler(dev, pch_iir);
|
||||
else
|
||||
cpt_irq_handler(dev, pch_iir);
|
||||
- } else
|
||||
- DRM_ERROR("The master control interrupt lied (SDE)!\n");
|
||||
-
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * Like on previous PCH there seems to be something
|
||||
+ * fishy going on with forwarding PCH interrupts.
|
||||
+ */
|
||||
+ DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n");
|
||||
+ }
|
||||
}
|
||||
|
||||
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
|
@ -1,60 +0,0 @@
|
|||
From: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Date: Fri, 8 Jan 2016 20:29:40 +0100
|
||||
Subject: drm/vmwgfx: Fix a width / pitch mismatch on framebuffer updates
|
||||
Origin: https://git.kernel.org/linus/a50e2bf5a0f674d62b69f51f6935a30e82bd015c
|
||||
|
||||
When the framebuffer is a vmwgfx dma buffer and a proxy surface is
|
||||
created, the vmw_kms_update_proxy() function requires that the proxy
|
||||
surface width and the framebuffer pitch are compatible, otherwise
|
||||
display corruption occurs as seen in gnome-shell/native with software
|
||||
3D. Since the framebuffer pitch is determined by user-space, allocate
|
||||
a proxy surface the width of which is based on the framebuffer pitch
|
||||
rather than on the framebuffer width.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Reported-by: Raphael Hertzog <buxy@kali.org>
|
||||
Tested-by: Mati Aharoni <muts@kali.org>
|
||||
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Reviewed-by: Brian Paul <brianp@vmware.com>
|
||||
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||
---
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
|
||||
@@ -725,21 +725,25 @@ static int vmw_create_dmabuf_proxy(struc
|
||||
uint32_t format;
|
||||
struct drm_vmw_size content_base_size;
|
||||
struct vmw_resource *res;
|
||||
+ unsigned int bytes_pp;
|
||||
int ret;
|
||||
|
||||
switch (mode_cmd->depth) {
|
||||
case 32:
|
||||
case 24:
|
||||
format = SVGA3D_X8R8G8B8;
|
||||
+ bytes_pp = 4;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case 15:
|
||||
format = SVGA3D_R5G6B5;
|
||||
+ bytes_pp = 2;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
format = SVGA3D_P8;
|
||||
+ bytes_pp = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -747,7 +751,7 @@ static int vmw_create_dmabuf_proxy(struc
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- content_base_size.width = mode_cmd->width;
|
||||
+ content_base_size.width = mode_cmd->pitch / bytes_pp;
|
||||
content_base_size.height = mode_cmd->height;
|
||||
content_base_size.depth = 1;
|
||||
|
|
@ -3,9 +3,9 @@ Subject: cgroups: Document the Debian memory resource controller config change
|
|||
Forwarded: not-needed
|
||||
|
||||
---
|
||||
--- a/Documentation/cgroups/memory.txt
|
||||
+++ b/Documentation/cgroups/memory.txt
|
||||
@@ -46,6 +46,10 @@ Features:
|
||||
--- a/Documentation/cgroup-v1/memory.txt
|
||||
+++ b/Documentation/cgroup-v1/memory.txt
|
||||
@@ -52,6 +52,10 @@ Features:
|
||||
Kernel memory support is a work in progress, and the current version provides
|
||||
basically functionality. (See Section 2.7)
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ The installer appears to report any failed request, and it is probably
|
|||
not easy to detect that this particular failure is harmless. So stop
|
||||
requesting the unreleased firmware.
|
||||
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
|
||||
--- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c
|
||||
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "dvm/commands.h" /* needed for BT for now */
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ are set.
|
|||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -980,7 +980,7 @@ endif
|
||||
@@ -984,7 +984,7 @@ endif
|
||||
prepare2: prepare3 outputmakefile asm-generic
|
||||
|
||||
prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
|
||||
|
@ -18,7 +18,7 @@ are set.
|
|||
$(cmd_crmodverdir)
|
||||
|
||||
archprepare: archheaders archscripts prepare1 scripts_basic
|
||||
@@ -1012,6 +1012,16 @@ define filechk_version.h
|
||||
@@ -1016,6 +1016,16 @@ define filechk_version.h
|
||||
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
|
||||
endef
|
||||
|
||||
|
@ -35,7 +35,7 @@ are set.
|
|||
$(version_h): $(srctree)/Makefile FORCE
|
||||
$(call filechk,version.h)
|
||||
$(Q)rm -f $(old_version_h)
|
||||
@@ -1019,6 +1029,9 @@ $(version_h): $(srctree)/Makefile FORCE
|
||||
@@ -1023,6 +1033,9 @@ $(version_h): $(srctree)/Makefile FORCE
|
||||
include/generated/utsrelease.h: include/config/kernel.release FORCE
|
||||
$(call filechk,utsrelease.h)
|
||||
|
||||
|
@ -99,7 +99,7 @@ are set.
|
|||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/io.h>
|
||||
@@ -1001,8 +1002,9 @@ void show_regs(struct pt_regs * regs)
|
||||
@@ -1150,8 +1151,9 @@ void show_regs(struct pt_regs * regs)
|
||||
|
||||
printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
|
||||
regs->nip, regs->link, regs->ctr);
|
||||
|
@ -109,7 +109,7 @@ are set.
|
|||
+ regs, regs->trap, print_tainted(), init_utsname()->release,
|
||||
+ LINUX_PACKAGE_ID);
|
||||
printk("MSR: "REG" ", regs->msr);
|
||||
printbits(regs->msr, msr_bits);
|
||||
print_msr_bits(regs->msr);
|
||||
printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
|
||||
--- a/kernel/printk/printk.c
|
||||
+++ b/kernel/printk/printk.c
|
||||
|
@ -120,8 +120,8 @@ are set.
|
|||
+#include <generated/package.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -3036,11 +3037,12 @@ void __init dump_stack_set_arch_desc(con
|
||||
#include <asm-generic/sections.h>
|
||||
@@ -3168,11 +3169,12 @@ void __init dump_stack_set_arch_desc(con
|
||||
*/
|
||||
void dump_stack_print_info(const char *log_lvl)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From: J. R. Okajima <hooanon05@yahoo.co.jp>
|
||||
Date: Sat Nov 21 10:43:50 2015 +0900
|
||||
Date: Wed Feb 10 03:44:15 2016 +0900
|
||||
Subject: aufs4.x-rcN base patch
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/980697121e7bb079411664d77caa8f1e489f344c
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/5fecf5788b797f74b83e36ca921dc1c4bfdcbad9
|
||||
Bug-Debian: https://bugs.debian.org/541828
|
||||
|
||||
Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
||||
|
@ -9,10 +9,10 @@ Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
|||
aufs4.x-rcN base patch
|
||||
|
||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index e9caa4b..ddb7b8a 100644
|
||||
index 7f1fa4f..d910255 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -2028,6 +2028,19 @@ F: include/linux/audit.h
|
||||
@@ -2075,6 +2075,19 @@ F: include/linux/audit.h
|
||||
F: include/uapi/linux/audit.h
|
||||
F: kernel/audit*
|
||||
|
||||
|
@ -62,7 +62,7 @@ index 423f4ca..abfdd2b 100644
|
|||
|
||||
static ssize_t loop_attr_show(struct device *dev, char *page,
|
||||
diff --git a/fs/dcache.c b/fs/dcache.c
|
||||
index 5c33aeb..8aa7f26 100644
|
||||
index 92d5140..63b22d7 100644
|
||||
--- a/fs/dcache.c
|
||||
+++ b/fs/dcache.c
|
||||
@@ -1167,7 +1167,7 @@ enum d_walk_ret {
|
||||
|
@ -75,10 +75,10 @@ index 5c33aeb..8aa7f26 100644
|
|||
void (*finish)(void *))
|
||||
{
|
||||
diff --git a/fs/read_write.c b/fs/read_write.c
|
||||
index 819ef3f..fd0414e 100644
|
||||
index 324ec27..d38892e 100644
|
||||
--- a/fs/read_write.c
|
||||
+++ b/fs/read_write.c
|
||||
@@ -494,6 +494,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
|
||||
@@ -533,6 +533,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_write);
|
||||
|
||||
|
@ -108,10 +108,10 @@ index 819ef3f..fd0414e 100644
|
|||
{
|
||||
mm_segment_t old_fs;
|
||||
diff --git a/fs/splice.c b/fs/splice.c
|
||||
index 801c21c..218d188 100644
|
||||
index 82bc0d6..93aee51 100644
|
||||
--- a/fs/splice.c
|
||||
+++ b/fs/splice.c
|
||||
@@ -1102,8 +1102,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
|
||||
@@ -1108,8 +1108,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
|
||||
/*
|
||||
* Attempt to initiate a splice from pipe to file.
|
||||
*/
|
||||
|
@ -122,7 +122,7 @@ index 801c21c..218d188 100644
|
|||
{
|
||||
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
|
||||
loff_t *, size_t, unsigned int);
|
||||
@@ -1119,9 +1119,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
|
||||
@@ -1125,9 +1125,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
|
||||
/*
|
||||
* Attempt to initiate a splice from a file to a pipe.
|
||||
*/
|
||||
|
@ -148,10 +148,10 @@ index f87d308..9a290b3 100644
|
|||
static inline void fput_light(struct file *file, int fput_needed)
|
||||
{
|
||||
diff --git a/include/linux/fs.h b/include/linux/fs.h
|
||||
index 3aa5142..8d48506 100644
|
||||
index ae68100..2ea096b 100644
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1672,6 +1672,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
|
||||
@@ -1704,6 +1704,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
|
||||
struct iovec *fast_pointer,
|
||||
struct iovec **ret_pointer);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From: J. R. Okajima <hooanon05@yahoo.co.jp>
|
||||
Date: Sat Nov 21 10:43:50 2015 +0900
|
||||
Date: Wed Feb 10 03:44:15 2016 +0900
|
||||
Subject: aufs4.x-rcN mmap patch
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/980697121e7bb079411664d77caa8f1e489f344c
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/5fecf5788b797f74b83e36ca921dc1c4bfdcbad9
|
||||
Bug-Debian: https://bugs.debian.org/541828
|
||||
|
||||
Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
||||
|
@ -9,10 +9,10 @@ Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
|||
aufs4.x-rcN mmap patch
|
||||
|
||||
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
||||
index bd3e9e6..fc42216 100644
|
||||
index 4f764c2..229de5e 100644
|
||||
--- a/fs/proc/base.c
|
||||
+++ b/fs/proc/base.c
|
||||
@@ -1921,7 +1921,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
|
||||
@@ -1933,7 +1933,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_exact_vma(mm, vm_start, vm_end);
|
||||
if (vma && vma->vm_file) {
|
||||
|
@ -38,10 +38,10 @@ index f8595e8..cb8eda0 100644
|
|||
ino = inode->i_ino;
|
||||
}
|
||||
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
||||
index 187b3b5..e03793e 100644
|
||||
index fa95ab2..d440354 100644
|
||||
--- a/fs/proc/task_mmu.c
|
||||
+++ b/fs/proc/task_mmu.c
|
||||
@@ -281,7 +281,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
||||
@@ -298,7 +298,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
||||
const char *name = NULL;
|
||||
|
||||
if (file) {
|
||||
|
@ -53,7 +53,7 @@ index 187b3b5..e03793e 100644
|
|||
dev = inode->i_sb->s_dev;
|
||||
ino = inode->i_ino;
|
||||
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
|
||||
@@ -1505,7 +1508,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
|
||||
@@ -1576,7 +1579,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
|
||||
struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
|
||||
struct vm_area_struct *vma = v;
|
||||
struct numa_maps *md = &numa_priv->md;
|
||||
|
@ -63,10 +63,10 @@ index 187b3b5..e03793e 100644
|
|||
struct mm_walk walk = {
|
||||
.hugetlb_entry = gather_hugetlb_stats,
|
||||
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
|
||||
index e0d64c9..7aa92db 100644
|
||||
index faacb0c..17b43be 100644
|
||||
--- a/fs/proc/task_nommu.c
|
||||
+++ b/fs/proc/task_nommu.c
|
||||
@@ -160,7 +160,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
|
||||
@@ -163,7 +163,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
|
||||
file = vma->vm_file;
|
||||
|
||||
if (file) {
|
||||
|
@ -79,10 +79,10 @@ index e0d64c9..7aa92db 100644
|
|||
ino = inode->i_ino;
|
||||
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
||||
index 00bad77..cc616b0 100644
|
||||
index 516e149..ddd5454 100644
|
||||
--- a/include/linux/mm.h
|
||||
+++ b/include/linux/mm.h
|
||||
@@ -1183,6 +1183,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
|
||||
@@ -1217,6 +1217,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -112,10 +112,10 @@ index 00bad77..cc616b0 100644
|
|||
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, int write);
|
||||
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
|
||||
index f8d1492..c3a3760 100644
|
||||
index 624b78b..1be91c5 100644
|
||||
--- a/include/linux/mm_types.h
|
||||
+++ b/include/linux/mm_types.h
|
||||
@@ -272,6 +272,7 @@ struct vm_region {
|
||||
@@ -269,6 +269,7 @@ struct vm_region {
|
||||
unsigned long vm_top; /* region allocated to here */
|
||||
unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
|
||||
struct file *vm_file; /* the backing file or NULL */
|
||||
|
@ -123,7 +123,7 @@ index f8d1492..c3a3760 100644
|
|||
|
||||
int vm_usage; /* region usage count (access under nommu_region_sem) */
|
||||
bool vm_icache_flushed : 1; /* true if the icache has been flushed for
|
||||
@@ -346,6 +347,7 @@ struct vm_area_struct {
|
||||
@@ -343,6 +344,7 @@ struct vm_area_struct {
|
||||
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
|
||||
units, *not* PAGE_CACHE_SIZE */
|
||||
struct file * vm_file; /* File we map to (can be NULL). */
|
||||
|
@ -132,7 +132,7 @@ index f8d1492..c3a3760 100644
|
|||
|
||||
#ifndef CONFIG_MMU
|
||||
diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
index f97f2c4..3ef40d6 100644
|
||||
index 2e391c7..6c4215c 100644
|
||||
--- a/kernel/fork.c
|
||||
+++ b/kernel/fork.c
|
||||
@@ -464,7 +464,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
|
||||
|
@ -158,10 +158,10 @@ index 2ed4319..e3a53f5 100644
|
|||
obj-y += init-mm.o
|
||||
|
||||
diff --git a/mm/filemap.c b/mm/filemap.c
|
||||
index 1bb0076..8eaece8 100644
|
||||
index bc94386..25cdcef 100644
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -2128,7 +2128,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
@@ -2209,7 +2209,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
int ret = VM_FAULT_LOCKED;
|
||||
|
||||
sb_start_pagefault(inode->i_sb);
|
||||
|
@ -171,10 +171,10 @@ index 1bb0076..8eaece8 100644
|
|||
if (page->mapping != inode->i_mapping) {
|
||||
unlock_page(page);
|
||||
diff --git a/mm/memory.c b/mm/memory.c
|
||||
index deb679c..df2ce3e 100644
|
||||
index 635451a..f589a4e 100644
|
||||
--- a/mm/memory.c
|
||||
+++ b/mm/memory.c
|
||||
@@ -2035,7 +2035,7 @@ static inline int wp_page_reuse(struct mm_struct *mm,
|
||||
@@ -2042,7 +2042,7 @@ static inline int wp_page_reuse(struct mm_struct *mm,
|
||||
}
|
||||
|
||||
if (!page_mkwrite)
|
||||
|
@ -184,10 +184,10 @@ index deb679c..df2ce3e 100644
|
|||
|
||||
return VM_FAULT_WRITE;
|
||||
diff --git a/mm/mmap.c b/mm/mmap.c
|
||||
index 2ce04a6..f555c0a 100644
|
||||
index 2f2415a..d5943a1 100644
|
||||
--- a/mm/mmap.c
|
||||
+++ b/mm/mmap.c
|
||||
@@ -275,7 +275,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
|
||||
@@ -290,7 +290,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
|
||||
if (vma->vm_ops && vma->vm_ops->close)
|
||||
vma->vm_ops->close(vma);
|
||||
if (vma->vm_file)
|
||||
|
@ -196,7 +196,7 @@ index 2ce04a6..f555c0a 100644
|
|||
mpol_put(vma_policy(vma));
|
||||
kmem_cache_free(vm_area_cachep, vma);
|
||||
return next;
|
||||
@@ -887,7 +887,7 @@ again: remove_next = 1 + (end > next->vm_end);
|
||||
@@ -909,7 +909,7 @@ again: remove_next = 1 + (end > next->vm_end);
|
||||
if (remove_next) {
|
||||
if (file) {
|
||||
uprobe_munmap(next, next->vm_start, next->vm_end);
|
||||
|
@ -205,7 +205,7 @@ index 2ce04a6..f555c0a 100644
|
|||
}
|
||||
if (next->anon_vma)
|
||||
anon_vma_merge(vma, next);
|
||||
@@ -1681,8 +1681,8 @@ out:
|
||||
@@ -1683,8 +1683,8 @@ out:
|
||||
return addr;
|
||||
|
||||
unmap_and_free_vma:
|
||||
|
@ -215,7 +215,7 @@ index 2ce04a6..f555c0a 100644
|
|||
|
||||
/* Undo any partial mapping done by a device driver. */
|
||||
unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
|
||||
@@ -2488,7 +2488,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
@@ -2479,7 +2479,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
goto out_free_mpol;
|
||||
|
||||
if (new->vm_file)
|
||||
|
@ -224,7 +224,7 @@ index 2ce04a6..f555c0a 100644
|
|||
|
||||
if (new->vm_ops && new->vm_ops->open)
|
||||
new->vm_ops->open(new);
|
||||
@@ -2507,7 +2507,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
@@ -2498,7 +2498,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
if (new->vm_ops && new->vm_ops->close)
|
||||
new->vm_ops->close(new);
|
||||
if (new->vm_file)
|
||||
|
@ -233,7 +233,7 @@ index 2ce04a6..f555c0a 100644
|
|||
unlink_anon_vmas(new);
|
||||
out_free_mpol:
|
||||
mpol_put(vma_policy(new));
|
||||
@@ -2649,7 +2649,6 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
||||
@@ -2640,7 +2640,6 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long populate = 0;
|
||||
unsigned long ret = -EINVAL;
|
||||
|
@ -241,7 +241,7 @@ index 2ce04a6..f555c0a 100644
|
|||
|
||||
pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. "
|
||||
"See Documentation/vm/remap_file_pages.txt.\n",
|
||||
@@ -2693,10 +2692,10 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
||||
@@ -2684,10 +2683,10 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
||||
munlock_vma_pages_range(vma, start, start + size);
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ index 2ce04a6..f555c0a 100644
|
|||
out:
|
||||
up_write(&mm->mmap_sem);
|
||||
if (populate)
|
||||
@@ -2966,7 +2965,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
|
||||
@@ -2958,7 +2957,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
|
||||
if (anon_vma_clone(new_vma, vma))
|
||||
goto out_free_mempol;
|
||||
if (new_vma->vm_file)
|
||||
|
@ -264,7 +264,7 @@ index 2ce04a6..f555c0a 100644
|
|||
new_vma->vm_ops->open(new_vma);
|
||||
vma_link(mm, new_vma, prev, rb_link, rb_parent);
|
||||
diff --git a/mm/nommu.c b/mm/nommu.c
|
||||
index 92be862..29179f7 100644
|
||||
index fbf6f0f1..1a4a06d 100644
|
||||
--- a/mm/nommu.c
|
||||
+++ b/mm/nommu.c
|
||||
@@ -671,7 +671,7 @@ static void __put_nommu_region(struct vm_region *region)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From: J. R. Okajima <hooanon05@yahoo.co.jp>
|
||||
Date: Sat Nov 21 10:43:50 2015 +0900
|
||||
Date: Wed Feb 10 03:44:15 2016 +0900
|
||||
Subject: aufs4.x-rcN standalone patch
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/980697121e7bb079411664d77caa8f1e489f344c
|
||||
Origin: https://github.com/sfjro/aufs4-standalone/tree/5fecf5788b797f74b83e36ca921dc1c4bfdcbad9
|
||||
Bug-Debian: https://bugs.debian.org/541828
|
||||
|
||||
Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
||||
|
@ -9,7 +9,7 @@ Patch headers added by debian/patches/features/all/aufs4/gen-patch
|
|||
aufs4.x-rcN standalone patch
|
||||
|
||||
diff --git a/fs/dcache.c b/fs/dcache.c
|
||||
index 8aa7f26..f997345 100644
|
||||
index 63b22d7..4dcd979 100644
|
||||
--- a/fs/dcache.c
|
||||
+++ b/fs/dcache.c
|
||||
@@ -1272,6 +1272,7 @@ rename_retry:
|
||||
|
@ -21,7 +21,7 @@ index 8aa7f26..f997345 100644
|
|||
/*
|
||||
* Search for at least 1 mount point in the dentry's subdirs.
|
||||
diff --git a/fs/exec.c b/fs/exec.c
|
||||
index b06623a..b9206c5 100644
|
||||
index dcd4ac7..f4e040f 100644
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -103,6 +103,7 @@ bool path_noexec(const struct path *path)
|
||||
|
@ -33,7 +33,7 @@ index b06623a..b9206c5 100644
|
|||
#ifdef CONFIG_USELIB
|
||||
/*
|
||||
diff --git a/fs/file_table.c b/fs/file_table.c
|
||||
index ad17e05..df66450 100644
|
||||
index ad17e05..38e046a 100644
|
||||
--- a/fs/file_table.c
|
||||
+++ b/fs/file_table.c
|
||||
@@ -147,6 +147,7 @@ over:
|
||||
|
@ -44,7 +44,23 @@ index ad17e05..df66450 100644
|
|||
|
||||
/**
|
||||
* alloc_file - allocate and initialize a 'struct file'
|
||||
@@ -308,6 +309,7 @@ void put_filp(struct file *file)
|
||||
@@ -258,6 +259,7 @@ void flush_delayed_fput(void)
|
||||
{
|
||||
delayed_fput(NULL);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(flush_delayed_fput);
|
||||
|
||||
static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
|
||||
|
||||
@@ -300,6 +302,7 @@ void __fput_sync(struct file *file)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(fput);
|
||||
+EXPORT_SYMBOL_GPL(__fput_sync);
|
||||
|
||||
void put_filp(struct file *file)
|
||||
{
|
||||
@@ -308,6 +311,7 @@ void put_filp(struct file *file)
|
||||
file_free(file);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +69,7 @@ index ad17e05..df66450 100644
|
|||
void __init files_init(void)
|
||||
{
|
||||
diff --git a/fs/namespace.c b/fs/namespace.c
|
||||
index 0570729..ec560d8 100644
|
||||
index 4fb1691..765ebc3 100644
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -463,6 +463,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
|
||||
|
@ -64,7 +80,7 @@ index 0570729..ec560d8 100644
|
|||
|
||||
/**
|
||||
* mnt_drop_write - give up write access to a mount
|
||||
@@ -1803,6 +1804,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
|
||||
@@ -1811,6 +1812,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -109,10 +125,10 @@ index d16b62c..06ca6bc 100644
|
|||
int fsnotify_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
|
||||
index fc0df44..325b5c6 100644
|
||||
index cfcbf11..2c024528 100644
|
||||
--- a/fs/notify/mark.c
|
||||
+++ b/fs/notify/mark.c
|
||||
@@ -109,6 +109,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
|
||||
@@ -106,6 +106,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
|
||||
mark->free_mark(mark);
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +136,7 @@ index fc0df44..325b5c6 100644
|
|||
|
||||
/* Calculate mask of events for a list of marks */
|
||||
u32 fsnotify_recalc_mask(struct hlist_head *head)
|
||||
@@ -208,6 +209,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark,
|
||||
@@ -211,6 +212,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark,
|
||||
mutex_unlock(&group->mark_mutex);
|
||||
fsnotify_free_mark(mark);
|
||||
}
|
||||
|
@ -128,28 +144,25 @@ index fc0df44..325b5c6 100644
|
|||
|
||||
void fsnotify_destroy_marks(struct hlist_head *head, spinlock_t *lock)
|
||||
{
|
||||
@@ -392,6 +394,7 @@ err:
|
||||
|
||||
@@ -391,6 +393,7 @@ err:
|
||||
call_srcu(&fsnotify_mark_srcu, &mark->g_rcu, fsnotify_mark_free_rcu);
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
|
||||
|
||||
int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
|
||||
struct inode *inode, struct vfsmount *mnt, int allow_dups)
|
||||
@@ -492,6 +495,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
|
||||
@@ -491,3 +494,4 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
|
||||
atomic_set(&mark->refcnt, 1);
|
||||
mark->free_mark = free_mark;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
|
||||
|
||||
static int fsnotify_mark_destroy(void *ignored)
|
||||
{
|
||||
diff --git a/fs/open.c b/fs/open.c
|
||||
index b6f1e96..4ab0d4e 100644
|
||||
index 55bdc75..e0606c6 100644
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
inode_unlock(dentry->d_inode);
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(do_truncate);
|
||||
|
@ -165,10 +178,10 @@ index b6f1e96..4ab0d4e 100644
|
|||
static int do_dentry_open(struct file *f,
|
||||
struct inode *inode,
|
||||
diff --git a/fs/read_write.c b/fs/read_write.c
|
||||
index fd0414e..8ace6ec 100644
|
||||
index d38892e..fbd7169 100644
|
||||
--- a/fs/read_write.c
|
||||
+++ b/fs/read_write.c
|
||||
@@ -504,6 +504,7 @@ vfs_readf_t vfs_readf(struct file *file)
|
||||
@@ -543,6 +543,7 @@ vfs_readf_t vfs_readf(struct file *file)
|
||||
return new_sync_read;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
@ -176,7 +189,7 @@ index fd0414e..8ace6ec 100644
|
|||
|
||||
vfs_writef_t vfs_writef(struct file *file)
|
||||
{
|
||||
@@ -515,6 +516,7 @@ vfs_writef_t vfs_writef(struct file *file)
|
||||
@@ -554,6 +555,7 @@ vfs_writef_t vfs_writef(struct file *file)
|
||||
return new_sync_write;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
@ -185,10 +198,10 @@ index fd0414e..8ace6ec 100644
|
|||
ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
|
||||
{
|
||||
diff --git a/fs/splice.c b/fs/splice.c
|
||||
index 218d188..aa4f0d1 100644
|
||||
index 93aee51..5316378 100644
|
||||
--- a/fs/splice.c
|
||||
+++ b/fs/splice.c
|
||||
@@ -1115,6 +1115,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
|
||||
@@ -1121,6 +1121,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
|
||||
|
||||
return splice_write(pipe, out, ppos, len, flags);
|
||||
}
|
||||
|
@ -196,7 +209,7 @@ index 218d188..aa4f0d1 100644
|
|||
|
||||
/*
|
||||
* Attempt to initiate a splice from a file to a pipe.
|
||||
@@ -1141,6 +1142,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
|
||||
@@ -1147,6 +1148,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
|
||||
|
||||
return splice_read(in, ppos, pipe, len, flags);
|
||||
}
|
||||
|
@ -205,7 +218,7 @@ index 218d188..aa4f0d1 100644
|
|||
/**
|
||||
* splice_direct_to_actor - splices data directly between two non-pipes
|
||||
diff --git a/fs/xattr.c b/fs/xattr.c
|
||||
index 9b932b9..44c457a 100644
|
||||
index 07d0e47..20c8815 100644
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -207,6 +207,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
|
@ -214,13 +227,22 @@ index 9b932b9..44c457a 100644
|
|||
}
|
||||
+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
|
||||
|
||||
/* Compare an extended attribute value with the given value */
|
||||
int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
|
||||
ssize_t
|
||||
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
diff --git a/kernel/task_work.c b/kernel/task_work.c
|
||||
index 53fa971..f80d564 100644
|
||||
--- a/kernel/task_work.c
|
||||
+++ b/kernel/task_work.c
|
||||
@@ -118,3 +118,4 @@ void task_work_run(void)
|
||||
} while (work);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(task_work_run);
|
||||
diff --git a/security/commoncap.c b/security/commoncap.c
|
||||
index 1832cf7..987ff5f 100644
|
||||
index 48071ed..bf82414 100644
|
||||
--- a/security/commoncap.c
|
||||
+++ b/security/commoncap.c
|
||||
@@ -1053,12 +1053,14 @@ int cap_mmap_addr(unsigned long addr)
|
||||
@@ -1058,12 +1058,14 @@ int cap_mmap_addr(unsigned long addr)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -256,7 +278,7 @@ index 03c1652..b00aa76 100644
|
|||
int devcgroup_inode_mknod(int mode, dev_t dev)
|
||||
{
|
||||
diff --git a/security/security.c b/security/security.c
|
||||
index 46f405c..54488b0 100644
|
||||
index e8ffd92..6f07901 100644
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -433,6 +433,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
|
||||
|
|
|
@ -13,7 +13,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
---
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -588,8 +588,8 @@ bytes respectively. Such letter suffixes
|
||||
@@ -597,8 +597,8 @@ bytes respectively. Such letter suffixes
|
||||
ccw_timeout_log [S390]
|
||||
See Documentation/s390/CommonIO for details.
|
||||
|
||||
|
@ -26,9 +26,9 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
a single hierarchy
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -1010,6 +1010,14 @@ config MEMCG
|
||||
Provides a memory resource controller that manages both anonymous
|
||||
memory and page cache. (See Documentation/cgroups/memory.txt)
|
||||
@@ -945,6 +945,14 @@ config MEMCG
|
||||
help
|
||||
Provides control over the memory footprint of tasks in a cgroup.
|
||||
|
||||
+config MEMCG_DISABLED
|
||||
+ bool "Memory Resource Controller disabled by default"
|
||||
|
@ -39,11 +39,11 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
+ enabled using the kernel parameter "cgroup_enable=memory".
|
||||
+
|
||||
config MEMCG_SWAP
|
||||
bool "Memory Resource Controller Swap Extension"
|
||||
bool "Swap controller"
|
||||
depends on MEMCG && SWAP
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -5216,7 +5216,11 @@ int __init cgroup_init_early(void)
|
||||
@@ -5269,7 +5269,11 @@ int __init cgroup_init_early(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
|
||||
/**
|
||||
* cgroup_init - cgroup initialization
|
||||
@@ -5691,7 +5695,7 @@ out_free:
|
||||
@@ -5729,7 +5733,7 @@ out_free:
|
||||
kfree(pathbuf);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
{
|
||||
struct cgroup_subsys *ss;
|
||||
char *token;
|
||||
@@ -5705,13 +5709,27 @@ static int __init cgroup_disable(char *s
|
||||
@@ -5743,13 +5747,27 @@ static int __init cgroup_disable(char *s
|
||||
if (strcmp(token, ss->name) &&
|
||||
strcmp(token, ss->legacy_name))
|
||||
continue;
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 1 Mar 2013 11:17:42 +0100
|
||||
Subject: futex: Ensure lock/unlock symetry versus pi_lock and hash bucket lock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
In exit_pi_state_list() we have the following locking construct:
|
||||
|
||||
spin_lock(&hb->lock);
|
||||
raw_spin_lock_irq(&curr->pi_lock);
|
||||
|
||||
...
|
||||
spin_unlock(&hb->lock);
|
||||
|
||||
In !RT this works, but on RT the migrate_enable() function which is
|
||||
called from spin_unlock() sees atomic context due to the held pi_lock
|
||||
and just decrements the migrate_disable_atomic counter of the
|
||||
task. Now the next call to migrate_disable() sees the counter being
|
||||
negative and issues a warning. That check should be in
|
||||
migrate_enable() already.
|
||||
|
||||
Fix this by dropping pi_lock before unlocking hb->lock and reaquire
|
||||
pi_lock after that again. This is safe as the loop code reevaluates
|
||||
head again under the pi_lock.
|
||||
|
||||
Reported-by: Yong Zhang <yong.zhang@windriver.com>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/futex.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/kernel/futex.c
|
||||
+++ b/kernel/futex.c
|
||||
@@ -815,7 +815,9 @@ void exit_pi_state_list(struct task_stru
|
||||
* task still owns the PI-state:
|
||||
*/
|
||||
if (head->next != next) {
|
||||
+ raw_spin_unlock_irq(&curr->pi_lock);
|
||||
spin_unlock(&hb->lock);
|
||||
+ raw_spin_lock_irq(&curr->pi_lock);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
From: "Yadi.hu" <yadi.hu@windriver.com>
|
||||
Date: Wed, 10 Dec 2014 10:32:09 +0800
|
||||
Subject: ARM: enable irq in translation/section permission fault handlers
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Probably happens on all ARM, with
|
||||
CONFIG_PREEMPT_RT_FULL
|
||||
CONFIG_DEBUG_ATOMIC_SLEEP
|
||||
|
||||
This simple program....
|
||||
|
||||
int main() {
|
||||
*((char*)0xc0001000) = 0;
|
||||
};
|
||||
|
||||
[ 512.742724] BUG: sleeping function called from invalid context at kernel/rtmutex.c:658
|
||||
[ 512.743000] in_atomic(): 0, irqs_disabled(): 128, pid: 994, name: a
|
||||
[ 512.743217] INFO: lockdep is turned off.
|
||||
[ 512.743360] irq event stamp: 0
|
||||
[ 512.743482] hardirqs last enabled at (0): [< (null)>] (null)
|
||||
[ 512.743714] hardirqs last disabled at (0): [<c0426370>] copy_process+0x3b0/0x11c0
|
||||
[ 512.744013] softirqs last enabled at (0): [<c0426370>] copy_process+0x3b0/0x11c0
|
||||
[ 512.744303] softirqs last disabled at (0): [< (null)>] (null)
|
||||
[ 512.744631] [<c041872c>] (unwind_backtrace+0x0/0x104)
|
||||
[ 512.745001] [<c09af0c4>] (dump_stack+0x20/0x24)
|
||||
[ 512.745355] [<c0462490>] (__might_sleep+0x1dc/0x1e0)
|
||||
[ 512.745717] [<c09b6770>] (rt_spin_lock+0x34/0x6c)
|
||||
[ 512.746073] [<c0441bf0>] (do_force_sig_info+0x34/0xf0)
|
||||
[ 512.746457] [<c0442668>] (force_sig_info+0x18/0x1c)
|
||||
[ 512.746829] [<c041d880>] (__do_user_fault+0x9c/0xd8)
|
||||
[ 512.747185] [<c041d938>] (do_bad_area+0x7c/0x94)
|
||||
[ 512.747536] [<c041d990>] (do_sect_fault+0x40/0x48)
|
||||
[ 512.747898] [<c040841c>] (do_DataAbort+0x40/0xa0)
|
||||
[ 512.748181] Exception stack(0xecaa1fb0 to 0xecaa1ff8)
|
||||
|
||||
Oxc0000000 belongs to kernel address space, user task can not be
|
||||
allowed to access it. For above condition, correct result is that
|
||||
test case should receive a “segment fault” and exits but not stacks.
|
||||
|
||||
the root cause is commit 02fe2845d6a8 ("avoid enabling interrupts in
|
||||
prefetch/data abort handlers"),it deletes irq enable block in Data
|
||||
abort assemble code and move them into page/breakpiont/alignment fault
|
||||
handlers instead. But author does not enable irq in translation/section
|
||||
permission fault handlers. ARM disables irq when it enters exception/
|
||||
interrupt mode, if kernel doesn't enable irq, it would be still disabled
|
||||
during translation/section permission fault.
|
||||
|
||||
We see the above splat because do_force_sig_info is still called with
|
||||
IRQs off, and that code eventually does a:
|
||||
|
||||
spin_lock_irqsave(&t->sighand->siglock, flags);
|
||||
|
||||
As this is architecture independent code, and we've not seen any other
|
||||
need for other arch to have the siglock converted to raw lock, we can
|
||||
conclude that we should enable irq for ARM translation/section
|
||||
permission exception.
|
||||
|
||||
|
||||
Signed-off-by: Yadi.hu <yadi.hu@windriver.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/mm/fault.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/arch/arm/mm/fault.c
|
||||
+++ b/arch/arm/mm/fault.c
|
||||
@@ -430,6 +430,9 @@ do_translation_fault(unsigned long addr,
|
||||
if (addr < TASK_SIZE)
|
||||
return do_page_fault(addr, fsr, regs);
|
||||
|
||||
+ if (interrupts_enabled(regs))
|
||||
+ local_irq_enable();
|
||||
+
|
||||
if (user_mode(regs))
|
||||
goto bad_area;
|
||||
|
||||
@@ -497,6 +500,9 @@ do_translation_fault(unsigned long addr,
|
||||
static int
|
||||
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
{
|
||||
+ if (interrupts_enabled(regs))
|
||||
+ local_irq_enable();
|
||||
+
|
||||
do_bad_area(addr, fsr, regs);
|
||||
return 0;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 21 Mar 2013 19:01:05 +0100
|
||||
Subject: printk: Drop the logbuf_lock more often
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The lock is hold with irgs off. The latency drops 500us+ on my arm bugs
|
||||
with a "full" buffer after executing "dmesg" on the shell.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/printk/printk.c | 27 ++++++++++++++++++++++++++-
|
||||
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/printk/printk.c
|
||||
+++ b/kernel/printk/printk.c
|
||||
@@ -1262,6 +1262,7 @@ static int syslog_print_all(char __user
|
||||
{
|
||||
char *text;
|
||||
int len = 0;
|
||||
+ int attempts = 0;
|
||||
|
||||
text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
|
||||
if (!text)
|
||||
@@ -1273,7 +1274,14 @@ static int syslog_print_all(char __user
|
||||
u64 seq;
|
||||
u32 idx;
|
||||
enum log_flags prev;
|
||||
-
|
||||
+ int num_msg;
|
||||
+try_again:
|
||||
+ attempts++;
|
||||
+ if (attempts > 10) {
|
||||
+ len = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ num_msg = 0;
|
||||
if (clear_seq < log_first_seq) {
|
||||
/* messages are gone, move to first available one */
|
||||
clear_seq = log_first_seq;
|
||||
@@ -1294,6 +1302,14 @@ static int syslog_print_all(char __user
|
||||
prev = msg->flags;
|
||||
idx = log_next(idx);
|
||||
seq++;
|
||||
+ num_msg++;
|
||||
+ if (num_msg > 5) {
|
||||
+ num_msg = 0;
|
||||
+ raw_spin_unlock_irq(&logbuf_lock);
|
||||
+ raw_spin_lock_irq(&logbuf_lock);
|
||||
+ if (clear_seq < log_first_seq)
|
||||
+ goto try_again;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* move first record forward until length fits into the buffer */
|
||||
@@ -1307,6 +1323,14 @@ static int syslog_print_all(char __user
|
||||
prev = msg->flags;
|
||||
idx = log_next(idx);
|
||||
seq++;
|
||||
+ num_msg++;
|
||||
+ if (num_msg > 5) {
|
||||
+ num_msg = 0;
|
||||
+ raw_spin_unlock_irq(&logbuf_lock);
|
||||
+ raw_spin_lock_irq(&logbuf_lock);
|
||||
+ if (clear_seq < log_first_seq)
|
||||
+ goto try_again;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* last message fitting into this dump */
|
||||
@@ -1347,6 +1371,7 @@ static int syslog_print_all(char __user
|
||||
clear_seq = log_next_seq;
|
||||
clear_idx = log_next_idx;
|
||||
}
|
||||
+out:
|
||||
raw_spin_unlock_irq(&logbuf_lock);
|
||||
|
||||
kfree(text);
|
|
@ -1,26 +0,0 @@
|
|||
From: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Date: Wed, 8 Apr 2015 20:33:25 -0300
|
||||
Subject: KVM: lapic: mark LAPIC timer handler as irqsafe
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Since lapic timer handler only wakes up a simple waitqueue,
|
||||
it can be executed from hardirq context.
|
||||
|
||||
Reduces average cyclictest latency by 3us.
|
||||
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/x86/kvm/lapic.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/x86/kvm/lapic.c
|
||||
+++ b/arch/x86/kvm/lapic.c
|
||||
@@ -1801,6 +1801,7 @@ int kvm_create_lapic(struct kvm_vcpu *vc
|
||||
hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
|
||||
HRTIMER_MODE_ABS);
|
||||
apic->lapic_timer.timer.function = apic_timer_fn;
|
||||
+ apic->lapic_timer.timer.irqsafe = 1;
|
||||
|
||||
/*
|
||||
* APIC is created enabled. This will prevent kvm_lapic_set_base from
|
|
@ -1,335 +0,0 @@
|
|||
From: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Date: Wed, 8 Apr 2015 20:33:24 -0300
|
||||
Subject: KVM: use simple waitqueue for vcpu->wq
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The problem:
|
||||
|
||||
On -RT, an emulated LAPIC timer instances has the following path:
|
||||
|
||||
1) hard interrupt
|
||||
2) ksoftirqd is scheduled
|
||||
3) ksoftirqd wakes up vcpu thread
|
||||
4) vcpu thread is scheduled
|
||||
|
||||
This extra context switch introduces unnecessary latency in the
|
||||
LAPIC path for a KVM guest.
|
||||
|
||||
The solution:
|
||||
|
||||
Allow waking up vcpu thread from hardirq context,
|
||||
thus avoiding the need for ksoftirqd to be scheduled.
|
||||
|
||||
Normal waitqueues make use of spinlocks, which on -RT
|
||||
are sleepable locks. Therefore, waking up a waitqueue
|
||||
waiter involves locking a sleeping lock, which
|
||||
is not allowed from hard interrupt context.
|
||||
|
||||
cyclictest command line:
|
||||
# cyclictest -m -n -q -p99 -l 1000000 -h60 -D 1m
|
||||
|
||||
This patch reduces the average latency in my tests from 14us to 11us.
|
||||
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/kvm/arm.c | 8 ++++----
|
||||
arch/arm/kvm/psci.c | 4 ++--
|
||||
arch/powerpc/include/asm/kvm_host.h | 4 ++--
|
||||
arch/powerpc/kvm/book3s_hv.c | 23 +++++++++++------------
|
||||
arch/s390/include/asm/kvm_host.h | 2 +-
|
||||
arch/s390/kvm/interrupt.c | 4 ++--
|
||||
arch/x86/kvm/lapic.c | 6 +++---
|
||||
include/linux/kvm_host.h | 4 ++--
|
||||
virt/kvm/async_pf.c | 4 ++--
|
||||
virt/kvm/kvm_main.c | 16 ++++++++--------
|
||||
10 files changed, 37 insertions(+), 38 deletions(-)
|
||||
|
||||
--- a/arch/arm/kvm/arm.c
|
||||
+++ b/arch/arm/kvm/arm.c
|
||||
@@ -498,18 +498,18 @@ static void kvm_arm_resume_guest(struct
|
||||
struct kvm_vcpu *vcpu;
|
||||
|
||||
kvm_for_each_vcpu(i, vcpu, kvm) {
|
||||
- wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
|
||||
+ struct swait_head *wq = kvm_arch_vcpu_wq(vcpu);
|
||||
|
||||
vcpu->arch.pause = false;
|
||||
- wake_up_interruptible(wq);
|
||||
+ swait_wake_interruptible(wq);
|
||||
}
|
||||
}
|
||||
|
||||
static void vcpu_sleep(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
- wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
|
||||
+ struct swait_head *wq = kvm_arch_vcpu_wq(vcpu);
|
||||
|
||||
- wait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
|
||||
+ swait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
|
||||
(!vcpu->arch.pause)));
|
||||
}
|
||||
|
||||
--- a/arch/arm/kvm/psci.c
|
||||
+++ b/arch/arm/kvm/psci.c
|
||||
@@ -70,7 +70,7 @@ static unsigned long kvm_psci_vcpu_on(st
|
||||
{
|
||||
struct kvm *kvm = source_vcpu->kvm;
|
||||
struct kvm_vcpu *vcpu = NULL;
|
||||
- wait_queue_head_t *wq;
|
||||
+ struct swait_head *wq;
|
||||
unsigned long cpu_id;
|
||||
unsigned long context_id;
|
||||
phys_addr_t target_pc;
|
||||
@@ -119,7 +119,7 @@ static unsigned long kvm_psci_vcpu_on(st
|
||||
smp_mb(); /* Make sure the above is visible */
|
||||
|
||||
wq = kvm_arch_vcpu_wq(vcpu);
|
||||
- wake_up_interruptible(wq);
|
||||
+ swait_wake_interruptible(wq);
|
||||
|
||||
return PSCI_RET_SUCCESS;
|
||||
}
|
||||
--- a/arch/powerpc/include/asm/kvm_host.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_host.h
|
||||
@@ -286,7 +286,7 @@ struct kvmppc_vcore {
|
||||
struct list_head runnable_threads;
|
||||
struct list_head preempt_list;
|
||||
spinlock_t lock;
|
||||
- wait_queue_head_t wq;
|
||||
+ struct swait_head wq;
|
||||
spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */
|
||||
u64 stolen_tb;
|
||||
u64 preempt_tb;
|
||||
@@ -626,7 +626,7 @@ struct kvm_vcpu_arch {
|
||||
u8 prodded;
|
||||
u32 last_inst;
|
||||
|
||||
- wait_queue_head_t *wqp;
|
||||
+ struct swait_head *wqp;
|
||||
struct kvmppc_vcore *vcore;
|
||||
int ret;
|
||||
int trap;
|
||||
--- a/arch/powerpc/kvm/book3s_hv.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv.c
|
||||
@@ -114,11 +114,11 @@ static bool kvmppc_ipi_thread(int cpu)
|
||||
static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int cpu;
|
||||
- wait_queue_head_t *wqp;
|
||||
+ struct swait_head *wqp;
|
||||
|
||||
wqp = kvm_arch_vcpu_wq(vcpu);
|
||||
- if (waitqueue_active(wqp)) {
|
||||
- wake_up_interruptible(wqp);
|
||||
+ if (swaitqueue_active(wqp)) {
|
||||
+ swait_wake_interruptible(wqp);
|
||||
++vcpu->stat.halt_wakeup;
|
||||
}
|
||||
|
||||
@@ -707,8 +707,8 @@ int kvmppc_pseries_do_hcall(struct kvm_v
|
||||
tvcpu->arch.prodded = 1;
|
||||
smp_mb();
|
||||
if (vcpu->arch.ceded) {
|
||||
- if (waitqueue_active(&vcpu->wq)) {
|
||||
- wake_up_interruptible(&vcpu->wq);
|
||||
+ if (swaitqueue_active(&vcpu->wq)) {
|
||||
+ swait_wake_interruptible(&vcpu->wq);
|
||||
vcpu->stat.halt_wakeup++;
|
||||
}
|
||||
}
|
||||
@@ -1447,7 +1447,7 @@ static struct kvmppc_vcore *kvmppc_vcore
|
||||
INIT_LIST_HEAD(&vcore->runnable_threads);
|
||||
spin_lock_init(&vcore->lock);
|
||||
spin_lock_init(&vcore->stoltb_lock);
|
||||
- init_waitqueue_head(&vcore->wq);
|
||||
+ init_swait_head(&vcore->wq);
|
||||
vcore->preempt_tb = TB_NIL;
|
||||
vcore->lpcr = kvm->arch.lpcr;
|
||||
vcore->first_vcpuid = core * threads_per_subcore;
|
||||
@@ -2519,10 +2519,9 @@ static void kvmppc_vcore_blocked(struct
|
||||
{
|
||||
struct kvm_vcpu *vcpu;
|
||||
int do_sleep = 1;
|
||||
+ DEFINE_SWAITER(wait);
|
||||
|
||||
- DEFINE_WAIT(wait);
|
||||
-
|
||||
- prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
|
||||
+ swait_prepare(&vc->wq, &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
/*
|
||||
* Check one last time for pending exceptions and ceded state after
|
||||
@@ -2536,7 +2535,7 @@ static void kvmppc_vcore_blocked(struct
|
||||
}
|
||||
|
||||
if (!do_sleep) {
|
||||
- finish_wait(&vc->wq, &wait);
|
||||
+ swait_finish(&vc->wq, &wait);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2544,7 +2543,7 @@ static void kvmppc_vcore_blocked(struct
|
||||
trace_kvmppc_vcore_blocked(vc, 0);
|
||||
spin_unlock(&vc->lock);
|
||||
schedule();
|
||||
- finish_wait(&vc->wq, &wait);
|
||||
+ swait_finish(&vc->wq, &wait);
|
||||
spin_lock(&vc->lock);
|
||||
vc->vcore_state = VCORE_INACTIVE;
|
||||
trace_kvmppc_vcore_blocked(vc, 1);
|
||||
@@ -2600,7 +2599,7 @@ static int kvmppc_run_vcpu(struct kvm_ru
|
||||
kvmppc_start_thread(vcpu, vc);
|
||||
trace_kvm_guest_enter(vcpu);
|
||||
} else if (vc->vcore_state == VCORE_SLEEPING) {
|
||||
- wake_up(&vc->wq);
|
||||
+ swait_wake(&vc->wq);
|
||||
}
|
||||
|
||||
}
|
||||
--- a/arch/s390/include/asm/kvm_host.h
|
||||
+++ b/arch/s390/include/asm/kvm_host.h
|
||||
@@ -427,7 +427,7 @@ struct kvm_s390_irq_payload {
|
||||
struct kvm_s390_local_interrupt {
|
||||
spinlock_t lock;
|
||||
struct kvm_s390_float_interrupt *float_int;
|
||||
- wait_queue_head_t *wq;
|
||||
+ struct swait_head *wq;
|
||||
atomic_t *cpuflags;
|
||||
DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS);
|
||||
struct kvm_s390_irq_payload irq;
|
||||
--- a/arch/s390/kvm/interrupt.c
|
||||
+++ b/arch/s390/kvm/interrupt.c
|
||||
@@ -868,13 +868,13 @@ int kvm_s390_handle_wait(struct kvm_vcpu
|
||||
|
||||
void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
- if (waitqueue_active(&vcpu->wq)) {
|
||||
+ if (swaitqueue_active(&vcpu->wq)) {
|
||||
/*
|
||||
* The vcpu gave up the cpu voluntarily, mark it as a good
|
||||
* yield-candidate.
|
||||
*/
|
||||
vcpu->preempted = true;
|
||||
- wake_up_interruptible(&vcpu->wq);
|
||||
+ swait_wake_interruptible(&vcpu->wq);
|
||||
vcpu->stat.halt_wakeup++;
|
||||
}
|
||||
}
|
||||
--- a/arch/x86/kvm/lapic.c
|
||||
+++ b/arch/x86/kvm/lapic.c
|
||||
@@ -1195,7 +1195,7 @@ static void apic_update_lvtt(struct kvm_
|
||||
static void apic_timer_expired(struct kvm_lapic *apic)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = apic->vcpu;
|
||||
- wait_queue_head_t *q = &vcpu->wq;
|
||||
+ struct swait_head *q = &vcpu->wq;
|
||||
struct kvm_timer *ktimer = &apic->lapic_timer;
|
||||
|
||||
if (atomic_read(&apic->lapic_timer.pending))
|
||||
@@ -1204,8 +1204,8 @@ static void apic_timer_expired(struct kv
|
||||
atomic_inc(&apic->lapic_timer.pending);
|
||||
kvm_set_pending_timer(vcpu);
|
||||
|
||||
- if (waitqueue_active(q))
|
||||
- wake_up_interruptible(q);
|
||||
+ if (swaitqueue_active(q))
|
||||
+ swait_wake_interruptible(q);
|
||||
|
||||
if (apic_lvtt_tscdeadline(apic))
|
||||
ktimer->expired_tscdeadline = ktimer->tscdeadline;
|
||||
--- a/include/linux/kvm_host.h
|
||||
+++ b/include/linux/kvm_host.h
|
||||
@@ -243,7 +243,7 @@ struct kvm_vcpu {
|
||||
int fpu_active;
|
||||
int guest_fpu_loaded, guest_xcr0_loaded;
|
||||
unsigned char fpu_counter;
|
||||
- wait_queue_head_t wq;
|
||||
+ struct swait_head wq;
|
||||
struct pid *pid;
|
||||
int sigset_active;
|
||||
sigset_t sigset;
|
||||
@@ -794,7 +794,7 @@ static inline bool kvm_arch_has_assigned
|
||||
}
|
||||
#endif
|
||||
|
||||
-static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
|
||||
+static inline struct swait_head *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
#ifdef __KVM_HAVE_ARCH_WQP
|
||||
return vcpu->arch.wqp;
|
||||
--- a/virt/kvm/async_pf.c
|
||||
+++ b/virt/kvm/async_pf.c
|
||||
@@ -98,8 +98,8 @@ static void async_pf_execute(struct work
|
||||
* This memory barrier pairs with prepare_to_wait's set_current_state()
|
||||
*/
|
||||
smp_mb();
|
||||
- if (waitqueue_active(&vcpu->wq))
|
||||
- wake_up_interruptible(&vcpu->wq);
|
||||
+ if (swaitqueue_active(&vcpu->wq))
|
||||
+ swait_wake_interruptible(&vcpu->wq);
|
||||
|
||||
mmput(mm);
|
||||
kvm_put_kvm(vcpu->kvm);
|
||||
--- a/virt/kvm/kvm_main.c
|
||||
+++ b/virt/kvm/kvm_main.c
|
||||
@@ -227,7 +227,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu,
|
||||
vcpu->vcpu_id = id;
|
||||
vcpu->pid = NULL;
|
||||
vcpu->halt_poll_ns = 0;
|
||||
- init_waitqueue_head(&vcpu->wq);
|
||||
+ init_swait_head(&vcpu->wq);
|
||||
kvm_async_pf_vcpu_init(vcpu);
|
||||
|
||||
vcpu->pre_pcpu = -1;
|
||||
@@ -1999,7 +1999,7 @@ static int kvm_vcpu_check_block(struct k
|
||||
void kvm_vcpu_block(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
ktime_t start, cur;
|
||||
- DEFINE_WAIT(wait);
|
||||
+ DEFINE_SWAITER(wait);
|
||||
bool waited = false;
|
||||
u64 block_ns;
|
||||
|
||||
@@ -2024,7 +2024,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp
|
||||
kvm_arch_vcpu_blocking(vcpu);
|
||||
|
||||
for (;;) {
|
||||
- prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
|
||||
+ swait_prepare(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
if (kvm_vcpu_check_block(vcpu) < 0)
|
||||
break;
|
||||
@@ -2033,7 +2033,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp
|
||||
schedule();
|
||||
}
|
||||
|
||||
- finish_wait(&vcpu->wq, &wait);
|
||||
+ swait_finish(&vcpu->wq, &wait);
|
||||
cur = ktime_get();
|
||||
|
||||
kvm_arch_vcpu_unblocking(vcpu);
|
||||
@@ -2065,11 +2065,11 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu
|
||||
{
|
||||
int me;
|
||||
int cpu = vcpu->cpu;
|
||||
- wait_queue_head_t *wqp;
|
||||
+ struct swait_head *wqp;
|
||||
|
||||
wqp = kvm_arch_vcpu_wq(vcpu);
|
||||
- if (waitqueue_active(wqp)) {
|
||||
- wake_up_interruptible(wqp);
|
||||
+ if (swaitqueue_active(wqp)) {
|
||||
+ swait_wake_interruptible(wqp);
|
||||
++vcpu->stat.halt_wakeup;
|
||||
}
|
||||
|
||||
@@ -2170,7 +2170,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *m
|
||||
continue;
|
||||
if (vcpu == me)
|
||||
continue;
|
||||
- if (waitqueue_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
|
||||
+ if (swaitqueue_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
|
||||
continue;
|
||||
if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
|
||||
continue;
|
|
@ -1,174 +0,0 @@
|
|||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Wed, 13 Feb 2013 09:26:05 -0500
|
||||
Subject: acpi/rt: Convert acpi_gbl_hardware lock back to a raw_spinlock_t
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
We hit the following bug with 3.6-rt:
|
||||
|
||||
[ 5.898990] BUG: scheduling while atomic: swapper/3/0/0x00000002
|
||||
[ 5.898991] no locks held by swapper/3/0.
|
||||
[ 5.898993] Modules linked in:
|
||||
[ 5.898996] Pid: 0, comm: swapper/3 Not tainted 3.6.11-rt28.19.el6rt.x86_64.debug #1
|
||||
[ 5.898997] Call Trace:
|
||||
[ 5.899011] [<ffffffff810804e7>] __schedule_bug+0x67/0x90
|
||||
[ 5.899028] [<ffffffff81577923>] __schedule+0x793/0x7a0
|
||||
[ 5.899032] [<ffffffff810b4e40>] ? debug_rt_mutex_print_deadlock+0x50/0x200
|
||||
[ 5.899034] [<ffffffff81577b89>] schedule+0x29/0x70
|
||||
[ 5.899036] BUG: scheduling while atomic: swapper/7/0/0x00000002
|
||||
[ 5.899037] no locks held by swapper/7/0.
|
||||
[ 5.899039] [<ffffffff81578525>] rt_spin_lock_slowlock+0xe5/0x2f0
|
||||
[ 5.899040] Modules linked in:
|
||||
[ 5.899041]
|
||||
[ 5.899045] [<ffffffff81579a58>] ? _raw_spin_unlock_irqrestore+0x38/0x90
|
||||
[ 5.899046] Pid: 0, comm: swapper/7 Not tainted 3.6.11-rt28.19.el6rt.x86_64.debug #1
|
||||
[ 5.899047] Call Trace:
|
||||
[ 5.899049] [<ffffffff81578bc6>] rt_spin_lock+0x16/0x40
|
||||
[ 5.899052] [<ffffffff810804e7>] __schedule_bug+0x67/0x90
|
||||
[ 5.899054] [<ffffffff8157d3f0>] ? notifier_call_chain+0x80/0x80
|
||||
[ 5.899056] [<ffffffff81577923>] __schedule+0x793/0x7a0
|
||||
[ 5.899059] [<ffffffff812f2034>] acpi_os_acquire_lock+0x1f/0x23
|
||||
[ 5.899062] [<ffffffff810b4e40>] ? debug_rt_mutex_print_deadlock+0x50/0x200
|
||||
[ 5.899068] [<ffffffff8130be64>] acpi_write_bit_register+0x33/0xb0
|
||||
[ 5.899071] [<ffffffff81577b89>] schedule+0x29/0x70
|
||||
[ 5.899072] [<ffffffff8130be13>] ? acpi_read_bit_register+0x33/0x51
|
||||
[ 5.899074] [<ffffffff81578525>] rt_spin_lock_slowlock+0xe5/0x2f0
|
||||
[ 5.899077] [<ffffffff8131d1fc>] acpi_idle_enter_bm+0x8a/0x28e
|
||||
[ 5.899079] [<ffffffff81579a58>] ? _raw_spin_unlock_irqrestore+0x38/0x90
|
||||
[ 5.899081] [<ffffffff8107e5da>] ? this_cpu_load+0x1a/0x30
|
||||
[ 5.899083] [<ffffffff81578bc6>] rt_spin_lock+0x16/0x40
|
||||
[ 5.899087] [<ffffffff8144c759>] cpuidle_enter+0x19/0x20
|
||||
[ 5.899088] [<ffffffff8157d3f0>] ? notifier_call_chain+0x80/0x80
|
||||
[ 5.899090] [<ffffffff8144c777>] cpuidle_enter_state+0x17/0x50
|
||||
[ 5.899092] [<ffffffff812f2034>] acpi_os_acquire_lock+0x1f/0x23
|
||||
[ 5.899094] [<ffffffff8144d1a1>] cpuidle899101] [<ffffffff8130be13>] ?
|
||||
|
||||
As the acpi code disables interrupts in acpi_idle_enter_bm, and calls
|
||||
code that grabs the acpi lock, it causes issues as the lock is currently
|
||||
in RT a sleeping lock.
|
||||
|
||||
The lock was converted from a raw to a sleeping lock due to some
|
||||
previous issues, and tests that showed it didn't seem to matter.
|
||||
Unfortunately, it did matter for one of our boxes.
|
||||
|
||||
This patch converts the lock back to a raw lock. I've run this code on a
|
||||
few of my own machines, one being my laptop that uses the acpi quite
|
||||
extensively. I've been able to suspend and resume without issues.
|
||||
|
||||
[ tglx: Made the change exclusive for acpi_gbl_hardware_lock ]
|
||||
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Cc: John Kacur <jkacur@gmail.com>
|
||||
Cc: Clark Williams <clark@redhat.com>
|
||||
Link: http://lkml.kernel.org/r/1360765565.23152.5.camel@gandalf.local.home
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/acpi/acpica/acglobal.h | 2 +-
|
||||
drivers/acpi/acpica/hwregs.c | 4 ++--
|
||||
drivers/acpi/acpica/hwxface.c | 4 ++--
|
||||
drivers/acpi/acpica/utmutex.c | 4 ++--
|
||||
include/acpi/platform/aclinux.h | 15 +++++++++++++++
|
||||
5 files changed, 22 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/acpi/acpica/acglobal.h
|
||||
+++ b/drivers/acpi/acpica/acglobal.h
|
||||
@@ -116,7 +116,7 @@ ACPI_GLOBAL(u8, acpi_gbl_global_lock_pen
|
||||
* interrupt level
|
||||
*/
|
||||
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */
|
||||
-ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||||
+ACPI_GLOBAL(acpi_raw_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
|
||||
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock);
|
||||
|
||||
/* Mutex for _OSI support */
|
||||
--- a/drivers/acpi/acpica/hwregs.c
|
||||
+++ b/drivers/acpi/acpica/hwregs.c
|
||||
@@ -269,14 +269,14 @@ acpi_status acpi_hw_clear_acpi_status(vo
|
||||
ACPI_BITMASK_ALL_FIXED_STATUS,
|
||||
ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
|
||||
|
||||
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||||
+ raw_spin_lock_irqsave(acpi_gbl_hardware_lock, lock_flags);
|
||||
|
||||
/* Clear the fixed events in PM1 A/B */
|
||||
|
||||
status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
|
||||
ACPI_BITMASK_ALL_FIXED_STATUS);
|
||||
|
||||
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
+ raw_spin_unlock_irqrestore(acpi_gbl_hardware_lock, lock_flags);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
--- a/drivers/acpi/acpica/hwxface.c
|
||||
+++ b/drivers/acpi/acpica/hwxface.c
|
||||
@@ -374,7 +374,7 @@ acpi_status acpi_write_bit_register(u32
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
|
||||
+ raw_spin_lock_irqsave(acpi_gbl_hardware_lock, lock_flags);
|
||||
|
||||
/*
|
||||
* At this point, we know that the parent register is one of the
|
||||
@@ -435,7 +435,7 @@ acpi_status acpi_write_bit_register(u32
|
||||
|
||||
unlock_and_exit:
|
||||
|
||||
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
|
||||
+ raw_spin_unlock_irqrestore(acpi_gbl_hardware_lock, lock_flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
--- a/drivers/acpi/acpica/utmutex.c
|
||||
+++ b/drivers/acpi/acpica/utmutex.c
|
||||
@@ -88,7 +88,7 @@ acpi_status acpi_ut_mutex_initialize(voi
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
- status = acpi_os_create_lock (&acpi_gbl_hardware_lock);
|
||||
+ status = acpi_os_create_raw_lock (&acpi_gbl_hardware_lock);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ void acpi_ut_mutex_terminate(void)
|
||||
/* Delete the spinlocks */
|
||||
|
||||
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
||||
- acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
||||
+ acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
|
||||
acpi_os_delete_lock(acpi_gbl_reference_count_lock);
|
||||
|
||||
/* Delete the reader/writer lock */
|
||||
--- a/include/acpi/platform/aclinux.h
|
||||
+++ b/include/acpi/platform/aclinux.h
|
||||
@@ -127,6 +127,7 @@
|
||||
|
||||
#define acpi_cache_t struct kmem_cache
|
||||
#define acpi_spinlock spinlock_t *
|
||||
+#define acpi_raw_spinlock raw_spinlock_t *
|
||||
#define acpi_cpu_flags unsigned long
|
||||
|
||||
/* Use native linux version of acpi_os_allocate_zeroed */
|
||||
@@ -145,6 +146,20 @@
|
||||
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id
|
||||
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock
|
||||
|
||||
+#define acpi_os_create_raw_lock(__handle) \
|
||||
+({ \
|
||||
+ raw_spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
|
||||
+ \
|
||||
+ if (lock) { \
|
||||
+ *(__handle) = lock; \
|
||||
+ raw_spin_lock_init(*(__handle)); \
|
||||
+ } \
|
||||
+ lock ? AE_OK : AE_NO_MEMORY; \
|
||||
+ })
|
||||
+
|
||||
+#define acpi_os_delete_raw_lock(__handle) kfree(__handle)
|
||||
+
|
||||
+
|
||||
/*
|
||||
* OSL interfaces used by debugger/disassembler
|
||||
*/
|
|
@ -1,104 +0,0 @@
|
|||
From: Anders Roxell <anders.roxell@linaro.org>
|
||||
Date: Thu, 14 May 2015 17:52:17 +0200
|
||||
Subject: arch/arm64: Add lazy preempt support
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
arm64 is missing support for PREEMPT_RT. The main feature which is
|
||||
lacking is support for lazy preemption. The arch-specific entry code,
|
||||
thread information structure definitions, and associated data tables
|
||||
have to be extended to provide this support. Then the Kconfig file has
|
||||
to be extended to indicate the support is available, and also to
|
||||
indicate that support for full RT preemption is now available.
|
||||
|
||||
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
|
||||
---
|
||||
arch/arm64/Kconfig | 1 +
|
||||
arch/arm64/include/asm/thread_info.h | 3 +++
|
||||
arch/arm64/kernel/asm-offsets.c | 1 +
|
||||
arch/arm64/kernel/entry.S | 13 ++++++++++---
|
||||
4 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/arm64/Kconfig
|
||||
+++ b/arch/arm64/Kconfig
|
||||
@@ -76,6 +76,7 @@ config ARM64
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_RCU_TABLE_FREE
|
||||
+ select HAVE_PREEMPT_LAZY
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select IOMMU_DMA if IOMMU_SUPPORT
|
||||
select IRQ_DOMAIN
|
||||
--- a/arch/arm64/include/asm/thread_info.h
|
||||
+++ b/arch/arm64/include/asm/thread_info.h
|
||||
@@ -49,6 +49,7 @@ struct thread_info {
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
struct task_struct *task; /* main task structure */
|
||||
int preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
|
||||
int cpu; /* cpu */
|
||||
};
|
||||
|
||||
@@ -103,6 +104,7 @@ static inline struct thread_info *curren
|
||||
#define TIF_NEED_RESCHED 1
|
||||
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
||||
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
|
||||
+#define TIF_NEED_RESCHED_LAZY 4
|
||||
#define TIF_NOHZ 7
|
||||
#define TIF_SYSCALL_TRACE 8
|
||||
#define TIF_SYSCALL_AUDIT 9
|
||||
@@ -118,6 +120,7 @@ static inline struct thread_info *curren
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
#define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
|
||||
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
|
||||
#define _TIF_NOHZ (1 << TIF_NOHZ)
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
--- a/arch/arm64/kernel/asm-offsets.c
|
||||
+++ b/arch/arm64/kernel/asm-offsets.c
|
||||
@@ -35,6 +35,7 @@ int main(void)
|
||||
BLANK();
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
|
||||
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
--- a/arch/arm64/kernel/entry.S
|
||||
+++ b/arch/arm64/kernel/entry.S
|
||||
@@ -363,11 +363,16 @@ ENDPROC(el1_sync)
|
||||
#ifdef CONFIG_PREEMPT
|
||||
get_thread_info tsk
|
||||
ldr w24, [tsk, #TI_PREEMPT] // get preempt count
|
||||
- cbnz w24, 1f // preempt count != 0
|
||||
+ cbnz w24, 2f // preempt count != 0
|
||||
ldr x0, [tsk, #TI_FLAGS] // get flags
|
||||
- tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
|
||||
- bl el1_preempt
|
||||
+ tbnz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
|
||||
+
|
||||
+ ldr w24, [tsk, #TI_PREEMPT_LAZY] // get preempt lazy count
|
||||
+ cbnz w24, 2f // preempt lazy count != 0
|
||||
+ tbz x0, #TIF_NEED_RESCHED_LAZY, 2f // needs rescheduling?
|
||||
1:
|
||||
+ bl el1_preempt
|
||||
+2:
|
||||
#endif
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
bl trace_hardirqs_on
|
||||
@@ -381,6 +386,7 @@ ENDPROC(el1_irq)
|
||||
1: bl preempt_schedule_irq // irq en/disable is done inside
|
||||
ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS
|
||||
tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling?
|
||||
+ tbnz x0, #TIF_NEED_RESCHED_LAZY, 1b // needs rescheduling?
|
||||
ret x24
|
||||
#endif
|
||||
|
||||
@@ -625,6 +631,7 @@ ENDPROC(cpu_switch_to)
|
||||
*/
|
||||
work_pending:
|
||||
tbnz x1, #TIF_NEED_RESCHED, work_resched
|
||||
+ tbnz x1, #TIF_NEED_RESCHED_LAZY, work_resched
|
||||
/* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
|
||||
ldr x2, [sp, #S_PSTATE]
|
||||
mov x0, sp // 'regs'
|
|
@ -1,77 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 22 Jan 2016 21:33:39 +0100
|
||||
Subject: arm+arm64: lazy-preempt: add TIF_NEED_RESCHED_LAZY to _TIF_WORK_MASK
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
_TIF_WORK_MASK is used to check for TIF_NEED_RESCHED so we need to check
|
||||
for TIF_NEED_RESCHED_LAZY here, too.
|
||||
|
||||
Reported-by: Grygorii Strashko <grygorii.strashko@ti.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/include/asm/thread_info.h | 7 ++++---
|
||||
arch/arm/kernel/entry-common.S | 9 +++++++--
|
||||
arch/arm64/include/asm/thread_info.h | 3 ++-
|
||||
3 files changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/thread_info.h
|
||||
+++ b/arch/arm/include/asm/thread_info.h
|
||||
@@ -143,8 +143,8 @@ extern int vfp_restore_user_hwstate(stru
|
||||
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
|
||||
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||
-#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
|
||||
-#define TIF_NEED_RESCHED_LAZY 8
|
||||
+#define TIF_SECCOMP 8 /* seccomp syscall filtering active */
|
||||
+#define TIF_NEED_RESCHED_LAZY 7
|
||||
|
||||
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
||||
#define TIF_USING_IWMMXT 17
|
||||
@@ -170,7 +170,8 @@ extern int vfp_restore_user_hwstate(stru
|
||||
* Change these and you break ASM code in entry-common.S
|
||||
*/
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||
- _TIF_NOTIFY_RESUME | _TIF_UPROBE)
|
||||
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
||||
+ _TIF_NEED_RESCHED_LAZY)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_ARM_THREAD_INFO_H */
|
||||
--- a/arch/arm/kernel/entry-common.S
|
||||
+++ b/arch/arm/kernel/entry-common.S
|
||||
@@ -36,7 +36,9 @@
|
||||
UNWIND(.cantunwind )
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
|
||||
+ bne fast_work_pending
|
||||
+ tst r1, #_TIF_SECCOMP
|
||||
bne fast_work_pending
|
||||
|
||||
/* perform architecture specific actions before user return */
|
||||
@@ -62,8 +64,11 @@ ENDPROC(ret_fast_syscall)
|
||||
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
|
||||
+ bne do_slower_path
|
||||
+ tst r1, #_TIF_SECCOMP
|
||||
beq no_work_pending
|
||||
+do_slower_path:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(ret_fast_syscall)
|
||||
|
||||
--- a/arch/arm64/include/asm/thread_info.h
|
||||
+++ b/arch/arm64/include/asm/thread_info.h
|
||||
@@ -129,7 +129,8 @@ static inline struct thread_info *curren
|
||||
#define _TIF_32BIT (1 << TIF_32BIT)
|
||||
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||
- _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
|
||||
+ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
|
||||
+ _TIF_NEED_RESCHED_LAZY)
|
||||
|
||||
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
|
||||
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
|
|
@ -1,147 +0,0 @@
|
|||
From: Benedikt Spranger <b.spranger@linutronix.de>
|
||||
Date: Sat, 6 Mar 2010 17:47:10 +0100
|
||||
Subject: ARM: AT91: PIT: Remove irq handler when clock event is unused
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Setup and remove the interrupt handler in clock event mode selection.
|
||||
This avoids calling the (shared) interrupt handler when the device is
|
||||
not used.
|
||||
|
||||
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
[bigeasy: redo the patch with NR_IRQS_LEGACY which is probably required since
|
||||
commit 8fe82a55 ("ARM: at91: sparse irq support") which is included since v3.6.
|
||||
Patch based on what Sami Pietikäinen <Sami.Pietikainen@wapice.com> suggested].
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/clocksource/timer-atmel-pit.c | 17 +++++++++--------
|
||||
drivers/clocksource/timer-atmel-st.c | 32 ++++++++++++++++++++++----------
|
||||
2 files changed, 31 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/clocksource/timer-atmel-pit.c
|
||||
+++ b/drivers/clocksource/timer-atmel-pit.c
|
||||
@@ -96,15 +96,24 @@ static int pit_clkevt_shutdown(struct cl
|
||||
|
||||
/* disable irq, leaving the clocksource active */
|
||||
pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN);
|
||||
+ free_irq(data->irq, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id);
|
||||
/*
|
||||
* Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
|
||||
*/
|
||||
static int pit_clkevt_set_periodic(struct clock_event_device *dev)
|
||||
{
|
||||
struct pit_data *data = clkevt_to_pit_data(dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = request_irq(data->irq, at91sam926x_pit_interrupt,
|
||||
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
+ "at91_tick", data);
|
||||
+ if (ret)
|
||||
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||||
|
||||
/* update clocksource counter */
|
||||
data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
|
||||
@@ -181,7 +190,6 @@ static void __init at91sam926x_pit_commo
|
||||
{
|
||||
unsigned long pit_rate;
|
||||
unsigned bits;
|
||||
- int ret;
|
||||
|
||||
/*
|
||||
* Use our actual MCK to figure out how many MCK/16 ticks per
|
||||
@@ -206,13 +214,6 @@ static void __init at91sam926x_pit_commo
|
||||
data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
|
||||
clocksource_register_hz(&data->clksrc, pit_rate);
|
||||
|
||||
- /* Set up irq handler */
|
||||
- ret = request_irq(data->irq, at91sam926x_pit_interrupt,
|
||||
- IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
- "at91_tick", data);
|
||||
- if (ret)
|
||||
- panic(pr_fmt("Unable to setup IRQ\n"));
|
||||
-
|
||||
/* Set up and register clockevents */
|
||||
data->clkevt.name = "pit";
|
||||
data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
|
||||
--- a/drivers/clocksource/timer-atmel-st.c
|
||||
+++ b/drivers/clocksource/timer-atmel-st.c
|
||||
@@ -115,18 +115,29 @@ static void clkdev32k_disable_and_flush_
|
||||
last_crtr = read_CRTR();
|
||||
}
|
||||
|
||||
+static int atmel_st_irq;
|
||||
+
|
||||
static int clkevt32k_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
irqmask = 0;
|
||||
regmap_write(regmap_st, AT91_ST_IER, irqmask);
|
||||
+ free_irq(atmel_st_irq, regmap_st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt32k_set_oneshot(struct clock_event_device *dev)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
|
||||
+ ret = request_irq(atmel_st_irq, at91rm9200_timer_interrupt,
|
||||
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
+ "at91_tick", regmap_st);
|
||||
+ if (ret)
|
||||
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||||
+
|
||||
/*
|
||||
* ALM for oneshot irqs, set by next_event()
|
||||
* before 32 seconds have passed.
|
||||
@@ -139,8 +150,16 @@ static int clkevt32k_set_oneshot(struct
|
||||
|
||||
static int clkevt32k_set_periodic(struct clock_event_device *dev)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
|
||||
+ ret = request_irq(atmel_st_irq, at91rm9200_timer_interrupt,
|
||||
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
+ "at91_tick", regmap_st);
|
||||
+ if (ret)
|
||||
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||||
+
|
||||
/* PIT for periodic irqs; fixed rate of 1/HZ */
|
||||
irqmask = AT91_ST_PITS;
|
||||
regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);
|
||||
@@ -198,7 +217,7 @@ static void __init atmel_st_timer_init(s
|
||||
{
|
||||
struct clk *sclk;
|
||||
unsigned int sclk_rate, val;
|
||||
- int irq, ret;
|
||||
+ int ret;
|
||||
|
||||
regmap_st = syscon_node_to_regmap(node);
|
||||
if (IS_ERR(regmap_st))
|
||||
@@ -210,17 +229,10 @@ static void __init atmel_st_timer_init(s
|
||||
regmap_read(regmap_st, AT91_ST_SR, &val);
|
||||
|
||||
/* Get the interrupts property */
|
||||
- irq = irq_of_parse_and_map(node, 0);
|
||||
- if (!irq)
|
||||
+ atmel_st_irq = irq_of_parse_and_map(node, 0);
|
||||
+ if (!atmel_st_irq)
|
||||
panic(pr_fmt("Unable to get IRQ from DT\n"));
|
||||
|
||||
- /* Make IRQs happen for the system timer */
|
||||
- ret = request_irq(irq, at91rm9200_timer_interrupt,
|
||||
- IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
- "at91_tick", regmap_st);
|
||||
- if (ret)
|
||||
- panic(pr_fmt("Unable to setup IRQ\n"));
|
||||
-
|
||||
sclk = of_clk_get(node, 0);
|
||||
if (IS_ERR(sclk))
|
||||
panic(pr_fmt("Unable to get slow clock\n"));
|
|
@ -1,33 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sat, 1 May 2010 18:29:35 +0200
|
||||
Subject: ARM: at91: tclib: Default to tclib timer for RT
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
RT is not too happy about the shared timer interrupt in AT91
|
||||
devices. Default to tclib timer for RT.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/misc/Kconfig | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/misc/Kconfig
|
||||
+++ b/drivers/misc/Kconfig
|
||||
@@ -54,6 +54,7 @@ config AD525X_DPOT_SPI
|
||||
config ATMEL_TCLIB
|
||||
bool "Atmel AT32/AT91 Timer/Counter Library"
|
||||
depends on (AVR32 || ARCH_AT91)
|
||||
+ default y if PREEMPT_RT_FULL
|
||||
help
|
||||
Select this if you want a library to allocate the Timer/Counter
|
||||
blocks found on many Atmel processors. This facilitates using
|
||||
@@ -86,7 +87,7 @@ config ATMEL_TCB_CLKSRC_BLOCK
|
||||
config ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
|
||||
bool "TC Block use 32 KiHz clock"
|
||||
depends on ATMEL_TCB_CLKSRC
|
||||
- default y
|
||||
+ default y if !PREEMPT_RT_FULL
|
||||
help
|
||||
Select this to use 32 KiHz base clock rate as TC block clock
|
||||
source for clock events.
|
|
@ -1,408 +0,0 @@
|
|||
From: Frank Rowand <frank.rowand@am.sony.com>
|
||||
Date: Mon, 19 Sep 2011 14:51:14 -0700
|
||||
Subject: arm: Convert arm boot_lock to raw
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The arm boot_lock is used by the secondary processor startup code. The locking
|
||||
task is the idle thread, which has idle->sched_class == &idle_sched_class.
|
||||
idle_sched_class->enqueue_task == NULL, so if the idle task blocks on the
|
||||
lock, the attempt to wake it when the lock becomes available will fail:
|
||||
|
||||
try_to_wake_up()
|
||||
...
|
||||
activate_task()
|
||||
enqueue_task()
|
||||
p->sched_class->enqueue_task(rq, p, flags)
|
||||
|
||||
Fix by converting boot_lock to a raw spin lock.
|
||||
|
||||
Signed-off-by: Frank Rowand <frank.rowand@am.sony.com>
|
||||
Link: http://lkml.kernel.org/r/4E77B952.3010606@am.sony.com
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
arch/arm/mach-exynos/platsmp.c | 12 ++++++------
|
||||
arch/arm/mach-hisi/platmcpm.c | 22 +++++++++++-----------
|
||||
arch/arm/mach-omap2/omap-smp.c | 10 +++++-----
|
||||
arch/arm/mach-prima2/platsmp.c | 10 +++++-----
|
||||
arch/arm/mach-qcom/platsmp.c | 10 +++++-----
|
||||
arch/arm/mach-spear/platsmp.c | 10 +++++-----
|
||||
arch/arm/mach-sti/platsmp.c | 10 +++++-----
|
||||
arch/arm/plat-versatile/platsmp.c | 10 +++++-----
|
||||
8 files changed, 47 insertions(+), 47 deletions(-)
|
||||
|
||||
--- a/arch/arm/mach-exynos/platsmp.c
|
||||
+++ b/arch/arm/mach-exynos/platsmp.c
|
||||
@@ -230,7 +230,7 @@ static void __iomem *scu_base_addr(void)
|
||||
return (void __iomem *)(S5P_VA_SCU);
|
||||
}
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
static void exynos_secondary_init(unsigned int cpu)
|
||||
{
|
||||
@@ -243,8 +243,8 @@ static void exynos_secondary_init(unsign
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr)
|
||||
@@ -308,7 +308,7 @@ static int exynos_boot_secondary(unsigne
|
||||
* Set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
@@ -335,7 +335,7 @@ static int exynos_boot_secondary(unsigne
|
||||
|
||||
if (timeout == 0) {
|
||||
printk(KERN_ERR "cpu1 power enable failed");
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@ static int exynos_boot_secondary(unsigne
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
fail:
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? ret : 0;
|
||||
}
|
||||
--- a/arch/arm/mach-hisi/platmcpm.c
|
||||
+++ b/arch/arm/mach-hisi/platmcpm.c
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
static void __iomem *sysctrl, *fabric;
|
||||
static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER];
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
static u32 fabric_phys_addr;
|
||||
/*
|
||||
* [0]: bootwrapper physical address
|
||||
@@ -113,7 +113,7 @@ static int hip04_boot_secondary(unsigned
|
||||
if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
|
||||
return -EINVAL;
|
||||
|
||||
- spin_lock_irq(&boot_lock);
|
||||
+ raw_spin_lock_irq(&boot_lock);
|
||||
|
||||
if (hip04_cpu_table[cluster][cpu])
|
||||
goto out;
|
||||
@@ -147,7 +147,7 @@ static int hip04_boot_secondary(unsigned
|
||||
|
||||
out:
|
||||
hip04_cpu_table[cluster][cpu]++;
|
||||
- spin_unlock_irq(&boot_lock);
|
||||
+ raw_spin_unlock_irq(&boot_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -162,11 +162,11 @@ static void hip04_cpu_die(unsigned int l
|
||||
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
hip04_cpu_table[cluster][cpu]--;
|
||||
if (hip04_cpu_table[cluster][cpu] == 1) {
|
||||
/* A power_up request went ahead of us. */
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
return;
|
||||
} else if (hip04_cpu_table[cluster][cpu] > 1) {
|
||||
pr_err("Cluster %d CPU%d boots multiple times\n", cluster, cpu);
|
||||
@@ -174,7 +174,7 @@ static void hip04_cpu_die(unsigned int l
|
||||
}
|
||||
|
||||
last_man = hip04_cluster_is_down(cluster);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
if (last_man) {
|
||||
/* Since it's Cortex A15, disable L2 prefetching. */
|
||||
asm volatile(
|
||||
@@ -203,7 +203,7 @@ static int hip04_cpu_kill(unsigned int l
|
||||
cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
|
||||
|
||||
count = TIMEOUT_MSEC / POLL_MSEC;
|
||||
- spin_lock_irq(&boot_lock);
|
||||
+ raw_spin_lock_irq(&boot_lock);
|
||||
for (tries = 0; tries < count; tries++) {
|
||||
if (hip04_cpu_table[cluster][cpu])
|
||||
goto err;
|
||||
@@ -211,10 +211,10 @@ static int hip04_cpu_kill(unsigned int l
|
||||
data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
|
||||
if (data & CORE_WFI_STATUS(cpu))
|
||||
break;
|
||||
- spin_unlock_irq(&boot_lock);
|
||||
+ raw_spin_unlock_irq(&boot_lock);
|
||||
/* Wait for clean L2 when the whole cluster is down. */
|
||||
msleep(POLL_MSEC);
|
||||
- spin_lock_irq(&boot_lock);
|
||||
+ raw_spin_lock_irq(&boot_lock);
|
||||
}
|
||||
if (tries >= count)
|
||||
goto err;
|
||||
@@ -231,10 +231,10 @@ static int hip04_cpu_kill(unsigned int l
|
||||
goto err;
|
||||
if (hip04_cluster_is_down(cluster))
|
||||
hip04_set_snoop_filter(cluster, 0);
|
||||
- spin_unlock_irq(&boot_lock);
|
||||
+ raw_spin_unlock_irq(&boot_lock);
|
||||
return 1;
|
||||
err:
|
||||
- spin_unlock_irq(&boot_lock);
|
||||
+ raw_spin_unlock_irq(&boot_lock);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
--- a/arch/arm/mach-omap2/omap-smp.c
|
||||
+++ b/arch/arm/mach-omap2/omap-smp.c
|
||||
@@ -43,7 +43,7 @@
|
||||
/* SCU base address */
|
||||
static void __iomem *scu_base;
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
void __iomem *omap4_get_scu_base(void)
|
||||
{
|
||||
@@ -74,8 +74,8 @@ static void omap4_secondary_init(unsigne
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
@@ -89,7 +89,7 @@ static int omap4_boot_secondary(unsigned
|
||||
* Set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* Update the AuxCoreBoot0 with boot state for secondary core.
|
||||
@@ -166,7 +166,7 @@ static int omap4_boot_secondary(unsigned
|
||||
* Now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/arch/arm/mach-prima2/platsmp.c
|
||||
+++ b/arch/arm/mach-prima2/platsmp.c
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
static void __iomem *clk_base;
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
static void sirfsoc_secondary_init(unsigned int cpu)
|
||||
{
|
||||
@@ -36,8 +36,8 @@ static void sirfsoc_secondary_init(unsig
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static const struct of_device_id clk_ids[] = {
|
||||
@@ -75,7 +75,7 @@ static int sirfsoc_boot_secondary(unsign
|
||||
/* make sure write buffer is drained */
|
||||
mb();
|
||||
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
@@ -107,7 +107,7 @@ static int sirfsoc_boot_secondary(unsign
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
--- a/arch/arm/mach-qcom/platsmp.c
|
||||
+++ b/arch/arm/mach-qcom/platsmp.c
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
extern void secondary_startup_arm(void);
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void qcom_cpu_die(unsigned int cpu)
|
||||
@@ -60,8 +60,8 @@ static void qcom_secondary_init(unsigned
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int scss_release_secondary(unsigned int cpu)
|
||||
@@ -284,7 +284,7 @@ static int qcom_boot_secondary(unsigned
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
@@ -297,7 +297,7 @@ static int qcom_boot_secondary(unsigned
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- a/arch/arm/mach-spear/platsmp.c
|
||||
+++ b/arch/arm/mach-spear/platsmp.c
|
||||
@@ -32,7 +32,7 @@ static void write_pen_release(int val)
|
||||
sync_cache_w(&pen_release);
|
||||
}
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
|
||||
|
||||
@@ -47,8 +47,8 @@ static void spear13xx_secondary_init(uns
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
@@ -59,7 +59,7 @@ static int spear13xx_boot_secondary(unsi
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
@@ -84,7 +84,7 @@ static int spear13xx_boot_secondary(unsi
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
--- a/arch/arm/mach-sti/platsmp.c
|
||||
+++ b/arch/arm/mach-sti/platsmp.c
|
||||
@@ -35,7 +35,7 @@ static void write_pen_release(int val)
|
||||
sync_cache_w(&pen_release);
|
||||
}
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
static void sti_secondary_init(unsigned int cpu)
|
||||
{
|
||||
@@ -48,8 +48,8 @@ static void sti_secondary_init(unsigned
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
@@ -60,7 +60,7 @@ static int sti_boot_secondary(unsigned i
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
@@ -91,7 +91,7 @@ static int sti_boot_secondary(unsigned i
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
--- a/arch/arm/plat-versatile/platsmp.c
|
||||
+++ b/arch/arm/plat-versatile/platsmp.c
|
||||
@@ -30,7 +30,7 @@ static void write_pen_release(int val)
|
||||
sync_cache_w(&pen_release);
|
||||
}
|
||||
|
||||
-static DEFINE_SPINLOCK(boot_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(boot_lock);
|
||||
|
||||
void versatile_secondary_init(unsigned int cpu)
|
||||
{
|
||||
@@ -43,8 +43,8 @@ void versatile_secondary_init(unsigned i
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
@@ -55,7 +55,7 @@ int versatile_boot_secondary(unsigned in
|
||||
* Set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
- spin_lock(&boot_lock);
|
||||
+ raw_spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* This is really belt and braces; we hold unintended secondary
|
||||
@@ -85,7 +85,7 @@ int versatile_boot_secondary(unsigned in
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
- spin_unlock(&boot_lock);
|
||||
+ raw_spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
Subject: arm: Enable highmem for rt
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Wed, 13 Feb 2013 11:03:11 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
fixup highmem for ARM.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
arch/arm/include/asm/switch_to.h | 8 +++++
|
||||
arch/arm/mm/highmem.c | 56 +++++++++++++++++++++++++++++++++------
|
||||
include/linux/highmem.h | 1
|
||||
3 files changed, 57 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/switch_to.h
|
||||
+++ b/arch/arm/include/asm/switch_to.h
|
||||
@@ -3,6 +3,13 @@
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
+#if defined CONFIG_PREEMPT_RT_FULL && defined CONFIG_HIGHMEM
|
||||
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p);
|
||||
+#else
|
||||
+static inline void
|
||||
+switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { }
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* For v7 SMP cores running a preemptible kernel we may be pre-empted
|
||||
* during a TLB maintenance operation, so execute an inner-shareable dsb
|
||||
@@ -25,6 +32,7 @@ extern struct task_struct *__switch_to(s
|
||||
#define switch_to(prev,next,last) \
|
||||
do { \
|
||||
__complete_pending_tlbi(); \
|
||||
+ switch_kmaps(prev, next); \
|
||||
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
|
||||
} while (0)
|
||||
|
||||
--- a/arch/arm/mm/highmem.c
|
||||
+++ b/arch/arm/mm/highmem.c
|
||||
@@ -34,6 +34,11 @@ static inline pte_t get_fixmap_pte(unsig
|
||||
return *ptep;
|
||||
}
|
||||
|
||||
+static unsigned int fixmap_idx(int type)
|
||||
+{
|
||||
+ return FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
|
||||
+}
|
||||
+
|
||||
void *kmap(struct page *page)
|
||||
{
|
||||
might_sleep();
|
||||
@@ -54,12 +59,13 @@ EXPORT_SYMBOL(kunmap);
|
||||
|
||||
void *kmap_atomic(struct page *page)
|
||||
{
|
||||
+ pte_t pte = mk_pte(page, kmap_prot);
|
||||
unsigned int idx;
|
||||
unsigned long vaddr;
|
||||
void *kmap;
|
||||
int type;
|
||||
|
||||
- preempt_disable();
|
||||
+ preempt_disable_nort();
|
||||
pagefault_disable();
|
||||
if (!PageHighMem(page))
|
||||
return page_address(page);
|
||||
@@ -79,7 +85,7 @@ void *kmap_atomic(struct page *page)
|
||||
|
||||
type = kmap_atomic_idx_push();
|
||||
|
||||
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
|
||||
+ idx = fixmap_idx(type);
|
||||
vaddr = __fix_to_virt(idx);
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
/*
|
||||
@@ -93,7 +99,10 @@ void *kmap_atomic(struct page *page)
|
||||
* in place, so the contained TLB flush ensures the TLB is updated
|
||||
* with the new mapping.
|
||||
*/
|
||||
- set_fixmap_pte(idx, mk_pte(page, kmap_prot));
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ current->kmap_pte[type] = pte;
|
||||
+#endif
|
||||
+ set_fixmap_pte(idx, pte);
|
||||
|
||||
return (void *)vaddr;
|
||||
}
|
||||
@@ -106,10 +115,13 @@ void __kunmap_atomic(void *kvaddr)
|
||||
|
||||
if (kvaddr >= (void *)FIXADDR_START) {
|
||||
type = kmap_atomic_idx();
|
||||
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
|
||||
+ idx = fixmap_idx(type);
|
||||
|
||||
if (cache_is_vivt())
|
||||
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ current->kmap_pte[type] = __pte(0);
|
||||
+#endif
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
BUG_ON(vaddr != __fix_to_virt(idx));
|
||||
#else
|
||||
@@ -122,28 +134,56 @@ void __kunmap_atomic(void *kvaddr)
|
||||
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
|
||||
}
|
||||
pagefault_enable();
|
||||
- preempt_enable();
|
||||
+ preempt_enable_nort();
|
||||
}
|
||||
EXPORT_SYMBOL(__kunmap_atomic);
|
||||
|
||||
void *kmap_atomic_pfn(unsigned long pfn)
|
||||
{
|
||||
+ pte_t pte = pfn_pte(pfn, kmap_prot);
|
||||
unsigned long vaddr;
|
||||
int idx, type;
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
|
||||
- preempt_disable();
|
||||
+ preempt_disable_nort();
|
||||
pagefault_disable();
|
||||
if (!PageHighMem(page))
|
||||
return page_address(page);
|
||||
|
||||
type = kmap_atomic_idx_push();
|
||||
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
|
||||
+ idx = fixmap_idx(type);
|
||||
vaddr = __fix_to_virt(idx);
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
|
||||
#endif
|
||||
- set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot));
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ current->kmap_pte[type] = pte;
|
||||
+#endif
|
||||
+ set_fixmap_pte(idx, pte);
|
||||
|
||||
return (void *)vaddr;
|
||||
}
|
||||
+#if defined CONFIG_PREEMPT_RT_FULL
|
||||
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ /*
|
||||
+ * Clear @prev's kmap_atomic mappings
|
||||
+ */
|
||||
+ for (i = 0; i < prev_p->kmap_idx; i++) {
|
||||
+ int idx = fixmap_idx(i);
|
||||
+
|
||||
+ set_fixmap_pte(idx, __pte(0));
|
||||
+ }
|
||||
+ /*
|
||||
+ * Restore @next_p's kmap_atomic mappings
|
||||
+ */
|
||||
+ for (i = 0; i < next_p->kmap_idx; i++) {
|
||||
+ int idx = fixmap_idx(i);
|
||||
+
|
||||
+ if (!pte_none(next_p->kmap_pte[i]))
|
||||
+ set_fixmap_pte(idx, next_p->kmap_pte[i]);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
--- a/include/linux/highmem.h
|
||||
+++ b/include/linux/highmem.h
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/hardirq.h>
|
||||
+#include <linux/sched.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Mon, 11 Mar 2013 21:37:27 +0100
|
||||
Subject: arm/highmem: Flush tlb on unmap
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The tlb should be flushed on unmap and thus make the mapping entry
|
||||
invalid. This is only done in the non-debug case which does not look
|
||||
right.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/mm/highmem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/mm/highmem.c
|
||||
+++ b/arch/arm/mm/highmem.c
|
||||
@@ -112,10 +112,10 @@ void __kunmap_atomic(void *kvaddr)
|
||||
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
BUG_ON(vaddr != __fix_to_virt(idx));
|
||||
- set_fixmap_pte(idx, __pte(0));
|
||||
#else
|
||||
(void) idx; /* to kill a warning */
|
||||
#endif
|
||||
+ set_fixmap_pte(idx, __pte(0));
|
||||
kmap_atomic_idx_pop();
|
||||
} else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
|
||||
/* this address was obtained through kmap_high_get() */
|
|
@ -1,106 +0,0 @@
|
|||
Subject: arm: Add support for lazy preemption
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Wed, 31 Oct 2012 12:04:11 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Implement the arm pieces for lazy preempt.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
arch/arm/Kconfig | 1 +
|
||||
arch/arm/include/asm/thread_info.h | 3 +++
|
||||
arch/arm/kernel/asm-offsets.c | 1 +
|
||||
arch/arm/kernel/entry-armv.S | 13 +++++++++++--
|
||||
arch/arm/kernel/signal.c | 3 ++-
|
||||
5 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -68,6 +68,7 @@ config ARM
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
+ select HAVE_PREEMPT_LAZY
|
||||
select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE)
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
--- a/arch/arm/include/asm/thread_info.h
|
||||
+++ b/arch/arm/include/asm/thread_info.h
|
||||
@@ -49,6 +49,7 @@ struct cpu_context_save {
|
||||
struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
struct task_struct *task; /* main task structure */
|
||||
__u32 cpu; /* cpu */
|
||||
@@ -143,6 +144,7 @@ extern int vfp_restore_user_hwstate(stru
|
||||
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||
#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
|
||||
+#define TIF_NEED_RESCHED_LAZY 8
|
||||
|
||||
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
||||
#define TIF_USING_IWMMXT 17
|
||||
@@ -152,6 +154,7 @@ extern int vfp_restore_user_hwstate(stru
|
||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
|
||||
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
--- a/arch/arm/kernel/asm-offsets.c
|
||||
+++ b/arch/arm/kernel/asm-offsets.c
|
||||
@@ -65,6 +65,7 @@ int main(void)
|
||||
BLANK();
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
|
||||
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
--- a/arch/arm/kernel/entry-armv.S
|
||||
+++ b/arch/arm/kernel/entry-armv.S
|
||||
@@ -215,11 +215,18 @@ ENDPROC(__dabt_svc)
|
||||
#ifdef CONFIG_PREEMPT
|
||||
get_thread_info tsk
|
||||
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||
- ldr r0, [tsk, #TI_FLAGS] @ get flags
|
||||
teq r8, #0 @ if preempt count != 0
|
||||
+ bne 1f @ return from exeption
|
||||
+ ldr r0, [tsk, #TI_FLAGS] @ get flags
|
||||
+ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set
|
||||
+ blne svc_preempt @ preempt!
|
||||
+
|
||||
+ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
|
||||
+ teq r8, #0 @ if preempt lazy count != 0
|
||||
movne r0, #0 @ force flags to 0
|
||||
- tst r0, #_TIF_NEED_RESCHED
|
||||
+ tst r0, #_TIF_NEED_RESCHED_LAZY
|
||||
blne svc_preempt
|
||||
+1:
|
||||
#endif
|
||||
|
||||
svc_exit r5, irq = 1 @ return from exception
|
||||
@@ -234,6 +241,8 @@ ENDPROC(__irq_svc)
|
||||
1: bl preempt_schedule_irq @ irq en/disable is done inside
|
||||
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
|
||||
tst r0, #_TIF_NEED_RESCHED
|
||||
+ bne 1b
|
||||
+ tst r0, #_TIF_NEED_RESCHED_LAZY
|
||||
reteq r8 @ go again
|
||||
b 1b
|
||||
#endif
|
||||
--- a/arch/arm/kernel/signal.c
|
||||
+++ b/arch/arm/kernel/signal.c
|
||||
@@ -572,7 +572,8 @@ do_work_pending(struct pt_regs *regs, un
|
||||
*/
|
||||
trace_hardirqs_off();
|
||||
do {
|
||||
- if (likely(thread_flags & _TIF_NEED_RESCHED)) {
|
||||
+ if (likely(thread_flags & (_TIF_NEED_RESCHED |
|
||||
+ _TIF_NEED_RESCHED_LAZY))) {
|
||||
schedule();
|
||||
} else {
|
||||
if (unlikely(!user_mode(regs)))
|
|
@ -1,84 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 20 Sep 2013 14:31:54 +0200
|
||||
Subject: arm/unwind: use a raw_spin_lock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Mostly unwind is done with irqs enabled however SLUB may call it with
|
||||
irqs disabled while creating a new SLUB cache.
|
||||
|
||||
I had system freeze while loading a module which called
|
||||
kmem_cache_create() on init. That means SLUB's __slab_alloc() disabled
|
||||
interrupts and then
|
||||
|
||||
->new_slab_objects()
|
||||
->new_slab()
|
||||
->setup_object()
|
||||
->setup_object_debug()
|
||||
->init_tracking()
|
||||
->set_track()
|
||||
->save_stack_trace()
|
||||
->save_stack_trace_tsk()
|
||||
->walk_stackframe()
|
||||
->unwind_frame()
|
||||
->unwind_find_idx()
|
||||
=>spin_lock_irqsave(&unwind_lock);
|
||||
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/kernel/unwind.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/arm/kernel/unwind.c
|
||||
+++ b/arch/arm/kernel/unwind.c
|
||||
@@ -93,7 +93,7 @@ extern const struct unwind_idx __start_u
|
||||
static const struct unwind_idx *__origin_unwind_idx;
|
||||
extern const struct unwind_idx __stop_unwind_idx[];
|
||||
|
||||
-static DEFINE_SPINLOCK(unwind_lock);
|
||||
+static DEFINE_RAW_SPINLOCK(unwind_lock);
|
||||
static LIST_HEAD(unwind_tables);
|
||||
|
||||
/* Convert a prel31 symbol to an absolute address */
|
||||
@@ -201,7 +201,7 @@ static const struct unwind_idx *unwind_f
|
||||
/* module unwind tables */
|
||||
struct unwind_table *table;
|
||||
|
||||
- spin_lock_irqsave(&unwind_lock, flags);
|
||||
+ raw_spin_lock_irqsave(&unwind_lock, flags);
|
||||
list_for_each_entry(table, &unwind_tables, list) {
|
||||
if (addr >= table->begin_addr &&
|
||||
addr < table->end_addr) {
|
||||
@@ -213,7 +213,7 @@ static const struct unwind_idx *unwind_f
|
||||
break;
|
||||
}
|
||||
}
|
||||
- spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
+ raw_spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
}
|
||||
|
||||
pr_debug("%s: idx = %p\n", __func__, idx);
|
||||
@@ -529,9 +529,9 @@ struct unwind_table *unwind_table_add(un
|
||||
tab->begin_addr = text_addr;
|
||||
tab->end_addr = text_addr + text_size;
|
||||
|
||||
- spin_lock_irqsave(&unwind_lock, flags);
|
||||
+ raw_spin_lock_irqsave(&unwind_lock, flags);
|
||||
list_add_tail(&tab->list, &unwind_tables);
|
||||
- spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
+ raw_spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
|
||||
return tab;
|
||||
}
|
||||
@@ -543,9 +543,9 @@ void unwind_table_del(struct unwind_tabl
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
- spin_lock_irqsave(&unwind_lock, flags);
|
||||
+ raw_spin_lock_irqsave(&unwind_lock, flags);
|
||||
list_del(&tab->list);
|
||||
- spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
+ raw_spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
|
||||
kfree(tab);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
Subject: arm64/xen: Make XEN depend on !RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Mon, 12 Oct 2015 11:18:40 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
It's not ready and probably never will be, unless xen folks have a
|
||||
look at it.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
arch/arm64/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm64/Kconfig
|
||||
+++ b/arch/arm64/Kconfig
|
||||
@@ -562,7 +562,7 @@ config XEN_DOM0
|
||||
|
||||
config XEN
|
||||
bool "Xen guest support on ARM64"
|
||||
- depends on ARM64 && OF
|
||||
+ depends on ARM64 && OF && !PREEMPT_RT_FULL
|
||||
select SWIOTLB_XEN
|
||||
help
|
||||
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64.
|
|
@ -1,65 +0,0 @@
|
|||
From: Steven Rostedt <srostedt@redhat.com>
|
||||
Date: Fri, 3 Jul 2009 08:44:29 -0500
|
||||
Subject: ata: Do not disable interrupts in ide code for preempt-rt
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Use the local_irq_*_nort variants.
|
||||
|
||||
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/ata/libata-sff.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/ata/libata-sff.c
|
||||
+++ b/drivers/ata/libata-sff.c
|
||||
@@ -678,9 +678,9 @@ unsigned int ata_sff_data_xfer_noirq(str
|
||||
unsigned long flags;
|
||||
unsigned int consumed;
|
||||
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
consumed = ata_sff_data_xfer32(dev, buf, buflen, rw);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
@@ -719,7 +719,7 @@ static void ata_pio_sector(struct ata_qu
|
||||
unsigned long flags;
|
||||
|
||||
/* FIXME: use a bounce buffer */
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
buf = kmap_atomic(page);
|
||||
|
||||
/* do the actual data transfer */
|
||||
@@ -727,7 +727,7 @@ static void ata_pio_sector(struct ata_qu
|
||||
do_write);
|
||||
|
||||
kunmap_atomic(buf);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
} else {
|
||||
buf = page_address(page);
|
||||
ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
|
||||
@@ -864,7 +864,7 @@ static int __atapi_pio_bytes(struct ata_
|
||||
unsigned long flags;
|
||||
|
||||
/* FIXME: use bounce buffer */
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
buf = kmap_atomic(page);
|
||||
|
||||
/* do the actual data transfer */
|
||||
@@ -872,7 +872,7 @@ static int __atapi_pio_bytes(struct ata_
|
||||
count, rw);
|
||||
|
||||
kunmap_atomic(buf);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
} else {
|
||||
buf = page_address(page);
|
||||
consumed = ap->ops->sff_data_xfer(dev, buf + offset,
|
|
@ -1,84 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Sat, 3 May 2014 11:00:29 +0200
|
||||
Subject: blk-mq: revert raw locks, post pone notifier to POST_DEAD
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The blk_mq_cpu_notify_lock should be raw because some CPU down levels
|
||||
are called with interrupts off. The notifier itself calls currently one
|
||||
function that is blk_mq_hctx_notify().
|
||||
That function acquires the ctx->lock lock which is sleeping and I would
|
||||
prefer to keep it that way. That function only moves IO-requests from
|
||||
the CPU that is going offline to another CPU and it is currently the
|
||||
only one. Therefore I revert the list lock back to sleeping spinlocks
|
||||
and let the notifier run at POST_DEAD time.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-mq-cpu.c | 17 ++++++++++-------
|
||||
block/blk-mq.c | 2 +-
|
||||
2 files changed, 11 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/block/blk-mq-cpu.c
|
||||
+++ b/block/blk-mq-cpu.c
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "blk-mq.h"
|
||||
|
||||
static LIST_HEAD(blk_mq_cpu_notify_list);
|
||||
-static DEFINE_RAW_SPINLOCK(blk_mq_cpu_notify_lock);
|
||||
+static DEFINE_SPINLOCK(blk_mq_cpu_notify_lock);
|
||||
|
||||
static int blk_mq_main_cpu_notify(struct notifier_block *self,
|
||||
unsigned long action, void *hcpu)
|
||||
@@ -25,7 +25,10 @@ static int blk_mq_main_cpu_notify(struct
|
||||
struct blk_mq_cpu_notifier *notify;
|
||||
int ret = NOTIFY_OK;
|
||||
|
||||
- raw_spin_lock(&blk_mq_cpu_notify_lock);
|
||||
+ if (action != CPU_POST_DEAD)
|
||||
+ return NOTIFY_OK;
|
||||
+
|
||||
+ spin_lock(&blk_mq_cpu_notify_lock);
|
||||
|
||||
list_for_each_entry(notify, &blk_mq_cpu_notify_list, list) {
|
||||
ret = notify->notify(notify->data, action, cpu);
|
||||
@@ -33,7 +36,7 @@ static int blk_mq_main_cpu_notify(struct
|
||||
break;
|
||||
}
|
||||
|
||||
- raw_spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
+ spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -41,16 +44,16 @@ void blk_mq_register_cpu_notifier(struct
|
||||
{
|
||||
BUG_ON(!notifier->notify);
|
||||
|
||||
- raw_spin_lock(&blk_mq_cpu_notify_lock);
|
||||
+ spin_lock(&blk_mq_cpu_notify_lock);
|
||||
list_add_tail(¬ifier->list, &blk_mq_cpu_notify_list);
|
||||
- raw_spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
+ spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
}
|
||||
|
||||
void blk_mq_unregister_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
|
||||
{
|
||||
- raw_spin_lock(&blk_mq_cpu_notify_lock);
|
||||
+ spin_lock(&blk_mq_cpu_notify_lock);
|
||||
list_del(¬ifier->list);
|
||||
- raw_spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
+ spin_unlock(&blk_mq_cpu_notify_lock);
|
||||
}
|
||||
|
||||
void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier,
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -1640,7 +1640,7 @@ static int blk_mq_hctx_notify(void *data
|
||||
{
|
||||
struct blk_mq_hw_ctx *hctx = data;
|
||||
|
||||
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
|
||||
+ if (action == CPU_POST_DEAD)
|
||||
return blk_mq_hctx_cpu_offline(hctx, cpu);
|
||||
|
||||
/*
|
|
@ -1,115 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 13 Feb 2015 11:01:26 +0100
|
||||
Subject: block: blk-mq: Use swait
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
| BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:914
|
||||
| in_atomic(): 1, irqs_disabled(): 0, pid: 255, name: kworker/u257:6
|
||||
| 5 locks held by kworker/u257:6/255:
|
||||
| #0: ("events_unbound"){.+.+.+}, at: [<ffffffff8108edf1>] process_one_work+0x171/0x5e0
|
||||
| #1: ((&entry->work)){+.+.+.}, at: [<ffffffff8108edf1>] process_one_work+0x171/0x5e0
|
||||
| #2: (&shost->scan_mutex){+.+.+.}, at: [<ffffffffa000faa3>] __scsi_add_device+0xa3/0x130 [scsi_mod]
|
||||
| #3: (&set->tag_list_lock){+.+...}, at: [<ffffffff812f09fa>] blk_mq_init_queue+0x96a/0xa50
|
||||
| #4: (rcu_read_lock_sched){......}, at: [<ffffffff8132887d>] percpu_ref_kill_and_confirm+0x1d/0x120
|
||||
| Preemption disabled at:[<ffffffff812eff76>] blk_mq_freeze_queue_start+0x56/0x70
|
||||
|
|
||||
| CPU: 2 PID: 255 Comm: kworker/u257:6 Not tainted 3.18.7-rt0+ #1
|
||||
| Workqueue: events_unbound async_run_entry_fn
|
||||
| 0000000000000003 ffff8800bc29f998 ffffffff815b3a12 0000000000000000
|
||||
| 0000000000000000 ffff8800bc29f9b8 ffffffff8109aa16 ffff8800bc29fa28
|
||||
| ffff8800bc5d1bc8 ffff8800bc29f9e8 ffffffff815b8dd4 ffff880000000000
|
||||
| Call Trace:
|
||||
| [<ffffffff815b3a12>] dump_stack+0x4f/0x7c
|
||||
| [<ffffffff8109aa16>] __might_sleep+0x116/0x190
|
||||
| [<ffffffff815b8dd4>] rt_spin_lock+0x24/0x60
|
||||
| [<ffffffff810b6089>] __wake_up+0x29/0x60
|
||||
| [<ffffffff812ee06e>] blk_mq_usage_counter_release+0x1e/0x20
|
||||
| [<ffffffff81328966>] percpu_ref_kill_and_confirm+0x106/0x120
|
||||
| [<ffffffff812eff76>] blk_mq_freeze_queue_start+0x56/0x70
|
||||
| [<ffffffff812f0000>] blk_mq_update_tag_set_depth+0x40/0xd0
|
||||
| [<ffffffff812f0a1c>] blk_mq_init_queue+0x98c/0xa50
|
||||
| [<ffffffffa000dcf0>] scsi_mq_alloc_queue+0x20/0x60 [scsi_mod]
|
||||
| [<ffffffffa000ea35>] scsi_alloc_sdev+0x2f5/0x370 [scsi_mod]
|
||||
| [<ffffffffa000f494>] scsi_probe_and_add_lun+0x9e4/0xdd0 [scsi_mod]
|
||||
| [<ffffffffa000fb26>] __scsi_add_device+0x126/0x130 [scsi_mod]
|
||||
| [<ffffffffa013033f>] ata_scsi_scan_host+0xaf/0x200 [libata]
|
||||
| [<ffffffffa012b5b6>] async_port_probe+0x46/0x60 [libata]
|
||||
| [<ffffffff810978fb>] async_run_entry_fn+0x3b/0xf0
|
||||
| [<ffffffff8108ee81>] process_one_work+0x201/0x5e0
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-core.c | 6 +++---
|
||||
block/blk-mq.c | 6 +++---
|
||||
include/linux/blkdev.h | 2 +-
|
||||
3 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/block/blk-core.c
|
||||
+++ b/block/blk-core.c
|
||||
@@ -660,7 +660,7 @@ int blk_queue_enter(struct request_queue
|
||||
if (!gfpflags_allow_blocking(gfp))
|
||||
return -EBUSY;
|
||||
|
||||
- ret = wait_event_interruptible(q->mq_freeze_wq,
|
||||
+ ret = swait_event_interruptible(q->mq_freeze_wq,
|
||||
!atomic_read(&q->mq_freeze_depth) ||
|
||||
blk_queue_dying(q));
|
||||
if (blk_queue_dying(q))
|
||||
@@ -680,7 +680,7 @@ static void blk_queue_usage_counter_rele
|
||||
struct request_queue *q =
|
||||
container_of(ref, struct request_queue, q_usage_counter);
|
||||
|
||||
- wake_up_all(&q->mq_freeze_wq);
|
||||
+ swait_wake_all(&q->mq_freeze_wq);
|
||||
}
|
||||
|
||||
struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
||||
@@ -742,7 +742,7 @@ struct request_queue *blk_alloc_queue_no
|
||||
q->bypass_depth = 1;
|
||||
__set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags);
|
||||
|
||||
- init_waitqueue_head(&q->mq_freeze_wq);
|
||||
+ init_swait_head(&q->mq_freeze_wq);
|
||||
|
||||
/*
|
||||
* Init percpu_ref in atomic mode so that it's faster to shutdown.
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -92,7 +92,7 @@ EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_st
|
||||
|
||||
static void blk_mq_freeze_queue_wait(struct request_queue *q)
|
||||
{
|
||||
- wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->q_usage_counter));
|
||||
+ swait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->q_usage_counter));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -130,7 +130,7 @@ void blk_mq_unfreeze_queue(struct reques
|
||||
WARN_ON_ONCE(freeze_depth < 0);
|
||||
if (!freeze_depth) {
|
||||
percpu_ref_reinit(&q->q_usage_counter);
|
||||
- wake_up_all(&q->mq_freeze_wq);
|
||||
+ swait_wake_all(&q->mq_freeze_wq);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
|
||||
@@ -149,7 +149,7 @@ void blk_mq_wake_waiters(struct request_
|
||||
* dying, we need to ensure that processes currently waiting on
|
||||
* the queue are notified as well.
|
||||
*/
|
||||
- wake_up_all(&q->mq_freeze_wq);
|
||||
+ swait_wake_all(&q->mq_freeze_wq);
|
||||
}
|
||||
|
||||
bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx)
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -456,7 +456,7 @@ struct request_queue {
|
||||
struct throtl_data *td;
|
||||
#endif
|
||||
struct rcu_head rcu_head;
|
||||
- wait_queue_head_t mq_freeze_wq;
|
||||
+ struct swait_head mq_freeze_wq;
|
||||
struct percpu_ref q_usage_counter;
|
||||
struct list_head all_q_node;
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 29 Jan 2015 15:10:08 +0100
|
||||
Subject: block/mq: don't complete requests via IPI
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The IPI runs in hardirq context and there are sleeping locks. This patch
|
||||
moves the completion into a workqueue.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-core.c | 3 +++
|
||||
block/blk-mq.c | 20 ++++++++++++++++++++
|
||||
include/linux/blk-mq.h | 1 +
|
||||
include/linux/blkdev.h | 1 +
|
||||
4 files changed, 25 insertions(+)
|
||||
|
||||
--- a/block/blk-core.c
|
||||
+++ b/block/blk-core.c
|
||||
@@ -125,6 +125,9 @@ void blk_rq_init(struct request_queue *q
|
||||
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
INIT_LIST_HEAD(&rq->timeout_list);
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ INIT_WORK(&rq->work, __blk_mq_complete_request_remote_work);
|
||||
+#endif
|
||||
rq->cpu = -1;
|
||||
rq->q = q;
|
||||
rq->__sector = (sector_t) -1;
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -196,6 +196,9 @@ static void blk_mq_rq_ctx_init(struct re
|
||||
rq->resid_len = 0;
|
||||
rq->sense = NULL;
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ INIT_WORK(&rq->work, __blk_mq_complete_request_remote_work);
|
||||
+#endif
|
||||
INIT_LIST_HEAD(&rq->timeout_list);
|
||||
rq->timeout = 0;
|
||||
|
||||
@@ -325,6 +328,17 @@ void blk_mq_end_request(struct request *
|
||||
}
|
||||
EXPORT_SYMBOL(blk_mq_end_request);
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+
|
||||
+void __blk_mq_complete_request_remote_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct request *rq = container_of(work, struct request, work);
|
||||
+
|
||||
+ rq->q->softirq_done_fn(rq);
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
static void __blk_mq_complete_request_remote(void *data)
|
||||
{
|
||||
struct request *rq = data;
|
||||
@@ -332,6 +346,8 @@ static void __blk_mq_complete_request_re
|
||||
rq->q->softirq_done_fn(rq);
|
||||
}
|
||||
|
||||
+#endif
|
||||
+
|
||||
static void blk_mq_ipi_complete_request(struct request *rq)
|
||||
{
|
||||
struct blk_mq_ctx *ctx = rq->mq_ctx;
|
||||
@@ -348,10 +364,14 @@ static void blk_mq_ipi_complete_request(
|
||||
shared = cpus_share_cache(cpu, ctx->cpu);
|
||||
|
||||
if (cpu != ctx->cpu && !shared && cpu_online(ctx->cpu)) {
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ schedule_work_on(ctx->cpu, &rq->work);
|
||||
+#else
|
||||
rq->csd.func = __blk_mq_complete_request_remote;
|
||||
rq->csd.info = rq;
|
||||
rq->csd.flags = 0;
|
||||
smp_call_function_single_async(ctx->cpu, &rq->csd);
|
||||
+#endif
|
||||
} else {
|
||||
rq->q->softirq_done_fn(rq);
|
||||
}
|
||||
--- a/include/linux/blk-mq.h
|
||||
+++ b/include/linux/blk-mq.h
|
||||
@@ -212,6 +212,7 @@ static inline u16 blk_mq_unique_tag_to_t
|
||||
|
||||
struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index);
|
||||
struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int);
|
||||
+void __blk_mq_complete_request_remote_work(struct work_struct *work);
|
||||
|
||||
int blk_mq_request_started(struct request *rq);
|
||||
void blk_mq_start_request(struct request *rq);
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -89,6 +89,7 @@ struct request {
|
||||
struct list_head queuelist;
|
||||
union {
|
||||
struct call_single_data csd;
|
||||
+ struct work_struct work;
|
||||
unsigned long fifo_time;
|
||||
};
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 18 Feb 2015 18:37:26 +0100
|
||||
Subject: block/mq: drop per ctx cpu_lock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
While converting the get_cpu() to get_cpu_light() I added a cpu lock to
|
||||
ensure the same code is not invoked twice on the same CPU. And now I run
|
||||
into this:
|
||||
|
||||
| kernel BUG at kernel/locking/rtmutex.c:996!
|
||||
| invalid opcode: 0000 [#1] PREEMPT SMP
|
||||
| CPU0: 13 PID: 75 Comm: kworker/u258:0 Tainted: G I 3.18.7-rt1.5+ #12
|
||||
| Workqueue: writeback bdi_writeback_workfn (flush-8:0)
|
||||
| task: ffff88023742a620 ti: ffff88023743c000 task.ti: ffff88023743c000
|
||||
| RIP: 0010:[<ffffffff81523cc0>] [<ffffffff81523cc0>] rt_spin_lock_slowlock+0x280/0x2d0
|
||||
| Call Trace:
|
||||
| [<ffffffff815254e7>] rt_spin_lock+0x27/0x60
|
||||
taking the same lock again
|
||||
|
|
||||
| [<ffffffff8127c771>] blk_mq_insert_requests+0x51/0x130
|
||||
| [<ffffffff8127d4a9>] blk_mq_flush_plug_list+0x129/0x140
|
||||
| [<ffffffff81272461>] blk_flush_plug_list+0xd1/0x250
|
||||
| [<ffffffff81522075>] schedule+0x75/0xa0
|
||||
| [<ffffffff8152474d>] do_nanosleep+0xdd/0x180
|
||||
| [<ffffffff810c8312>] __hrtimer_nanosleep+0xd2/0x1c0
|
||||
| [<ffffffff810c8456>] cpu_chill+0x56/0x80
|
||||
| [<ffffffff8107c13d>] try_to_grab_pending+0x1bd/0x390
|
||||
| [<ffffffff8107c431>] cancel_delayed_work+0x21/0x170
|
||||
| [<ffffffff81279a98>] blk_mq_stop_hw_queue+0x18/0x40
|
||||
| [<ffffffffa000ac6f>] scsi_queue_rq+0x7f/0x830 [scsi_mod]
|
||||
| [<ffffffff8127b0de>] __blk_mq_run_hw_queue+0x1ee/0x360
|
||||
| [<ffffffff8127b528>] blk_mq_map_request+0x108/0x190
|
||||
take the lock ^^^
|
||||
|
|
||||
| [<ffffffff8127c8d2>] blk_sq_make_request+0x82/0x350
|
||||
| [<ffffffff8126f6c0>] generic_make_request+0xd0/0x120
|
||||
| [<ffffffff8126f788>] submit_bio+0x78/0x190
|
||||
| [<ffffffff811bd537>] _submit_bh+0x117/0x180
|
||||
| [<ffffffff811bf528>] __block_write_full_page.constprop.38+0x138/0x3f0
|
||||
| [<ffffffff811bf880>] block_write_full_page+0xa0/0xe0
|
||||
| [<ffffffff811c02b3>] blkdev_writepage+0x13/0x20
|
||||
| [<ffffffff81127b25>] __writepage+0x15/0x40
|
||||
| [<ffffffff8112873b>] write_cache_pages+0x1fb/0x440
|
||||
| [<ffffffff811289be>] generic_writepages+0x3e/0x60
|
||||
| [<ffffffff8112a17c>] do_writepages+0x1c/0x30
|
||||
| [<ffffffff811b3603>] __writeback_single_inode+0x33/0x140
|
||||
| [<ffffffff811b462d>] writeback_sb_inodes+0x2bd/0x490
|
||||
| [<ffffffff811b4897>] __writeback_inodes_wb+0x97/0xd0
|
||||
| [<ffffffff811b4a9b>] wb_writeback+0x1cb/0x210
|
||||
| [<ffffffff811b505b>] bdi_writeback_workfn+0x25b/0x380
|
||||
| [<ffffffff8107b50b>] process_one_work+0x1bb/0x490
|
||||
| [<ffffffff8107c7ab>] worker_thread+0x6b/0x4f0
|
||||
| [<ffffffff81081863>] kthread+0xe3/0x100
|
||||
| [<ffffffff8152627c>] ret_from_fork+0x7c/0xb0
|
||||
|
||||
After looking at this for a while it seems that it is save if blk_mq_ctx is
|
||||
used multiple times, the in struct lock protects the access.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-mq.c | 4 ----
|
||||
block/blk-mq.h | 8 --------
|
||||
2 files changed, 12 deletions(-)
|
||||
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -1405,9 +1405,7 @@ static blk_qc_t blk_sq_make_request(stru
|
||||
blk_mq_put_ctx(data.ctx);
|
||||
|
||||
if (request_count >= BLK_MAX_REQUEST_COUNT) {
|
||||
- spin_unlock(&data.ctx->cpu_lock);
|
||||
blk_flush_plug_list(plug, false);
|
||||
- spin_lock(&data.ctx->cpu_lock);
|
||||
trace_block_plug(q);
|
||||
}
|
||||
|
||||
@@ -1609,7 +1607,6 @@ static int blk_mq_hctx_cpu_offline(struc
|
||||
blk_mq_hctx_clear_pending(hctx, ctx);
|
||||
}
|
||||
spin_unlock(&ctx->lock);
|
||||
- __blk_mq_put_ctx(ctx);
|
||||
|
||||
if (list_empty(&tmp))
|
||||
return NOTIFY_OK;
|
||||
@@ -1803,7 +1800,6 @@ static void blk_mq_init_cpu_queues(struc
|
||||
memset(__ctx, 0, sizeof(*__ctx));
|
||||
__ctx->cpu = i;
|
||||
spin_lock_init(&__ctx->lock);
|
||||
- spin_lock_init(&__ctx->cpu_lock);
|
||||
INIT_LIST_HEAD(&__ctx->rq_list);
|
||||
__ctx->queue = q;
|
||||
|
||||
--- a/block/blk-mq.h
|
||||
+++ b/block/blk-mq.h
|
||||
@@ -9,7 +9,6 @@ struct blk_mq_ctx {
|
||||
struct list_head rq_list;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
- spinlock_t cpu_lock;
|
||||
unsigned int cpu;
|
||||
unsigned int index_hw;
|
||||
|
||||
@@ -78,7 +77,6 @@ static inline struct blk_mq_ctx *__blk_m
|
||||
struct blk_mq_ctx *ctx;
|
||||
|
||||
ctx = per_cpu_ptr(q->queue_ctx, cpu);
|
||||
- spin_lock(&ctx->cpu_lock);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -93,14 +91,8 @@ static inline struct blk_mq_ctx *blk_mq_
|
||||
return __blk_mq_get_ctx(q, get_cpu_light());
|
||||
}
|
||||
|
||||
-static void __blk_mq_put_ctx(struct blk_mq_ctx *ctx)
|
||||
-{
|
||||
- spin_unlock(&ctx->cpu_lock);
|
||||
-}
|
||||
-
|
||||
static inline void blk_mq_put_ctx(struct blk_mq_ctx *ctx)
|
||||
{
|
||||
- __blk_mq_put_ctx(ctx);
|
||||
put_cpu_light();
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Tue, 14 Jul 2015 14:26:34 +0200
|
||||
Subject: block/mq: do not invoke preempt_disable()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
preempt_disable() and get_cpu() don't play well together with the sleeping
|
||||
locks it tries to allocate later.
|
||||
It seems to be enough to replace it with get_cpu_light() and migrate_disable().
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-mq.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -343,7 +343,7 @@ static void blk_mq_ipi_complete_request(
|
||||
return;
|
||||
}
|
||||
|
||||
- cpu = get_cpu();
|
||||
+ cpu = get_cpu_light();
|
||||
if (!test_bit(QUEUE_FLAG_SAME_FORCE, &rq->q->queue_flags))
|
||||
shared = cpus_share_cache(cpu, ctx->cpu);
|
||||
|
||||
@@ -355,7 +355,7 @@ static void blk_mq_ipi_complete_request(
|
||||
} else {
|
||||
rq->q->softirq_done_fn(rq);
|
||||
}
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
}
|
||||
|
||||
static void __blk_mq_complete_request(struct request *rq)
|
||||
@@ -862,14 +862,14 @@ void blk_mq_run_hw_queue(struct blk_mq_h
|
||||
return;
|
||||
|
||||
if (!async) {
|
||||
- int cpu = get_cpu();
|
||||
+ int cpu = get_cpu_light();
|
||||
if (cpumask_test_cpu(cpu, hctx->cpumask)) {
|
||||
__blk_mq_run_hw_queue(hctx);
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
return;
|
||||
}
|
||||
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
}
|
||||
|
||||
kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
|
|
@ -1,90 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 9 Apr 2014 10:37:23 +0200
|
||||
Subject: block: mq: use cpu_light()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
there is a might sleep splat because get_cpu() disables preemption and
|
||||
later we grab a lock. As a workaround for this we use get_cpu_light()
|
||||
and an additional lock to prevent taking the same ctx.
|
||||
|
||||
There is a lock member in the ctx already but there some functions which do ++
|
||||
on the member and this works with irq off but on RT we would need the extra lock.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
block/blk-mq.c | 4 ++++
|
||||
block/blk-mq.h | 17 ++++++++++++++---
|
||||
2 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -1385,7 +1385,9 @@ static blk_qc_t blk_sq_make_request(stru
|
||||
blk_mq_put_ctx(data.ctx);
|
||||
|
||||
if (request_count >= BLK_MAX_REQUEST_COUNT) {
|
||||
+ spin_unlock(&data.ctx->cpu_lock);
|
||||
blk_flush_plug_list(plug, false);
|
||||
+ spin_lock(&data.ctx->cpu_lock);
|
||||
trace_block_plug(q);
|
||||
}
|
||||
|
||||
@@ -1587,6 +1589,7 @@ static int blk_mq_hctx_cpu_offline(struc
|
||||
blk_mq_hctx_clear_pending(hctx, ctx);
|
||||
}
|
||||
spin_unlock(&ctx->lock);
|
||||
+ __blk_mq_put_ctx(ctx);
|
||||
|
||||
if (list_empty(&tmp))
|
||||
return NOTIFY_OK;
|
||||
@@ -1780,6 +1783,7 @@ static void blk_mq_init_cpu_queues(struc
|
||||
memset(__ctx, 0, sizeof(*__ctx));
|
||||
__ctx->cpu = i;
|
||||
spin_lock_init(&__ctx->lock);
|
||||
+ spin_lock_init(&__ctx->cpu_lock);
|
||||
INIT_LIST_HEAD(&__ctx->rq_list);
|
||||
__ctx->queue = q;
|
||||
|
||||
--- a/block/blk-mq.h
|
||||
+++ b/block/blk-mq.h
|
||||
@@ -9,6 +9,7 @@ struct blk_mq_ctx {
|
||||
struct list_head rq_list;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
+ spinlock_t cpu_lock;
|
||||
unsigned int cpu;
|
||||
unsigned int index_hw;
|
||||
|
||||
@@ -74,7 +75,11 @@ struct blk_align_bitmap {
|
||||
static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q,
|
||||
unsigned int cpu)
|
||||
{
|
||||
- return per_cpu_ptr(q->queue_ctx, cpu);
|
||||
+ struct blk_mq_ctx *ctx;
|
||||
+
|
||||
+ ctx = per_cpu_ptr(q->queue_ctx, cpu);
|
||||
+ spin_lock(&ctx->cpu_lock);
|
||||
+ return ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -85,12 +90,18 @@ static inline struct blk_mq_ctx *__blk_m
|
||||
*/
|
||||
static inline struct blk_mq_ctx *blk_mq_get_ctx(struct request_queue *q)
|
||||
{
|
||||
- return __blk_mq_get_ctx(q, get_cpu());
|
||||
+ return __blk_mq_get_ctx(q, get_cpu_light());
|
||||
+}
|
||||
+
|
||||
+static void __blk_mq_put_ctx(struct blk_mq_ctx *ctx)
|
||||
+{
|
||||
+ spin_unlock(&ctx->cpu_lock);
|
||||
}
|
||||
|
||||
static inline void blk_mq_put_ctx(struct blk_mq_ctx *ctx)
|
||||
{
|
||||
- put_cpu();
|
||||
+ __blk_mq_put_ctx(ctx);
|
||||
+ put_cpu_light();
|
||||
}
|
||||
|
||||
struct blk_mq_alloc_data {
|
|
@ -1,97 +0,0 @@
|
|||
Subject: block: Shorten interrupt disabled regions
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Wed, 22 Jun 2011 19:47:02 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Moving the blk_sched_flush_plug() call out of the interrupt/preempt
|
||||
disabled region in the scheduler allows us to replace
|
||||
local_irq_save/restore(flags) by local_irq_disable/enable() in
|
||||
blk_flush_plug().
|
||||
|
||||
Now instead of doing this we disable interrupts explicitely when we
|
||||
lock the request_queue and reenable them when we drop the lock. That
|
||||
allows interrupts to be handled when the plug list contains requests
|
||||
for more than one queue.
|
||||
|
||||
Aside of that this change makes the scope of the irq disabled region
|
||||
more obvious. The current code confused the hell out of me when
|
||||
looking at:
|
||||
|
||||
local_irq_save(flags);
|
||||
spin_lock(q->queue_lock);
|
||||
...
|
||||
queue_unplugged(q...);
|
||||
scsi_request_fn();
|
||||
spin_unlock(q->queue_lock);
|
||||
spin_lock(shost->host_lock);
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
-------------------^^^ ????
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
spin_unlock(q->lock);
|
||||
local_irq_restore(flags);
|
||||
|
||||
Also add a comment to __blk_run_queue() documenting that
|
||||
q->request_fn() can drop q->queue_lock and reenable interrupts, but
|
||||
must return with q->queue_lock held and interrupts disabled.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Tejun Heo <tj@kernel.org>
|
||||
Cc: Jens Axboe <axboe@kernel.dk>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Link: http://lkml.kernel.org/r/20110622174919.025446432@linutronix.de
|
||||
---
|
||||
block/blk-core.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/block/blk-core.c
|
||||
+++ b/block/blk-core.c
|
||||
@@ -3198,7 +3198,7 @@ static void queue_unplugged(struct reque
|
||||
blk_run_queue_async(q);
|
||||
else
|
||||
__blk_run_queue(q);
|
||||
- spin_unlock(q->queue_lock);
|
||||
+ spin_unlock_irq(q->queue_lock);
|
||||
}
|
||||
|
||||
static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
|
||||
@@ -3246,7 +3246,6 @@ EXPORT_SYMBOL(blk_check_plugged);
|
||||
void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
|
||||
{
|
||||
struct request_queue *q;
|
||||
- unsigned long flags;
|
||||
struct request *rq;
|
||||
LIST_HEAD(list);
|
||||
unsigned int depth;
|
||||
@@ -3266,11 +3265,6 @@ void blk_flush_plug_list(struct blk_plug
|
||||
q = NULL;
|
||||
depth = 0;
|
||||
|
||||
- /*
|
||||
- * Save and disable interrupts here, to avoid doing it for every
|
||||
- * queue lock we have to take.
|
||||
- */
|
||||
- local_irq_save(flags);
|
||||
while (!list_empty(&list)) {
|
||||
rq = list_entry_rq(list.next);
|
||||
list_del_init(&rq->queuelist);
|
||||
@@ -3283,7 +3277,7 @@ void blk_flush_plug_list(struct blk_plug
|
||||
queue_unplugged(q, depth, from_schedule);
|
||||
q = rq->q;
|
||||
depth = 0;
|
||||
- spin_lock(q->queue_lock);
|
||||
+ spin_lock_irq(q->queue_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3310,8 +3304,6 @@ void blk_flush_plug_list(struct blk_plug
|
||||
*/
|
||||
if (q)
|
||||
queue_unplugged(q, depth, from_schedule);
|
||||
-
|
||||
- local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void blk_finish_plug(struct blk_plug *plug)
|
|
@ -1,46 +0,0 @@
|
|||
Subject: block: Use cpu_chill() for retry loops
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Thu, 20 Dec 2012 18:28:26 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Retry loops on RT might loop forever when the modifying side was
|
||||
preempted. Steven also observed a live lock when there was a
|
||||
concurrent priority boosting going on.
|
||||
|
||||
Use cpu_chill() instead of cpu_relax() to let the system
|
||||
make progress.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
block/blk-ioc.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/block/blk-ioc.c
|
||||
+++ b/block/blk-ioc.c
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/bio.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/delay.h>
|
||||
|
||||
#include "blk.h"
|
||||
|
||||
@@ -109,7 +110,7 @@ static void ioc_release_fn(struct work_s
|
||||
spin_unlock(q->queue_lock);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&ioc->lock, flags);
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
spin_lock_irqsave_nested(&ioc->lock, flags, 1);
|
||||
}
|
||||
}
|
||||
@@ -187,7 +188,7 @@ void put_io_context_active(struct io_con
|
||||
spin_unlock(icq->q->queue_lock);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&ioc->lock, flags);
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
goto retry;
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 15 Jan 2016 14:28:39 +0100
|
||||
Subject: btrfs: initialize the seq counter in struct btrfs_device
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
I managed to trigger this:
|
||||
| INFO: trying to register non-static key.
|
||||
| the code is fine but needs lockdep annotation.
|
||||
| turning off the locking correctness validator.
|
||||
| CPU: 1 PID: 781 Comm: systemd-gpt-aut Not tainted 4.4.0-rt2+ #14
|
||||
| Hardware name: ARM-Versatile Express
|
||||
| [<80307cec>] (dump_stack)
|
||||
| [<80070e98>] (__lock_acquire)
|
||||
| [<8007184c>] (lock_acquire)
|
||||
| [<80287800>] (btrfs_ioctl)
|
||||
| [<8012a8d4>] (do_vfs_ioctl)
|
||||
| [<8012ac14>] (SyS_ioctl)
|
||||
|
||||
so I think that btrfs_device_data_ordered_init() is not invoked behind
|
||||
a macro somewhere.
|
||||
|
||||
Fixes: 7cc8e58d53cd ("Btrfs: fix unprotected device's variants on 32bits machine")
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
fs/btrfs/volumes.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/fs/btrfs/volumes.c
|
||||
+++ b/fs/btrfs/volumes.c
|
||||
@@ -232,6 +232,7 @@ static struct btrfs_device *__alloc_devi
|
||||
spin_lock_init(&dev->reada_lock);
|
||||
atomic_set(&dev->reada_in_flight, 0);
|
||||
atomic_set(&dev->dev_stats_ccnt, 0);
|
||||
+ btrfs_device_data_ordered_init(dev);
|
||||
INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
|
||||
INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Ingo Molnar <mingo@elte.hu>
|
||||
Date: Fri, 3 Jul 2009 08:29:58 -0500
|
||||
Subject: bug: BUG_ON/WARN_ON variants dependend on RT/!RT
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Introduce RT/NON-RT WARN/BUG statements to avoid ifdefs in the code.
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
include/asm-generic/bug.h | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
--- a/include/asm-generic/bug.h
|
||||
+++ b/include/asm-generic/bug.h
|
||||
@@ -206,6 +206,20 @@ extern void warn_slowpath_null(const cha
|
||||
# define WARN_ON_SMP(x) ({0;})
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+# define BUG_ON_RT(c) BUG_ON(c)
|
||||
+# define BUG_ON_NONRT(c) do { } while (0)
|
||||
+# define WARN_ON_RT(condition) WARN_ON(condition)
|
||||
+# define WARN_ON_NONRT(condition) do { } while (0)
|
||||
+# define WARN_ON_ONCE_NONRT(condition) do { } while (0)
|
||||
+#else
|
||||
+# define BUG_ON_RT(c) do { } while (0)
|
||||
+# define BUG_ON_NONRT(c) BUG_ON(c)
|
||||
+# define WARN_ON_RT(condition) do { } while (0)
|
||||
+# define WARN_ON_NONRT(condition) WARN_ON(condition)
|
||||
+# define WARN_ON_ONCE_NONRT(condition) WARN_ON_ONCE(condition)
|
||||
+#endif
|
||||
+
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||
From: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Date: Sat, 21 Jun 2014 10:09:48 +0200
|
||||
Subject: memcontrol: Prevent scheduling while atomic in cgroup code
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
mm, memcg: make refill_stock() use get_cpu_light()
|
||||
|
||||
Nikita reported the following memcg scheduling while atomic bug:
|
||||
|
||||
Call Trace:
|
||||
[e22d5a90] [c0007ea8] show_stack+0x4c/0x168 (unreliable)
|
||||
[e22d5ad0] [c0618c04] __schedule_bug+0x94/0xb0
|
||||
[e22d5ae0] [c060b9ec] __schedule+0x530/0x550
|
||||
[e22d5bf0] [c060bacc] schedule+0x30/0xbc
|
||||
[e22d5c00] [c060ca24] rt_spin_lock_slowlock+0x180/0x27c
|
||||
[e22d5c70] [c00b39dc] res_counter_uncharge_until+0x40/0xc4
|
||||
[e22d5ca0] [c013ca88] drain_stock.isra.20+0x54/0x98
|
||||
[e22d5cc0] [c01402ac] __mem_cgroup_try_charge+0x2e8/0xbac
|
||||
[e22d5d70] [c01410d4] mem_cgroup_charge_common+0x3c/0x70
|
||||
[e22d5d90] [c0117284] __do_fault+0x38c/0x510
|
||||
[e22d5df0] [c011a5f4] handle_pte_fault+0x98/0x858
|
||||
[e22d5e50] [c060ed08] do_page_fault+0x42c/0x6fc
|
||||
[e22d5f40] [c000f5b4] handle_page_fault+0xc/0x80
|
||||
|
||||
What happens:
|
||||
|
||||
refill_stock()
|
||||
get_cpu_var()
|
||||
drain_stock()
|
||||
res_counter_uncharge()
|
||||
res_counter_uncharge_until()
|
||||
spin_lock() <== boom
|
||||
|
||||
Fix it by replacing get/put_cpu_var() with get/put_cpu_light().
|
||||
|
||||
|
||||
Reported-by: Nikita Yushchenko <nyushchenko@dev.rtsoft.ru>
|
||||
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
mm/memcontrol.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/mm/memcontrol.c
|
||||
+++ b/mm/memcontrol.c
|
||||
@@ -1937,14 +1937,17 @@ static void drain_local_stock(struct wor
|
||||
*/
|
||||
static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
|
||||
{
|
||||
- struct memcg_stock_pcp *stock = &get_cpu_var(memcg_stock);
|
||||
+ struct memcg_stock_pcp *stock;
|
||||
+ int cpu = get_cpu_light();
|
||||
+
|
||||
+ stock = &per_cpu(memcg_stock, cpu);
|
||||
|
||||
if (stock->cached != memcg) { /* reset if necessary */
|
||||
drain_stock(stock);
|
||||
stock->cached = memcg;
|
||||
}
|
||||
stock->nr_pages += nr_pages;
|
||||
- put_cpu_var(memcg_stock);
|
||||
+ put_cpu_light();
|
||||
}
|
||||
|
||||
/*
|
|
@ -1,87 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 13 Feb 2015 15:52:24 +0100
|
||||
Subject: cgroups: use simple wait in css_release()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
To avoid:
|
||||
|BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:914
|
||||
|in_atomic(): 1, irqs_disabled(): 0, pid: 92, name: rcuc/11
|
||||
|2 locks held by rcuc/11/92:
|
||||
| #0: (rcu_callback){......}, at: [<ffffffff810e037e>] rcu_cpu_kthread+0x3de/0x940
|
||||
| #1: (rcu_read_lock_sched){......}, at: [<ffffffff81328390>] percpu_ref_call_confirm_rcu+0x0/0xd0
|
||||
|Preemption disabled at:[<ffffffff813284e2>] percpu_ref_switch_to_atomic_rcu+0x82/0xc0
|
||||
|CPU: 11 PID: 92 Comm: rcuc/11 Not tainted 3.18.7-rt0+ #1
|
||||
| ffff8802398cdf80 ffff880235f0bc28 ffffffff815b3a12 0000000000000000
|
||||
| 0000000000000000 ffff880235f0bc48 ffffffff8109aa16 0000000000000000
|
||||
| ffff8802398cdf80 ffff880235f0bc78 ffffffff815b8dd4 000000000000df80
|
||||
|Call Trace:
|
||||
| [<ffffffff815b3a12>] dump_stack+0x4f/0x7c
|
||||
| [<ffffffff8109aa16>] __might_sleep+0x116/0x190
|
||||
| [<ffffffff815b8dd4>] rt_spin_lock+0x24/0x60
|
||||
| [<ffffffff8108d2cd>] queue_work_on+0x6d/0x1d0
|
||||
| [<ffffffff8110c881>] css_release+0x81/0x90
|
||||
| [<ffffffff8132844e>] percpu_ref_call_confirm_rcu+0xbe/0xd0
|
||||
| [<ffffffff813284e2>] percpu_ref_switch_to_atomic_rcu+0x82/0xc0
|
||||
| [<ffffffff810e03e5>] rcu_cpu_kthread+0x445/0x940
|
||||
| [<ffffffff81098a2d>] smpboot_thread_fn+0x18d/0x2d0
|
||||
| [<ffffffff810948d8>] kthread+0xe8/0x100
|
||||
| [<ffffffff815b9c3c>] ret_from_fork+0x7c/0xb0
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/linux/cgroup-defs.h | 2 ++
|
||||
kernel/cgroup.c | 9 +++++----
|
||||
2 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/include/linux/cgroup-defs.h
|
||||
+++ b/include/linux/cgroup-defs.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/percpu-refcount.h>
|
||||
#include <linux/percpu-rwsem.h>
|
||||
#include <linux/workqueue.h>
|
||||
+#include <linux/work-simple.h>
|
||||
|
||||
#ifdef CONFIG_CGROUPS
|
||||
|
||||
@@ -136,6 +137,7 @@ struct cgroup_subsys_state {
|
||||
/* percpu_ref killing and RCU release */
|
||||
struct rcu_head rcu_head;
|
||||
struct work_struct destroy_work;
|
||||
+ struct swork_event destroy_swork;
|
||||
};
|
||||
|
||||
/*
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -4724,10 +4724,10 @@ static void css_free_rcu_fn(struct rcu_h
|
||||
queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
}
|
||||
|
||||
-static void css_release_work_fn(struct work_struct *work)
|
||||
+static void css_release_work_fn(struct swork_event *sev)
|
||||
{
|
||||
struct cgroup_subsys_state *css =
|
||||
- container_of(work, struct cgroup_subsys_state, destroy_work);
|
||||
+ container_of(sev, struct cgroup_subsys_state, destroy_swork);
|
||||
struct cgroup_subsys *ss = css->ss;
|
||||
struct cgroup *cgrp = css->cgroup;
|
||||
|
||||
@@ -4766,8 +4766,8 @@ static void css_release(struct percpu_re
|
||||
struct cgroup_subsys_state *css =
|
||||
container_of(ref, struct cgroup_subsys_state, refcnt);
|
||||
|
||||
- INIT_WORK(&css->destroy_work, css_release_work_fn);
|
||||
- queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
+ INIT_SWORK(&css->destroy_swork, css_release_work_fn);
|
||||
+ swork_queue(&css->destroy_swork);
|
||||
}
|
||||
|
||||
static void init_and_link_css(struct cgroup_subsys_state *css,
|
||||
@@ -5363,6 +5363,7 @@ static int __init cgroup_wq_init(void)
|
||||
*/
|
||||
cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
|
||||
BUG_ON(!cgroup_destroy_wq);
|
||||
+ BUG_ON(swork_get());
|
||||
|
||||
/*
|
||||
* Used to destroy pidlists and separate to serve as flush domain.
|
|
@ -1,158 +0,0 @@
|
|||
From: Benedikt Spranger <b.spranger@linutronix.de>
|
||||
Date: Mon, 8 Mar 2010 18:57:04 +0100
|
||||
Subject: clocksource: TCLIB: Allow higher clock rates for clock events
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
As default the TCLIB uses the 32KiHz base clock rate for clock events.
|
||||
Add a compile time selection to allow higher clock resulution.
|
||||
|
||||
(fixed up by Sami Pietikäinen <Sami.Pietikainen@wapice.com>)
|
||||
|
||||
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
drivers/clocksource/tcb_clksrc.c | 36 +++++++++++++++++++++---------------
|
||||
drivers/misc/Kconfig | 12 ++++++++++--
|
||||
2 files changed, 31 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/clocksource/tcb_clksrc.c
|
||||
+++ b/drivers/clocksource/tcb_clksrc.c
|
||||
@@ -23,8 +23,7 @@
|
||||
* this 32 bit free-running counter. the second channel is not used.
|
||||
*
|
||||
* - The third channel may be used to provide a 16-bit clockevent
|
||||
- * source, used in either periodic or oneshot mode. This runs
|
||||
- * at 32 KiHZ, and can handle delays of up to two seconds.
|
||||
+ * source, used in either periodic or oneshot mode.
|
||||
*
|
||||
* A boot clocksource and clockevent source are also currently needed,
|
||||
* unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
|
||||
@@ -74,6 +73,7 @@ static struct clocksource clksrc = {
|
||||
struct tc_clkevt_device {
|
||||
struct clock_event_device clkevt;
|
||||
struct clk *clk;
|
||||
+ u32 freq;
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
@@ -82,13 +82,6 @@ static struct tc_clkevt_device *to_tc_cl
|
||||
return container_of(clkevt, struct tc_clkevt_device, clkevt);
|
||||
}
|
||||
|
||||
-/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
|
||||
- * because using one of the divided clocks would usually mean the
|
||||
- * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
|
||||
- *
|
||||
- * A divided clock could be good for high resolution timers, since
|
||||
- * 30.5 usec resolution can seem "low".
|
||||
- */
|
||||
static u32 timer_clock;
|
||||
|
||||
static int tc_shutdown(struct clock_event_device *d)
|
||||
@@ -113,7 +106,7 @@ static int tc_set_oneshot(struct clock_e
|
||||
|
||||
clk_enable(tcd->clk);
|
||||
|
||||
- /* slow clock, count up to RC, then irq and stop */
|
||||
+ /* count up to RC, then irq and stop */
|
||||
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
|
||||
ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR));
|
||||
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
|
||||
@@ -135,10 +128,10 @@ static int tc_set_periodic(struct clock_
|
||||
*/
|
||||
clk_enable(tcd->clk);
|
||||
|
||||
- /* slow clock, count up to RC, then irq and restart */
|
||||
+ /* count up to RC, then irq and restart */
|
||||
__raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
|
||||
regs + ATMEL_TC_REG(2, CMR));
|
||||
- __raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
|
||||
+ __raw_writel((tcd->freq + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
|
||||
|
||||
/* Enable clock and interrupts on RC compare */
|
||||
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
|
||||
@@ -165,7 +158,11 @@ static struct tc_clkevt_device clkevt =
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
/* Should be lower than at91rm9200's system timer */
|
||||
+#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
|
||||
.rating = 125,
|
||||
+#else
|
||||
+ .rating = 200,
|
||||
+#endif
|
||||
.set_next_event = tc_next_event,
|
||||
.set_state_shutdown = tc_shutdown,
|
||||
.set_state_periodic = tc_set_periodic,
|
||||
@@ -187,8 +184,9 @@ static irqreturn_t ch2_irq(int irq, void
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
-static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
|
||||
+static int __init setup_clkevents(struct atmel_tc *tc, int divisor_idx)
|
||||
{
|
||||
+ unsigned divisor = atmel_tc_divisors[divisor_idx];
|
||||
int ret;
|
||||
struct clk *t2_clk = tc->clk[2];
|
||||
int irq = tc->irq[2];
|
||||
@@ -209,7 +207,11 @@ static int __init setup_clkevents(struct
|
||||
clkevt.regs = tc->regs;
|
||||
clkevt.clk = t2_clk;
|
||||
|
||||
- timer_clock = clk32k_divisor_idx;
|
||||
+ timer_clock = divisor_idx;
|
||||
+ if (!divisor)
|
||||
+ clkevt.freq = 32768;
|
||||
+ else
|
||||
+ clkevt.freq = clk_get_rate(t2_clk) / divisor;
|
||||
|
||||
clkevt.clkevt.cpumask = cpumask_of(0);
|
||||
|
||||
@@ -220,7 +222,7 @@ static int __init setup_clkevents(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
- clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);
|
||||
+ clockevents_config_and_register(&clkevt.clkevt, clkevt.freq, 1, 0xffff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -357,7 +359,11 @@ static int __init tcb_clksrc_init(void)
|
||||
goto err_disable_t1;
|
||||
|
||||
/* channel 2: periodic and oneshot timer support */
|
||||
+#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
|
||||
ret = setup_clkevents(tc, clk32k_divisor_idx);
|
||||
+#else
|
||||
+ ret = setup_clkevents(tc, best_divisor_idx);
|
||||
+#endif
|
||||
if (ret)
|
||||
goto err_unregister_clksrc;
|
||||
|
||||
--- a/drivers/misc/Kconfig
|
||||
+++ b/drivers/misc/Kconfig
|
||||
@@ -69,8 +69,7 @@ config ATMEL_TCB_CLKSRC
|
||||
are combined to make a single 32-bit timer.
|
||||
|
||||
When GENERIC_CLOCKEVENTS is defined, the third timer channel
|
||||
- may be used as a clock event device supporting oneshot mode
|
||||
- (delays of up to two seconds) based on the 32 KiHz clock.
|
||||
+ may be used as a clock event device supporting oneshot mode.
|
||||
|
||||
config ATMEL_TCB_CLKSRC_BLOCK
|
||||
int
|
||||
@@ -84,6 +83,15 @@ config ATMEL_TCB_CLKSRC_BLOCK
|
||||
TC can be used for other purposes, such as PWM generation and
|
||||
interval timing.
|
||||
|
||||
+config ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
|
||||
+ bool "TC Block use 32 KiHz clock"
|
||||
+ depends on ATMEL_TCB_CLKSRC
|
||||
+ default y
|
||||
+ help
|
||||
+ Select this to use 32 KiHz base clock rate as TC block clock
|
||||
+ source for clock events.
|
||||
+
|
||||
+
|
||||
config DUMMY_IRQ
|
||||
tristate "Dummy IRQ handler"
|
||||
default n
|
|
@ -1,225 +0,0 @@
|
|||
Subject: completion: Use simple wait queues
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 11 Jan 2013 11:23:51 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Completions have no long lasting callbacks and therefor do not need
|
||||
the complex waitqueue variant. Use simple waitqueues which reduces the
|
||||
contention on the waitqueue lock.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
drivers/net/wireless/orinoco/orinoco_usb.c | 2 -
|
||||
drivers/usb/gadget/function/f_fs.c | 2 -
|
||||
drivers/usb/gadget/legacy/inode.c | 4 +--
|
||||
include/linux/completion.h | 9 +++-----
|
||||
include/linux/uprobes.h | 1
|
||||
kernel/sched/completion.c | 32 ++++++++++++++---------------
|
||||
kernel/sched/core.c | 10 +++++++--
|
||||
7 files changed, 33 insertions(+), 27 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
@@ -697,7 +697,7 @@ static void ezusb_req_ctx_wait(struct ez
|
||||
while (!ctx->done.done && msecs--)
|
||||
udelay(1000);
|
||||
} else {
|
||||
- wait_event_interruptible(ctx->done.wait,
|
||||
+ swait_event_interruptible(ctx->done.wait,
|
||||
ctx->done.done);
|
||||
}
|
||||
break;
|
||||
--- a/drivers/usb/gadget/function/f_fs.c
|
||||
+++ b/drivers/usb/gadget/function/f_fs.c
|
||||
@@ -1405,7 +1405,7 @@ static void ffs_data_put(struct ffs_data
|
||||
pr_info("%s(): freeing\n", __func__);
|
||||
ffs_data_clear(ffs);
|
||||
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
|
||||
- waitqueue_active(&ffs->ep0req_completion.wait));
|
||||
+ swaitqueue_active(&ffs->ep0req_completion.wait));
|
||||
kfree(ffs->dev_name);
|
||||
kfree(ffs);
|
||||
}
|
||||
--- a/drivers/usb/gadget/legacy/inode.c
|
||||
+++ b/drivers/usb/gadget/legacy/inode.c
|
||||
@@ -345,7 +345,7 @@ ep_io (struct ep_data *epdata, void *buf
|
||||
spin_unlock_irq (&epdata->dev->lock);
|
||||
|
||||
if (likely (value == 0)) {
|
||||
- value = wait_event_interruptible (done.wait, done.done);
|
||||
+ value = swait_event_interruptible (done.wait, done.done);
|
||||
if (value != 0) {
|
||||
spin_lock_irq (&epdata->dev->lock);
|
||||
if (likely (epdata->ep != NULL)) {
|
||||
@@ -354,7 +354,7 @@ ep_io (struct ep_data *epdata, void *buf
|
||||
usb_ep_dequeue (epdata->ep, epdata->req);
|
||||
spin_unlock_irq (&epdata->dev->lock);
|
||||
|
||||
- wait_event (done.wait, done.done);
|
||||
+ swait_event (done.wait, done.done);
|
||||
if (epdata->status == -ECONNRESET)
|
||||
epdata->status = -EINTR;
|
||||
} else {
|
||||
--- a/include/linux/completion.h
|
||||
+++ b/include/linux/completion.h
|
||||
@@ -7,8 +7,7 @@
|
||||
* Atomic wait-for-completion handler data structures.
|
||||
* See kernel/sched/completion.c for details.
|
||||
*/
|
||||
-
|
||||
-#include <linux/wait.h>
|
||||
+#include <linux/wait-simple.h>
|
||||
|
||||
/*
|
||||
* struct completion - structure used to maintain state for a "completion"
|
||||
@@ -24,11 +23,11 @@
|
||||
*/
|
||||
struct completion {
|
||||
unsigned int done;
|
||||
- wait_queue_head_t wait;
|
||||
+ struct swait_head wait;
|
||||
};
|
||||
|
||||
#define COMPLETION_INITIALIZER(work) \
|
||||
- { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
|
||||
+ { 0, SWAIT_HEAD_INITIALIZER((work).wait) }
|
||||
|
||||
#define COMPLETION_INITIALIZER_ONSTACK(work) \
|
||||
({ init_completion(&work); work; })
|
||||
@@ -73,7 +72,7 @@ struct completion {
|
||||
static inline void init_completion(struct completion *x)
|
||||
{
|
||||
x->done = 0;
|
||||
- init_waitqueue_head(&x->wait);
|
||||
+ init_swait_head(&x->wait);
|
||||
}
|
||||
|
||||
/**
|
||||
--- a/include/linux/uprobes.h
|
||||
+++ b/include/linux/uprobes.h
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/types.h>
|
||||
+#include <linux/wait.h>
|
||||
|
||||
struct vm_area_struct;
|
||||
struct mm_struct;
|
||||
--- a/kernel/sched/completion.c
|
||||
+++ b/kernel/sched/completion.c
|
||||
@@ -30,10 +30,10 @@ void complete(struct completion *x)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
- spin_lock_irqsave(&x->wait.lock, flags);
|
||||
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
||||
x->done++;
|
||||
- __wake_up_locked(&x->wait, TASK_NORMAL, 1);
|
||||
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
+ __swait_wake_locked(&x->wait, TASK_NORMAL, 1);
|
||||
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(complete);
|
||||
|
||||
@@ -50,10 +50,10 @@ void complete_all(struct completion *x)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
- spin_lock_irqsave(&x->wait.lock, flags);
|
||||
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
||||
x->done += UINT_MAX/2;
|
||||
- __wake_up_locked(&x->wait, TASK_NORMAL, 0);
|
||||
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
+ __swait_wake_locked(&x->wait, TASK_NORMAL, 0);
|
||||
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(complete_all);
|
||||
|
||||
@@ -62,20 +62,20 @@ do_wait_for_common(struct completion *x,
|
||||
long (*action)(long), long timeout, int state)
|
||||
{
|
||||
if (!x->done) {
|
||||
- DECLARE_WAITQUEUE(wait, current);
|
||||
+ DEFINE_SWAITER(wait);
|
||||
|
||||
- __add_wait_queue_tail_exclusive(&x->wait, &wait);
|
||||
+ swait_prepare_locked(&x->wait, &wait);
|
||||
do {
|
||||
if (signal_pending_state(state, current)) {
|
||||
timeout = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
__set_current_state(state);
|
||||
- spin_unlock_irq(&x->wait.lock);
|
||||
+ raw_spin_unlock_irq(&x->wait.lock);
|
||||
timeout = action(timeout);
|
||||
- spin_lock_irq(&x->wait.lock);
|
||||
+ raw_spin_lock_irq(&x->wait.lock);
|
||||
} while (!x->done && timeout);
|
||||
- __remove_wait_queue(&x->wait, &wait);
|
||||
+ swait_finish_locked(&x->wait, &wait);
|
||||
if (!x->done)
|
||||
return timeout;
|
||||
}
|
||||
@@ -89,9 +89,9 @@ static inline long __sched
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
- spin_lock_irq(&x->wait.lock);
|
||||
+ raw_spin_lock_irq(&x->wait.lock);
|
||||
timeout = do_wait_for_common(x, action, timeout, state);
|
||||
- spin_unlock_irq(&x->wait.lock);
|
||||
+ raw_spin_unlock_irq(&x->wait.lock);
|
||||
return timeout;
|
||||
}
|
||||
|
||||
@@ -277,12 +277,12 @@ bool try_wait_for_completion(struct comp
|
||||
if (!READ_ONCE(x->done))
|
||||
return 0;
|
||||
|
||||
- spin_lock_irqsave(&x->wait.lock, flags);
|
||||
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
|
||||
if (!x->done)
|
||||
ret = 0;
|
||||
else
|
||||
x->done--;
|
||||
- spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(try_wait_for_completion);
|
||||
@@ -311,7 +311,7 @@ bool completion_done(struct completion *
|
||||
* after it's acquired the lock.
|
||||
*/
|
||||
smp_rmb();
|
||||
- spin_unlock_wait(&x->wait.lock);
|
||||
+ raw_spin_unlock_wait(&x->wait.lock);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(completion_done);
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -3102,7 +3102,10 @@ void migrate_disable(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
- WARN_ON_ONCE(p->migrate_disable_atomic);
|
||||
+ if (unlikely(p->migrate_disable_atomic)) {
|
||||
+ tracing_off();
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ }
|
||||
#endif
|
||||
|
||||
if (p->migrate_disable) {
|
||||
@@ -3129,7 +3132,10 @@ void migrate_enable(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
- WARN_ON_ONCE(p->migrate_disable_atomic);
|
||||
+ if (unlikely(p->migrate_disable_atomic)) {
|
||||
+ tracing_off();
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ }
|
||||
#endif
|
||||
WARN_ON_ONCE(p->migrate_disable <= 0);
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
Subject: sched: Use the proper LOCK_OFFSET for cond_resched()
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sun, 17 Jul 2011 22:51:33 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
RT does not increment preempt count when a 'sleeping' spinlock is
|
||||
locked. Update PREEMPT_LOCK_OFFSET for that case.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
include/linux/preempt.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/include/linux/preempt.h
|
||||
+++ b/include/linux/preempt.h
|
||||
@@ -91,7 +91,11 @@
|
||||
/*
|
||||
* The preempt_count offset after spin_lock()
|
||||
*/
|
||||
+#if !defined(CONFIG_PREEMPT_RT_FULL)
|
||||
#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET
|
||||
+#else
|
||||
+#define PREEMPT_LOCK_OFFSET 0
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* The preempt_count offset needed for things like:
|
|
@ -1,53 +0,0 @@
|
|||
Subject: sched: Take RT softirq semantics into account in cond_resched()
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Thu, 14 Jul 2011 09:56:44 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The softirq semantics work different on -RT. There is no SOFTIRQ_MASK in
|
||||
the preemption counter which leads to the BUG_ON() statement in
|
||||
__cond_resched_softirq(). As for -RT it is enough to perform a "normal"
|
||||
schedule.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
include/linux/sched.h | 4 ++++
|
||||
kernel/sched/core.c | 2 ++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -2987,12 +2987,16 @@ extern int __cond_resched_lock(spinlock_
|
||||
__cond_resched_lock(lock); \
|
||||
})
|
||||
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
extern int __cond_resched_softirq(void);
|
||||
|
||||
#define cond_resched_softirq() ({ \
|
||||
___might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET); \
|
||||
__cond_resched_softirq(); \
|
||||
})
|
||||
+#else
|
||||
+# define cond_resched_softirq() cond_resched()
|
||||
+#endif
|
||||
|
||||
static inline void cond_resched_rcu(void)
|
||||
{
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -4770,6 +4770,7 @@ int __cond_resched_lock(spinlock_t *lock
|
||||
}
|
||||
EXPORT_SYMBOL(__cond_resched_lock);
|
||||
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
int __sched __cond_resched_softirq(void)
|
||||
{
|
||||
BUG_ON(!in_softirq());
|
||||
@@ -4783,6 +4784,7 @@ int __sched __cond_resched_softirq(void)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__cond_resched_softirq);
|
||||
+#endif
|
||||
|
||||
/**
|
||||
* yield - yield the current processor to other threads.
|
|
@ -1,56 +0,0 @@
|
|||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Thu, 5 Dec 2013 09:16:52 -0500
|
||||
Subject: cpu hotplug: Document why PREEMPT_RT uses a spinlock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The patch:
|
||||
|
||||
cpu: Make hotplug.lock a "sleeping" spinlock on RT
|
||||
|
||||
Tasks can block on hotplug.lock in pin_current_cpu(), but their
|
||||
state might be != RUNNING. So the mutex wakeup will set the state
|
||||
unconditionally to RUNNING. That might cause spurious unexpected
|
||||
wakeups. We could provide a state preserving mutex_lock() function,
|
||||
but this is semantically backwards. So instead we convert the
|
||||
hotplug.lock() to a spinlock for RT, which has the state preserving
|
||||
semantics already.
|
||||
|
||||
Fixed a bug where the hotplug lock on PREEMPT_RT can be called after a
|
||||
task set its state to TASK_UNINTERRUPTIBLE and before it called
|
||||
schedule. If the hotplug_lock used a mutex, and there was contention,
|
||||
the current task's state would be turned to TASK_RUNNABLE and the
|
||||
schedule call will not sleep. This caused unexpected results.
|
||||
|
||||
Although the patch had a description of the change, the code had no
|
||||
comments about it. This causes confusion to those that review the code,
|
||||
and as PREEMPT_RT is held in a quilt queue and not git, it's not as easy
|
||||
to see why a change was made. Even if it was in git, the code should
|
||||
still have a comment for something as subtle as this.
|
||||
|
||||
Document the rational for using a spinlock on PREEMPT_RT in the hotplug
|
||||
lock code.
|
||||
|
||||
Reported-by: Nicholas Mc Guire <der.herr@hofr.at>
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/cpu.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/kernel/cpu.c
|
||||
+++ b/kernel/cpu.c
|
||||
@@ -110,6 +110,14 @@ struct hotplug_pcp {
|
||||
int grab_lock;
|
||||
struct completion synced;
|
||||
#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ /*
|
||||
+ * Note, on PREEMPT_RT, the hotplug lock must save the state of
|
||||
+ * the task, otherwise the mutex will cause the task to fail
|
||||
+ * to sleep when required. (Because it's called from migrate_disable())
|
||||
+ *
|
||||
+ * The spinlock_t on PREEMPT_RT is a mutex that saves the task's
|
||||
+ * state.
|
||||
+ */
|
||||
spinlock_t lock;
|
||||
#else
|
||||
struct mutex mutex;
|
|
@ -1,117 +0,0 @@
|
|||
Subject: cpu: Make hotplug.lock a "sleeping" spinlock on RT
|
||||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Fri, 02 Mar 2012 10:36:57 -0500
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Tasks can block on hotplug.lock in pin_current_cpu(), but their state
|
||||
might be != RUNNING. So the mutex wakeup will set the state
|
||||
unconditionally to RUNNING. That might cause spurious unexpected
|
||||
wakeups. We could provide a state preserving mutex_lock() function,
|
||||
but this is semantically backwards. So instead we convert the
|
||||
hotplug.lock() to a spinlock for RT, which has the state preserving
|
||||
semantics already.
|
||||
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Cc: Carsten Emde <C.Emde@osadl.org>
|
||||
Cc: John Kacur <jkacur@redhat.com>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Clark Williams <clark.williams@gmail.com>
|
||||
|
||||
Link: http://lkml.kernel.org/r/1330702617.25686.265.camel@gandalf.stny.rr.com
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/cpu.c | 34 +++++++++++++++++++++++++++-------
|
||||
1 file changed, 27 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/kernel/cpu.c
|
||||
+++ b/kernel/cpu.c
|
||||
@@ -60,10 +60,16 @@ static int cpu_hotplug_disabled;
|
||||
|
||||
static struct {
|
||||
struct task_struct *active_writer;
|
||||
+
|
||||
/* wait queue to wake up the active_writer */
|
||||
wait_queue_head_t wq;
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ /* Makes the lock keep the task's state */
|
||||
+ spinlock_t lock;
|
||||
+#else
|
||||
/* verifies that no writer will get active while readers are active */
|
||||
struct mutex lock;
|
||||
+#endif
|
||||
/*
|
||||
* Also blocks the new readers during
|
||||
* an ongoing cpu hotplug operation.
|
||||
@@ -76,12 +82,26 @@ static struct {
|
||||
} cpu_hotplug = {
|
||||
.active_writer = NULL,
|
||||
.wq = __WAIT_QUEUE_HEAD_INITIALIZER(cpu_hotplug.wq),
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ .lock = __SPIN_LOCK_UNLOCKED(cpu_hotplug.lock),
|
||||
+#else
|
||||
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
||||
+#endif
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
.dep_map = {.name = "cpu_hotplug.lock" },
|
||||
#endif
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+# define hotplug_lock() rt_spin_lock(&cpu_hotplug.lock)
|
||||
+# define hotplug_trylock() rt_spin_trylock(&cpu_hotplug.lock)
|
||||
+# define hotplug_unlock() rt_spin_unlock(&cpu_hotplug.lock)
|
||||
+#else
|
||||
+# define hotplug_lock() mutex_lock(&cpu_hotplug.lock)
|
||||
+# define hotplug_trylock() mutex_trylock(&cpu_hotplug.lock)
|
||||
+# define hotplug_unlock() mutex_unlock(&cpu_hotplug.lock)
|
||||
+#endif
|
||||
+
|
||||
/* Lockdep annotations for get/put_online_cpus() and cpu_hotplug_begin/end() */
|
||||
#define cpuhp_lock_acquire_read() lock_map_acquire_read(&cpu_hotplug.dep_map)
|
||||
#define cpuhp_lock_acquire_tryread() \
|
||||
@@ -118,8 +138,8 @@ void pin_current_cpu(void)
|
||||
return;
|
||||
}
|
||||
preempt_enable();
|
||||
- mutex_lock(&cpu_hotplug.lock);
|
||||
- mutex_unlock(&cpu_hotplug.lock);
|
||||
+ hotplug_lock();
|
||||
+ hotplug_unlock();
|
||||
preempt_disable();
|
||||
goto retry;
|
||||
}
|
||||
@@ -192,9 +212,9 @@ void get_online_cpus(void)
|
||||
if (cpu_hotplug.active_writer == current)
|
||||
return;
|
||||
cpuhp_lock_acquire_read();
|
||||
- mutex_lock(&cpu_hotplug.lock);
|
||||
+ hotplug_lock();
|
||||
atomic_inc(&cpu_hotplug.refcount);
|
||||
- mutex_unlock(&cpu_hotplug.lock);
|
||||
+ hotplug_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_online_cpus);
|
||||
|
||||
@@ -247,11 +267,11 @@ void cpu_hotplug_begin(void)
|
||||
cpuhp_lock_acquire();
|
||||
|
||||
for (;;) {
|
||||
- mutex_lock(&cpu_hotplug.lock);
|
||||
+ hotplug_lock();
|
||||
prepare_to_wait(&cpu_hotplug.wq, &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (likely(!atomic_read(&cpu_hotplug.refcount)))
|
||||
break;
|
||||
- mutex_unlock(&cpu_hotplug.lock);
|
||||
+ hotplug_unlock();
|
||||
schedule();
|
||||
}
|
||||
finish_wait(&cpu_hotplug.wq, &wait);
|
||||
@@ -260,7 +280,7 @@ void cpu_hotplug_begin(void)
|
||||
void cpu_hotplug_done(void)
|
||||
{
|
||||
cpu_hotplug.active_writer = NULL;
|
||||
- mutex_unlock(&cpu_hotplug.lock);
|
||||
+ hotplug_unlock();
|
||||
cpuhp_lock_release();
|
||||
}
|
||||
|
|
@ -1,530 +0,0 @@
|
|||
From: Steven Rostedt <srostedt@redhat.com>
|
||||
Date: Mon, 16 Jul 2012 08:07:43 +0000
|
||||
Subject: cpu/rt: Rework cpu down for PREEMPT_RT
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Bringing a CPU down is a pain with the PREEMPT_RT kernel because
|
||||
tasks can be preempted in many more places than in non-RT. In
|
||||
order to handle per_cpu variables, tasks may be pinned to a CPU
|
||||
for a while, and even sleep. But these tasks need to be off the CPU
|
||||
if that CPU is going down.
|
||||
|
||||
Several synchronization methods have been tried, but when stressed
|
||||
they failed. This is a new approach.
|
||||
|
||||
A sync_tsk thread is still created and tasks may still block on a
|
||||
lock when the CPU is going down, but how that works is a bit different.
|
||||
When cpu_down() starts, it will create the sync_tsk and wait on it
|
||||
to inform that current tasks that are pinned on the CPU are no longer
|
||||
pinned. But new tasks that are about to be pinned will still be allowed
|
||||
to do so at this time.
|
||||
|
||||
Then the notifiers are called. Several notifiers will bring down tasks
|
||||
that will enter these locations. Some of these tasks will take locks
|
||||
of other tasks that are on the CPU. If we don't let those other tasks
|
||||
continue, but make them block until CPU down is done, the tasks that
|
||||
the notifiers are waiting on will never complete as they are waiting
|
||||
for the locks held by the tasks that are blocked.
|
||||
|
||||
Thus we still let the task pin the CPU until the notifiers are done.
|
||||
After the notifiers run, we then make new tasks entering the pinned
|
||||
CPU sections grab a mutex and wait. This mutex is now a per CPU mutex
|
||||
in the hotplug_pcp descriptor.
|
||||
|
||||
To help things along, a new function in the scheduler code is created
|
||||
called migrate_me(). This function will try to migrate the current task
|
||||
off the CPU this is going down if possible. When the sync_tsk is created,
|
||||
all tasks will then try to migrate off the CPU going down. There are
|
||||
several cases that this wont work, but it helps in most cases.
|
||||
|
||||
After the notifiers are called and if a task can't migrate off but enters
|
||||
the pin CPU sections, it will be forced to wait on the hotplug_pcp mutex
|
||||
until the CPU down is complete. Then the scheduler will force the migration
|
||||
anyway.
|
||||
|
||||
Also, I found that THREAD_BOUND need to also be accounted for in the
|
||||
pinned CPU, and the migrate_disable no longer treats them special.
|
||||
This helps fix issues with ksoftirqd and workqueue that unbind on CPU down.
|
||||
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
include/linux/sched.h | 7 +
|
||||
kernel/cpu.c | 240 ++++++++++++++++++++++++++++++++++++++++----------
|
||||
kernel/sched/core.c | 78 ++++++++++++++++
|
||||
3 files changed, 281 insertions(+), 44 deletions(-)
|
||||
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -2288,6 +2288,10 @@ extern void do_set_cpus_allowed(struct t
|
||||
|
||||
extern int set_cpus_allowed_ptr(struct task_struct *p,
|
||||
const struct cpumask *new_mask);
|
||||
+int migrate_me(void);
|
||||
+void tell_sched_cpu_down_begin(int cpu);
|
||||
+void tell_sched_cpu_down_done(int cpu);
|
||||
+
|
||||
#else
|
||||
static inline void do_set_cpus_allowed(struct task_struct *p,
|
||||
const struct cpumask *new_mask)
|
||||
@@ -2300,6 +2304,9 @@ static inline int set_cpus_allowed_ptr(s
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
+static inline int migrate_me(void) { return 0; }
|
||||
+static inline void tell_sched_cpu_down_begin(int cpu) { }
|
||||
+static inline void tell_sched_cpu_down_done(int cpu) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
--- a/kernel/cpu.c
|
||||
+++ b/kernel/cpu.c
|
||||
@@ -60,16 +60,10 @@ static int cpu_hotplug_disabled;
|
||||
|
||||
static struct {
|
||||
struct task_struct *active_writer;
|
||||
-
|
||||
/* wait queue to wake up the active_writer */
|
||||
wait_queue_head_t wq;
|
||||
-#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
- /* Makes the lock keep the task's state */
|
||||
- spinlock_t lock;
|
||||
-#else
|
||||
/* verifies that no writer will get active while readers are active */
|
||||
struct mutex lock;
|
||||
-#endif
|
||||
/*
|
||||
* Also blocks the new readers during
|
||||
* an ongoing cpu hotplug operation.
|
||||
@@ -81,27 +75,13 @@ static struct {
|
||||
#endif
|
||||
} cpu_hotplug = {
|
||||
.active_writer = NULL,
|
||||
- .wq = __WAIT_QUEUE_HEAD_INITIALIZER(cpu_hotplug.wq),
|
||||
-#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
- .lock = __SPIN_LOCK_UNLOCKED(cpu_hotplug.lock),
|
||||
-#else
|
||||
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
||||
-#endif
|
||||
+ .wq = __WAIT_QUEUE_HEAD_INITIALIZER(cpu_hotplug.wq),
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
.dep_map = {.name = "cpu_hotplug.lock" },
|
||||
#endif
|
||||
};
|
||||
|
||||
-#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
-# define hotplug_lock() rt_spin_lock(&cpu_hotplug.lock)
|
||||
-# define hotplug_trylock() rt_spin_trylock(&cpu_hotplug.lock)
|
||||
-# define hotplug_unlock() rt_spin_unlock(&cpu_hotplug.lock)
|
||||
-#else
|
||||
-# define hotplug_lock() mutex_lock(&cpu_hotplug.lock)
|
||||
-# define hotplug_trylock() mutex_trylock(&cpu_hotplug.lock)
|
||||
-# define hotplug_unlock() mutex_unlock(&cpu_hotplug.lock)
|
||||
-#endif
|
||||
-
|
||||
/* Lockdep annotations for get/put_online_cpus() and cpu_hotplug_begin/end() */
|
||||
#define cpuhp_lock_acquire_read() lock_map_acquire_read(&cpu_hotplug.dep_map)
|
||||
#define cpuhp_lock_acquire_tryread() \
|
||||
@@ -109,12 +89,42 @@ static struct {
|
||||
#define cpuhp_lock_acquire() lock_map_acquire(&cpu_hotplug.dep_map)
|
||||
#define cpuhp_lock_release() lock_map_release(&cpu_hotplug.dep_map)
|
||||
|
||||
+/**
|
||||
+ * hotplug_pcp - per cpu hotplug descriptor
|
||||
+ * @unplug: set when pin_current_cpu() needs to sync tasks
|
||||
+ * @sync_tsk: the task that waits for tasks to finish pinned sections
|
||||
+ * @refcount: counter of tasks in pinned sections
|
||||
+ * @grab_lock: set when the tasks entering pinned sections should wait
|
||||
+ * @synced: notifier for @sync_tsk to tell cpu_down it's finished
|
||||
+ * @mutex: the mutex to make tasks wait (used when @grab_lock is true)
|
||||
+ * @mutex_init: zero if the mutex hasn't been initialized yet.
|
||||
+ *
|
||||
+ * Although @unplug and @sync_tsk may point to the same task, the @unplug
|
||||
+ * is used as a flag and still exists after @sync_tsk has exited and
|
||||
+ * @sync_tsk set to NULL.
|
||||
+ */
|
||||
struct hotplug_pcp {
|
||||
struct task_struct *unplug;
|
||||
+ struct task_struct *sync_tsk;
|
||||
int refcount;
|
||||
+ int grab_lock;
|
||||
struct completion synced;
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ spinlock_t lock;
|
||||
+#else
|
||||
+ struct mutex mutex;
|
||||
+#endif
|
||||
+ int mutex_init;
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+# define hotplug_lock(hp) rt_spin_lock(&(hp)->lock)
|
||||
+# define hotplug_unlock(hp) rt_spin_unlock(&(hp)->lock)
|
||||
+#else
|
||||
+# define hotplug_lock(hp) mutex_lock(&(hp)->mutex)
|
||||
+# define hotplug_unlock(hp) mutex_unlock(&(hp)->mutex)
|
||||
+#endif
|
||||
+
|
||||
static DEFINE_PER_CPU(struct hotplug_pcp, hotplug_pcp);
|
||||
|
||||
/**
|
||||
@@ -128,18 +138,39 @@ static DEFINE_PER_CPU(struct hotplug_pcp
|
||||
void pin_current_cpu(void)
|
||||
{
|
||||
struct hotplug_pcp *hp;
|
||||
+ int force = 0;
|
||||
|
||||
retry:
|
||||
hp = this_cpu_ptr(&hotplug_pcp);
|
||||
|
||||
- if (!hp->unplug || hp->refcount || preempt_count() > 1 ||
|
||||
+ if (!hp->unplug || hp->refcount || force || preempt_count() > 1 ||
|
||||
hp->unplug == current) {
|
||||
hp->refcount++;
|
||||
return;
|
||||
}
|
||||
- preempt_enable();
|
||||
- hotplug_lock();
|
||||
- hotplug_unlock();
|
||||
+ if (hp->grab_lock) {
|
||||
+ preempt_enable();
|
||||
+ hotplug_lock(hp);
|
||||
+ hotplug_unlock(hp);
|
||||
+ } else {
|
||||
+ preempt_enable();
|
||||
+ /*
|
||||
+ * Try to push this task off of this CPU.
|
||||
+ */
|
||||
+ if (!migrate_me()) {
|
||||
+ preempt_disable();
|
||||
+ hp = this_cpu_ptr(&hotplug_pcp);
|
||||
+ if (!hp->grab_lock) {
|
||||
+ /*
|
||||
+ * Just let it continue it's already pinned
|
||||
+ * or about to sleep.
|
||||
+ */
|
||||
+ force = 1;
|
||||
+ goto retry;
|
||||
+ }
|
||||
+ preempt_enable();
|
||||
+ }
|
||||
+ }
|
||||
preempt_disable();
|
||||
goto retry;
|
||||
}
|
||||
@@ -160,26 +191,84 @@ void unpin_current_cpu(void)
|
||||
wake_up_process(hp->unplug);
|
||||
}
|
||||
|
||||
-/*
|
||||
- * FIXME: Is this really correct under all circumstances ?
|
||||
- */
|
||||
+static void wait_for_pinned_cpus(struct hotplug_pcp *hp)
|
||||
+{
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ while (hp->refcount) {
|
||||
+ schedule_preempt_disabled();
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int sync_unplug_thread(void *data)
|
||||
{
|
||||
struct hotplug_pcp *hp = data;
|
||||
|
||||
preempt_disable();
|
||||
hp->unplug = current;
|
||||
+ wait_for_pinned_cpus(hp);
|
||||
+
|
||||
+ /*
|
||||
+ * This thread will synchronize the cpu_down() with threads
|
||||
+ * that have pinned the CPU. When the pinned CPU count reaches
|
||||
+ * zero, we inform the cpu_down code to continue to the next step.
|
||||
+ */
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
- while (hp->refcount) {
|
||||
- schedule_preempt_disabled();
|
||||
+ preempt_enable();
|
||||
+ complete(&hp->synced);
|
||||
+
|
||||
+ /*
|
||||
+ * If all succeeds, the next step will need tasks to wait till
|
||||
+ * the CPU is offline before continuing. To do this, the grab_lock
|
||||
+ * is set and tasks going into pin_current_cpu() will block on the
|
||||
+ * mutex. But we still need to wait for those that are already in
|
||||
+ * pinned CPU sections. If the cpu_down() failed, the kthread_should_stop()
|
||||
+ * will kick this thread out.
|
||||
+ */
|
||||
+ while (!hp->grab_lock && !kthread_should_stop()) {
|
||||
+ schedule();
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ }
|
||||
+
|
||||
+ /* Make sure grab_lock is seen before we see a stale completion */
|
||||
+ smp_mb();
|
||||
+
|
||||
+ /*
|
||||
+ * Now just before cpu_down() enters stop machine, we need to make
|
||||
+ * sure all tasks that are in pinned CPU sections are out, and new
|
||||
+ * tasks will now grab the lock, keeping them from entering pinned
|
||||
+ * CPU sections.
|
||||
+ */
|
||||
+ if (!kthread_should_stop()) {
|
||||
+ preempt_disable();
|
||||
+ wait_for_pinned_cpus(hp);
|
||||
+ preempt_enable();
|
||||
+ complete(&hp->synced);
|
||||
+ }
|
||||
+
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ while (!kthread_should_stop()) {
|
||||
+ schedule();
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
- preempt_enable();
|
||||
- complete(&hp->synced);
|
||||
+
|
||||
+ /*
|
||||
+ * Force this thread off this CPU as it's going down and
|
||||
+ * we don't want any more work on this CPU.
|
||||
+ */
|
||||
+ current->flags &= ~PF_NO_SETAFFINITY;
|
||||
+ do_set_cpus_allowed(current, cpu_present_mask);
|
||||
+ migrate_me();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void __cpu_unplug_sync(struct hotplug_pcp *hp)
|
||||
+{
|
||||
+ wake_up_process(hp->sync_tsk);
|
||||
+ wait_for_completion(&hp->synced);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Start the sync_unplug_thread on the target cpu and wait for it to
|
||||
* complete.
|
||||
@@ -187,23 +276,83 @@ static int sync_unplug_thread(void *data
|
||||
static int cpu_unplug_begin(unsigned int cpu)
|
||||
{
|
||||
struct hotplug_pcp *hp = &per_cpu(hotplug_pcp, cpu);
|
||||
- struct task_struct *tsk;
|
||||
+ int err;
|
||||
+
|
||||
+ /* Protected by cpu_hotplug.lock */
|
||||
+ if (!hp->mutex_init) {
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ spin_lock_init(&hp->lock);
|
||||
+#else
|
||||
+ mutex_init(&hp->mutex);
|
||||
+#endif
|
||||
+ hp->mutex_init = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Inform the scheduler to migrate tasks off this CPU */
|
||||
+ tell_sched_cpu_down_begin(cpu);
|
||||
|
||||
init_completion(&hp->synced);
|
||||
- tsk = kthread_create(sync_unplug_thread, hp, "sync_unplug/%d", cpu);
|
||||
- if (IS_ERR(tsk))
|
||||
- return (PTR_ERR(tsk));
|
||||
- kthread_bind(tsk, cpu);
|
||||
- wake_up_process(tsk);
|
||||
- wait_for_completion(&hp->synced);
|
||||
+
|
||||
+ hp->sync_tsk = kthread_create(sync_unplug_thread, hp, "sync_unplug/%d", cpu);
|
||||
+ if (IS_ERR(hp->sync_tsk)) {
|
||||
+ err = PTR_ERR(hp->sync_tsk);
|
||||
+ hp->sync_tsk = NULL;
|
||||
+ return err;
|
||||
+ }
|
||||
+ kthread_bind(hp->sync_tsk, cpu);
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for tasks to get out of the pinned sections,
|
||||
+ * it's still OK if new tasks enter. Some CPU notifiers will
|
||||
+ * wait for tasks that are going to enter these sections and
|
||||
+ * we must not have them block.
|
||||
+ */
|
||||
+ __cpu_unplug_sync(hp);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void cpu_unplug_sync(unsigned int cpu)
|
||||
+{
|
||||
+ struct hotplug_pcp *hp = &per_cpu(hotplug_pcp, cpu);
|
||||
+
|
||||
+ init_completion(&hp->synced);
|
||||
+ /* The completion needs to be initialzied before setting grab_lock */
|
||||
+ smp_wmb();
|
||||
+
|
||||
+ /* Grab the mutex before setting grab_lock */
|
||||
+ hotplug_lock(hp);
|
||||
+ hp->grab_lock = 1;
|
||||
+
|
||||
+ /*
|
||||
+ * The CPU notifiers have been completed.
|
||||
+ * Wait for tasks to get out of pinned CPU sections and have new
|
||||
+ * tasks block until the CPU is completely down.
|
||||
+ */
|
||||
+ __cpu_unplug_sync(hp);
|
||||
+
|
||||
+ /* All done with the sync thread */
|
||||
+ kthread_stop(hp->sync_tsk);
|
||||
+ hp->sync_tsk = NULL;
|
||||
+}
|
||||
+
|
||||
static void cpu_unplug_done(unsigned int cpu)
|
||||
{
|
||||
struct hotplug_pcp *hp = &per_cpu(hotplug_pcp, cpu);
|
||||
|
||||
hp->unplug = NULL;
|
||||
+ /* Let all tasks know cpu unplug is finished before cleaning up */
|
||||
+ smp_wmb();
|
||||
+
|
||||
+ if (hp->sync_tsk)
|
||||
+ kthread_stop(hp->sync_tsk);
|
||||
+
|
||||
+ if (hp->grab_lock) {
|
||||
+ hotplug_unlock(hp);
|
||||
+ /* protected by cpu_hotplug.lock */
|
||||
+ hp->grab_lock = 0;
|
||||
+ }
|
||||
+ tell_sched_cpu_down_done(cpu);
|
||||
}
|
||||
|
||||
void get_online_cpus(void)
|
||||
@@ -212,9 +361,9 @@ void get_online_cpus(void)
|
||||
if (cpu_hotplug.active_writer == current)
|
||||
return;
|
||||
cpuhp_lock_acquire_read();
|
||||
- hotplug_lock();
|
||||
+ mutex_lock(&cpu_hotplug.lock);
|
||||
atomic_inc(&cpu_hotplug.refcount);
|
||||
- hotplug_unlock();
|
||||
+ mutex_unlock(&cpu_hotplug.lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_online_cpus);
|
||||
|
||||
@@ -267,11 +416,11 @@ void cpu_hotplug_begin(void)
|
||||
cpuhp_lock_acquire();
|
||||
|
||||
for (;;) {
|
||||
- hotplug_lock();
|
||||
+ mutex_lock(&cpu_hotplug.lock);
|
||||
prepare_to_wait(&cpu_hotplug.wq, &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (likely(!atomic_read(&cpu_hotplug.refcount)))
|
||||
break;
|
||||
- hotplug_unlock();
|
||||
+ mutex_unlock(&cpu_hotplug.lock);
|
||||
schedule();
|
||||
}
|
||||
finish_wait(&cpu_hotplug.wq, &wait);
|
||||
@@ -280,7 +429,7 @@ void cpu_hotplug_begin(void)
|
||||
void cpu_hotplug_done(void)
|
||||
{
|
||||
cpu_hotplug.active_writer = NULL;
|
||||
- hotplug_unlock();
|
||||
+ mutex_unlock(&cpu_hotplug.lock);
|
||||
cpuhp_lock_release();
|
||||
}
|
||||
|
||||
@@ -516,6 +665,9 @@ static int _cpu_down(unsigned int cpu, i
|
||||
|
||||
smpboot_park_threads(cpu);
|
||||
|
||||
+ /* Notifiers are done. Don't let any more tasks pin this CPU. */
|
||||
+ cpu_unplug_sync(cpu);
|
||||
+
|
||||
/*
|
||||
* Prevent irq alloc/free while the dying cpu reorganizes the
|
||||
* interrupt affinities.
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -1211,6 +1211,84 @@ void do_set_cpus_allowed(struct task_str
|
||||
enqueue_task(rq, p, ENQUEUE_RESTORE);
|
||||
}
|
||||
|
||||
+static DEFINE_PER_CPU(struct cpumask, sched_cpumasks);
|
||||
+static DEFINE_MUTEX(sched_down_mutex);
|
||||
+static cpumask_t sched_down_cpumask;
|
||||
+
|
||||
+void tell_sched_cpu_down_begin(int cpu)
|
||||
+{
|
||||
+ mutex_lock(&sched_down_mutex);
|
||||
+ cpumask_set_cpu(cpu, &sched_down_cpumask);
|
||||
+ mutex_unlock(&sched_down_mutex);
|
||||
+}
|
||||
+
|
||||
+void tell_sched_cpu_down_done(int cpu)
|
||||
+{
|
||||
+ mutex_lock(&sched_down_mutex);
|
||||
+ cpumask_clear_cpu(cpu, &sched_down_cpumask);
|
||||
+ mutex_unlock(&sched_down_mutex);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * migrate_me - try to move the current task off this cpu
|
||||
+ *
|
||||
+ * Used by the pin_current_cpu() code to try to get tasks
|
||||
+ * to move off the current CPU as it is going down.
|
||||
+ * It will only move the task if the task isn't pinned to
|
||||
+ * the CPU (with migrate_disable, affinity or NO_SETAFFINITY)
|
||||
+ * and the task has to be in a RUNNING state. Otherwise the
|
||||
+ * movement of the task will wake it up (change its state
|
||||
+ * to running) when the task did not expect it.
|
||||
+ *
|
||||
+ * Returns 1 if it succeeded in moving the current task
|
||||
+ * 0 otherwise.
|
||||
+ */
|
||||
+int migrate_me(void)
|
||||
+{
|
||||
+ struct task_struct *p = current;
|
||||
+ struct migration_arg arg;
|
||||
+ struct cpumask *cpumask;
|
||||
+ struct cpumask *mask;
|
||||
+ unsigned long flags;
|
||||
+ unsigned int dest_cpu;
|
||||
+ struct rq *rq;
|
||||
+
|
||||
+ /*
|
||||
+ * We can not migrate tasks bounded to a CPU or tasks not
|
||||
+ * running. The movement of the task will wake it up.
|
||||
+ */
|
||||
+ if (p->flags & PF_NO_SETAFFINITY || p->state)
|
||||
+ return 0;
|
||||
+
|
||||
+ mutex_lock(&sched_down_mutex);
|
||||
+ rq = task_rq_lock(p, &flags);
|
||||
+
|
||||
+ cpumask = this_cpu_ptr(&sched_cpumasks);
|
||||
+ mask = &p->cpus_allowed;
|
||||
+
|
||||
+ cpumask_andnot(cpumask, mask, &sched_down_cpumask);
|
||||
+
|
||||
+ if (!cpumask_weight(cpumask)) {
|
||||
+ /* It's only on this CPU? */
|
||||
+ task_rq_unlock(rq, p, &flags);
|
||||
+ mutex_unlock(&sched_down_mutex);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ dest_cpu = cpumask_any_and(cpu_active_mask, cpumask);
|
||||
+
|
||||
+ arg.task = p;
|
||||
+ arg.dest_cpu = dest_cpu;
|
||||
+
|
||||
+ task_rq_unlock(rq, p, &flags);
|
||||
+
|
||||
+ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
|
||||
+ tlb_migrate_finish(p->mm);
|
||||
+ mutex_unlock(&sched_down_mutex);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Change a given task's CPU affinity. Migrate the thread to a
|
||||
* proper CPU and schedule it away if the CPU it's executing on
|
|
@ -1,107 +0,0 @@
|
|||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Tue, 4 Mar 2014 12:28:32 -0500
|
||||
Subject: cpu_chill: Add a UNINTERRUPTIBLE hrtimer_nanosleep
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
We hit another bug that was caused by switching cpu_chill() from
|
||||
msleep() to hrtimer_nanosleep().
|
||||
|
||||
This time it is a livelock. The problem is that hrtimer_nanosleep()
|
||||
calls schedule with the state == TASK_INTERRUPTIBLE. But these means
|
||||
that if a signal is pending, the scheduler wont schedule, and will
|
||||
simply change the current task state back to TASK_RUNNING. This
|
||||
nullifies the whole point of cpu_chill() in the first place. That is,
|
||||
if a task is spinning on a try_lock() and it preempted the owner of the
|
||||
lock, if it has a signal pending, it will never give up the CPU to let
|
||||
the owner of the lock run.
|
||||
|
||||
I made a static function __hrtimer_nanosleep() that takes a fifth
|
||||
parameter "state", which determines the task state of that the
|
||||
nanosleep() will be in. The normal hrtimer_nanosleep() will act the
|
||||
same, but cpu_chill() will call the __hrtimer_nanosleep() directly with
|
||||
the TASK_UNINTERRUPTIBLE state.
|
||||
|
||||
cpu_chill() only cares that the first sleep happens, and does not care
|
||||
about the state of the restart schedule (in hrtimer_nanosleep_restart).
|
||||
|
||||
|
||||
Reported-by: Ulrich Obergfell <uobergfe@redhat.com>
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/time/hrtimer.c | 25 ++++++++++++++++++-------
|
||||
1 file changed, 18 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/kernel/time/hrtimer.c
|
||||
+++ b/kernel/time/hrtimer.c
|
||||
@@ -1656,12 +1656,13 @@ void hrtimer_init_sleeper(struct hrtimer
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
|
||||
|
||||
-static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
|
||||
+static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode,
|
||||
+ unsigned long state)
|
||||
{
|
||||
hrtimer_init_sleeper(t, current);
|
||||
|
||||
do {
|
||||
- set_current_state(TASK_INTERRUPTIBLE);
|
||||
+ set_current_state(state);
|
||||
hrtimer_start_expires(&t->timer, mode);
|
||||
|
||||
if (likely(t->task))
|
||||
@@ -1703,7 +1704,8 @@ long __sched hrtimer_nanosleep_restart(s
|
||||
HRTIMER_MODE_ABS);
|
||||
hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
|
||||
|
||||
- if (do_nanosleep(&t, HRTIMER_MODE_ABS))
|
||||
+ /* cpu_chill() does not care about restart state. */
|
||||
+ if (do_nanosleep(&t, HRTIMER_MODE_ABS, TASK_INTERRUPTIBLE))
|
||||
goto out;
|
||||
|
||||
rmtp = restart->nanosleep.rmtp;
|
||||
@@ -1720,8 +1722,10 @@ long __sched hrtimer_nanosleep_restart(s
|
||||
return ret;
|
||||
}
|
||||
|
||||
-long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
|
||||
- const enum hrtimer_mode mode, const clockid_t clockid)
|
||||
+static long
|
||||
+__hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
|
||||
+ const enum hrtimer_mode mode, const clockid_t clockid,
|
||||
+ unsigned long state)
|
||||
{
|
||||
struct restart_block *restart;
|
||||
struct hrtimer_sleeper t;
|
||||
@@ -1734,7 +1738,7 @@ long hrtimer_nanosleep(struct timespec *
|
||||
|
||||
hrtimer_init_on_stack(&t.timer, clockid, mode);
|
||||
hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
|
||||
- if (do_nanosleep(&t, mode))
|
||||
+ if (do_nanosleep(&t, mode, state))
|
||||
goto out;
|
||||
|
||||
/* Absolute timers do not update the rmtp value and restart: */
|
||||
@@ -1761,6 +1765,12 @@ long hrtimer_nanosleep(struct timespec *
|
||||
return ret;
|
||||
}
|
||||
|
||||
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
|
||||
+ const enum hrtimer_mode mode, const clockid_t clockid)
|
||||
+{
|
||||
+ return __hrtimer_nanosleep(rqtp, rmtp, mode, clockid, TASK_INTERRUPTIBLE);
|
||||
+}
|
||||
+
|
||||
SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
|
||||
struct timespec __user *, rmtp)
|
||||
{
|
||||
@@ -1787,7 +1797,8 @@ void cpu_chill(void)
|
||||
unsigned int freeze_flag = current->flags & PF_NOFREEZE;
|
||||
|
||||
current->flags |= PF_NOFREEZE;
|
||||
- hrtimer_nanosleep(&tu, NULL, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
|
||||
+ __hrtimer_nanosleep(&tu, NULL, HRTIMER_MODE_REL, CLOCK_MONOTONIC,
|
||||
+ TASK_UNINTERRUPTIBLE);
|
||||
if (!freeze_flag)
|
||||
current->flags &= ~PF_NOFREEZE;
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
From: Tiejun Chen <tiejun.chen@windriver.com>
|
||||
Subject: cpu_down: move migrate_enable() back
|
||||
Date: Thu, 7 Nov 2013 10:06:07 +0800
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Commit 08c1ab68, "hotplug-use-migrate-disable.patch", intends to
|
||||
use migrate_enable()/migrate_disable() to replace that combination
|
||||
of preempt_enable() and preempt_disable(), but actually in
|
||||
!CONFIG_PREEMPT_RT_FULL case, migrate_enable()/migrate_disable()
|
||||
are still equal to preempt_enable()/preempt_disable(). So that
|
||||
followed cpu_hotplug_begin()/cpu_unplug_begin(cpu) would go schedule()
|
||||
to trigger schedule_debug() like this:
|
||||
|
||||
_cpu_down()
|
||||
|
|
||||
+ migrate_disable() = preempt_disable()
|
||||
|
|
||||
+ cpu_hotplug_begin() or cpu_unplug_begin()
|
||||
|
|
||||
+ schedule()
|
||||
|
|
||||
+ __schedule()
|
||||
|
|
||||
+ preempt_disable();
|
||||
|
|
||||
+ __schedule_bug() is true!
|
||||
|
||||
So we should move migrate_enable() as the original scheme.
|
||||
|
||||
|
||||
Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com>
|
||||
---
|
||||
kernel/cpu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/cpu.c
|
||||
+++ b/kernel/cpu.c
|
||||
@@ -657,6 +657,7 @@ static int _cpu_down(unsigned int cpu, i
|
||||
err = -EBUSY;
|
||||
goto restore_cpus;
|
||||
}
|
||||
+ migrate_enable();
|
||||
|
||||
cpu_hotplug_begin();
|
||||
err = cpu_unplug_begin(cpu);
|
||||
@@ -741,7 +742,6 @@ static int _cpu_down(unsigned int cpu, i
|
||||
out_release:
|
||||
cpu_unplug_done(cpu);
|
||||
out_cancel:
|
||||
- migrate_enable();
|
||||
cpu_hotplug_done();
|
||||
if (!err)
|
||||
cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
|
|
@ -1,33 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 9 Apr 2015 15:23:01 +0200
|
||||
Subject: cpufreq: drop K8's driver from beeing selected
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Ralf posted a picture of a backtrace from
|
||||
|
||||
| powernowk8_target_fn() -> transition_frequency_fidvid() and then at the
|
||||
| end:
|
||||
| 932 policy = cpufreq_cpu_get(smp_processor_id());
|
||||
| 933 cpufreq_cpu_put(policy);
|
||||
|
||||
crashing the system on -RT. I assumed that policy was a NULL pointer but
|
||||
was rulled out. Since Ralf can't do any more investigations on this and
|
||||
I have no machine with this, I simply switch it off.
|
||||
|
||||
Reported-by: Ralf Mardorf <ralf.mardorf@alice-dsl.net>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/cpufreq/Kconfig.x86 | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/Kconfig.x86
|
||||
+++ b/drivers/cpufreq/Kconfig.x86
|
||||
@@ -123,7 +123,7 @@ config X86_POWERNOW_K7_ACPI
|
||||
|
||||
config X86_POWERNOW_K8
|
||||
tristate "AMD Opteron/Athlon64 PowerNow!"
|
||||
- depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
|
||||
+ depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ && !PREEMPT_RT_BASE
|
||||
help
|
||||
This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
|
||||
Support for K10 and newer processors is now in acpi-cpufreq.
|
|
@ -1,35 +0,0 @@
|
|||
Subject: cpumask: Disable CONFIG_CPUMASK_OFFSTACK for RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Wed, 14 Dec 2011 01:03:49 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
We can't deal with the cpumask allocations which happen in atomic
|
||||
context (see arch/x86/kernel/apic/io_apic.c) on RT right now.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
arch/x86/Kconfig | 2 +-
|
||||
lib/Kconfig | 1 +
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -851,7 +851,7 @@ config IOMMU_HELPER
|
||||
config MAXSMP
|
||||
bool "Enable Maximum number of SMP Processors and NUMA Nodes"
|
||||
depends on X86_64 && SMP && DEBUG_KERNEL
|
||||
- select CPUMASK_OFFSTACK
|
||||
+ select CPUMASK_OFFSTACK if !PREEMPT_RT_FULL
|
||||
---help---
|
||||
Enable maximum number of CPUS and NUMA Nodes for this architecture.
|
||||
If unsure, say N.
|
||||
--- a/lib/Kconfig
|
||||
+++ b/lib/Kconfig
|
||||
@@ -395,6 +395,7 @@ config CHECK_SIGNATURE
|
||||
|
||||
config CPUMASK_OFFSTACK
|
||||
bool "Force CPU masks off stack" if DEBUG_PER_CPU_MAPS
|
||||
+ depends on !PREEMPT_RT_FULL
|
||||
help
|
||||
Use dynamic allocation for cpumask_var_t, instead of putting
|
||||
them on the stack. This is a bit more expensive, but avoids
|
|
@ -1,242 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 21 Feb 2014 17:24:04 +0100
|
||||
Subject: crypto: Reduce preempt disabled regions, more algos
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Don Estabrook reported
|
||||
| kernel: WARNING: CPU: 2 PID: 858 at kernel/sched/core.c:2428 migrate_disable+0xed/0x100()
|
||||
| kernel: WARNING: CPU: 2 PID: 858 at kernel/sched/core.c:2462 migrate_enable+0x17b/0x200()
|
||||
| kernel: WARNING: CPU: 3 PID: 865 at kernel/sched/core.c:2428 migrate_disable+0xed/0x100()
|
||||
|
||||
and his backtrace showed some crypto functions which looked fine.
|
||||
|
||||
The problem is the following sequence:
|
||||
|
||||
glue_xts_crypt_128bit()
|
||||
{
|
||||
blkcipher_walk_virt(); /* normal migrate_disable() */
|
||||
|
||||
glue_fpu_begin(); /* get atomic */
|
||||
|
||||
while (nbytes) {
|
||||
__glue_xts_crypt_128bit();
|
||||
blkcipher_walk_done(); /* with nbytes = 0, migrate_enable()
|
||||
* while we are atomic */
|
||||
};
|
||||
glue_fpu_end() /* no longer atomic */
|
||||
}
|
||||
|
||||
and this is why the counter get out of sync and the warning is printed.
|
||||
The other problem is that we are non-preemptible between
|
||||
glue_fpu_begin() and glue_fpu_end() and the latency grows. To fix this,
|
||||
I shorten the FPU off region and ensure blkcipher_walk_done() is called
|
||||
with preemption enabled. This might hurt the performance because we now
|
||||
enable/disable the FPU state more often but we gain lower latency and
|
||||
the bug is gone.
|
||||
|
||||
|
||||
Reported-by: Don Estabrook <don.estabrook@gmail.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/x86/crypto/cast5_avx_glue.c | 21 +++++++++------------
|
||||
arch/x86/crypto/glue_helper.c | 31 +++++++++++++++----------------
|
||||
2 files changed, 24 insertions(+), 28 deletions(-)
|
||||
|
||||
--- a/arch/x86/crypto/cast5_avx_glue.c
|
||||
+++ b/arch/x86/crypto/cast5_avx_glue.c
|
||||
@@ -59,7 +59,7 @@ static inline void cast5_fpu_end(bool fp
|
||||
static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
|
||||
bool enc)
|
||||
{
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
const unsigned int bsize = CAST5_BLOCK_SIZE;
|
||||
unsigned int nbytes;
|
||||
@@ -75,7 +75,7 @@ static int ecb_crypt(struct blkcipher_de
|
||||
u8 *wsrc = walk->src.virt.addr;
|
||||
u8 *wdst = walk->dst.virt.addr;
|
||||
|
||||
- fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
|
||||
+ fpu_enabled = cast5_fpu_begin(false, nbytes);
|
||||
|
||||
/* Process multi-block batch */
|
||||
if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
|
||||
@@ -103,10 +103,9 @@ static int ecb_crypt(struct blkcipher_de
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
done:
|
||||
+ cast5_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, walk, nbytes);
|
||||
}
|
||||
-
|
||||
- cast5_fpu_end(fpu_enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -227,7 +226,7 @@ static unsigned int __cbc_decrypt(struct
|
||||
static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
@@ -236,12 +235,11 @@ static int cbc_decrypt(struct blkcipher_
|
||||
desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
- fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
|
||||
+ fpu_enabled = cast5_fpu_begin(false, nbytes);
|
||||
nbytes = __cbc_decrypt(desc, &walk);
|
||||
+ cast5_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
-
|
||||
- cast5_fpu_end(fpu_enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -311,7 +309,7 @@ static unsigned int __ctr_crypt(struct b
|
||||
static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
@@ -320,13 +318,12 @@ static int ctr_crypt(struct blkcipher_de
|
||||
desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
while ((nbytes = walk.nbytes) >= CAST5_BLOCK_SIZE) {
|
||||
- fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
|
||||
+ fpu_enabled = cast5_fpu_begin(false, nbytes);
|
||||
nbytes = __ctr_crypt(desc, &walk);
|
||||
+ cast5_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
- cast5_fpu_end(fpu_enabled);
|
||||
-
|
||||
if (walk.nbytes) {
|
||||
ctr_crypt_final(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, 0);
|
||||
--- a/arch/x86/crypto/glue_helper.c
|
||||
+++ b/arch/x86/crypto/glue_helper.c
|
||||
@@ -39,7 +39,7 @@ static int __glue_ecb_crypt_128bit(const
|
||||
void *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
const unsigned int bsize = 128 / 8;
|
||||
unsigned int nbytes, i, func_bytes;
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
int err;
|
||||
|
||||
err = blkcipher_walk_virt(desc, walk);
|
||||
@@ -49,7 +49,7 @@ static int __glue_ecb_crypt_128bit(const
|
||||
u8 *wdst = walk->dst.virt.addr;
|
||||
|
||||
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
|
||||
- desc, fpu_enabled, nbytes);
|
||||
+ desc, false, nbytes);
|
||||
|
||||
for (i = 0; i < gctx->num_funcs; i++) {
|
||||
func_bytes = bsize * gctx->funcs[i].num_blocks;
|
||||
@@ -71,10 +71,10 @@ static int __glue_ecb_crypt_128bit(const
|
||||
}
|
||||
|
||||
done:
|
||||
+ glue_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, walk, nbytes);
|
||||
}
|
||||
|
||||
- glue_fpu_end(fpu_enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ int glue_cbc_decrypt_128bit(const struct
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
const unsigned int bsize = 128 / 8;
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
@@ -203,12 +203,12 @@ int glue_cbc_decrypt_128bit(const struct
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
|
||||
- desc, fpu_enabled, nbytes);
|
||||
+ desc, false, nbytes);
|
||||
nbytes = __glue_cbc_decrypt_128bit(gctx, desc, &walk);
|
||||
+ glue_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
- glue_fpu_end(fpu_enabled);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(glue_cbc_decrypt_128bit);
|
||||
@@ -277,7 +277,7 @@ int glue_ctr_crypt_128bit(const struct c
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
const unsigned int bsize = 128 / 8;
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
@@ -286,13 +286,12 @@ int glue_ctr_crypt_128bit(const struct c
|
||||
|
||||
while ((nbytes = walk.nbytes) >= bsize) {
|
||||
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
|
||||
- desc, fpu_enabled, nbytes);
|
||||
+ desc, false, nbytes);
|
||||
nbytes = __glue_ctr_crypt_128bit(gctx, desc, &walk);
|
||||
+ glue_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
- glue_fpu_end(fpu_enabled);
|
||||
-
|
||||
if (walk.nbytes) {
|
||||
glue_ctr_crypt_final_128bit(
|
||||
gctx->funcs[gctx->num_funcs - 1].fn_u.ctr, desc, &walk);
|
||||
@@ -347,7 +346,7 @@ int glue_xts_crypt_128bit(const struct c
|
||||
void *tweak_ctx, void *crypt_ctx)
|
||||
{
|
||||
const unsigned int bsize = 128 / 8;
|
||||
- bool fpu_enabled = false;
|
||||
+ bool fpu_enabled;
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
@@ -360,21 +359,21 @@ int glue_xts_crypt_128bit(const struct c
|
||||
|
||||
/* set minimum length to bsize, for tweak_fn */
|
||||
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
|
||||
- desc, fpu_enabled,
|
||||
+ desc, false,
|
||||
nbytes < bsize ? bsize : nbytes);
|
||||
-
|
||||
/* calculate first value of T */
|
||||
tweak_fn(tweak_ctx, walk.iv, walk.iv);
|
||||
+ glue_fpu_end(fpu_enabled);
|
||||
|
||||
while (nbytes) {
|
||||
+ fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
|
||||
+ desc, false, nbytes);
|
||||
nbytes = __glue_xts_crypt_128bit(gctx, crypt_ctx, desc, &walk);
|
||||
|
||||
+ glue_fpu_end(fpu_enabled);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
nbytes = walk.nbytes;
|
||||
}
|
||||
-
|
||||
- glue_fpu_end(fpu_enabled);
|
||||
-
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(glue_xts_crypt_128bit);
|
|
@ -1,26 +0,0 @@
|
|||
Subject: debugobjects: Make RT aware
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sun, 17 Jul 2011 21:41:35 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Avoid filling the pool / allocating memory with irqs off().
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
lib/debugobjects.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/lib/debugobjects.c
|
||||
+++ b/lib/debugobjects.c
|
||||
@@ -309,7 +309,10 @@ static void
|
||||
struct debug_obj *obj;
|
||||
unsigned long flags;
|
||||
|
||||
- fill_pool();
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ if (preempt_count() == 0 && !irqs_disabled())
|
||||
+#endif
|
||||
+ fill_pool();
|
||||
|
||||
db = get_bucket((unsigned long) addr);
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
Subject: dm: Make rt aware
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Mon, 14 Nov 2011 23:06:09 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Use the BUG_ON_NORT variant for the irq_disabled() checks. RT has
|
||||
interrupts legitimately enabled here as we cant deadlock against the
|
||||
irq thread due to the "sleeping spinlocks" conversion.
|
||||
|
||||
Reported-by: Luis Claudio R. Goncalves <lclaudio@uudg.org>
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
drivers/md/dm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/md/dm.c
|
||||
+++ b/drivers/md/dm.c
|
||||
@@ -2126,7 +2126,7 @@ static void dm_request_fn(struct request
|
||||
/* Establish tio->ti before queuing work (map_tio_request) */
|
||||
tio->ti = ti;
|
||||
queue_kthread_work(&md->kworker, &tio->work);
|
||||
- BUG_ON(!irqs_disabled());
|
||||
+ BUG_ON_NONRT(!irqs_disabled());
|
||||
}
|
||||
|
||||
goto out;
|
|
@ -1,26 +0,0 @@
|
|||
From: Anders Roxell <anders.roxell@linaro.org>
|
||||
Date: Fri, 15 Jan 2016 20:21:12 +0100
|
||||
Subject: drivers/cpuidle: coupled: fix warning cpuidle_coupled_lock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Used multi_v7_defconfig+PREEMPT_RT_FULL=y and this caused a compilation
|
||||
warning without this fix:
|
||||
../drivers/cpuidle/coupled.c:122:21: warning: 'cpuidle_coupled_lock'
|
||||
defined but not used [-Wunused-variable]
|
||||
|
||||
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/cpuidle/coupled.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpuidle/coupled.c
|
||||
+++ b/drivers/cpuidle/coupled.c
|
||||
@@ -119,7 +119,6 @@ struct cpuidle_coupled {
|
||||
|
||||
#define CPUIDLE_COUPLED_NOT_IDLE (-1)
|
||||
|
||||
-static DEFINE_MUTEX(cpuidle_coupled_lock);
|
||||
static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb);
|
||||
|
||||
/*
|
|
@ -1,33 +0,0 @@
|
|||
From: Anders Roxell <anders.roxell@linaro.org>
|
||||
Date: Fri, 15 Jan 2016 01:09:43 +0100
|
||||
Subject: drivers/media: vsp1_video: fix compile error
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
This was found with the -RT patch enabled, but the fix should apply to
|
||||
non-RT also.
|
||||
|
||||
Compilation error without this fix:
|
||||
../drivers/media/platform/vsp1/vsp1_video.c: In function
|
||||
'vsp1_pipeline_stopped':
|
||||
../drivers/media/platform/vsp1/vsp1_video.c:524:2: error: expected
|
||||
expression before 'do'
|
||||
spin_unlock_irqrestore(&pipe->irqlock, flags);
|
||||
^
|
||||
|
||||
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/media/platform/vsp1/vsp1_video.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/platform/vsp1/vsp1_video.c
|
||||
+++ b/drivers/media/platform/vsp1/vsp1_video.c
|
||||
@@ -520,7 +520,7 @@ static bool vsp1_pipeline_stopped(struct
|
||||
bool stopped;
|
||||
|
||||
spin_lock_irqsave(&pipe->irqlock, flags);
|
||||
- stopped = pipe->state == VSP1_PIPELINE_STOPPED,
|
||||
+ stopped = pipe->state == VSP1_PIPELINE_STOPPED;
|
||||
spin_unlock_irqrestore(&pipe->irqlock, flags);
|
||||
|
||||
return stopped;
|
|
@ -1,26 +0,0 @@
|
|||
From: Ingo Molnar <mingo@elte.hu>
|
||||
Date: Fri, 3 Jul 2009 08:29:24 -0500
|
||||
Subject: drivers/net: Use disable_irq_nosync() in 8139too
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Use disable_irq_nosync() instead of disable_irq() as this might be
|
||||
called in atomic context with netpoll.
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/net/ethernet/realtek/8139too.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/realtek/8139too.c
|
||||
+++ b/drivers/net/ethernet/realtek/8139too.c
|
||||
@@ -2229,7 +2229,7 @@ static void rtl8139_poll_controller(stru
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
const int irq = tp->pci_dev->irq;
|
||||
|
||||
- disable_irq(irq);
|
||||
+ disable_irq_nosync(irq);
|
||||
rtl8139_interrupt(irq, dev);
|
||||
enable_irq(irq);
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sat, 20 Jun 2009 11:36:54 +0200
|
||||
Subject: drivers/net: fix livelock issues
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Preempt-RT runs into a live lock issue with the NETDEV_TX_LOCKED micro
|
||||
optimization. The reason is that the softirq thread is rescheduling
|
||||
itself on that return value. Depending on priorities it starts to
|
||||
monoplize the CPU and livelock on UP systems.
|
||||
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 6 +-----
|
||||
drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 3 +--
|
||||
drivers/net/ethernet/chelsio/cxgb/sge.c | 3 +--
|
||||
drivers/net/ethernet/neterion/s2io.c | 7 +------
|
||||
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 6 ++----
|
||||
drivers/net/ethernet/tehuti/tehuti.c | 9 ++-------
|
||||
drivers/net/rionet.c | 6 +-----
|
||||
7 files changed, 9 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||||
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||||
@@ -2221,11 +2221,7 @@ static netdev_tx_t atl1c_xmit_frame(stru
|
||||
}
|
||||
|
||||
tpd_req = atl1c_cal_tpd_req(skb);
|
||||
- if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
|
||||
- if (netif_msg_pktdata(adapter))
|
||||
- dev_info(&adapter->pdev->dev, "tx locked\n");
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&adapter->tx_lock, flags);
|
||||
|
||||
if (atl1c_tpd_avail(adapter, type) < tpd_req) {
|
||||
/* no enough descriptor, just stop queue */
|
||||
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
|
||||
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
|
||||
@@ -1880,8 +1880,7 @@ static netdev_tx_t atl1e_xmit_frame(stru
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
tpd_req = atl1e_cal_tdp_req(skb);
|
||||
- if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
+ spin_lock_irqsave(&adapter->tx_lock, flags);
|
||||
|
||||
if (atl1e_tpd_avail(adapter) < tpd_req) {
|
||||
/* no enough descriptor, just stop queue */
|
||||
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
|
||||
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
|
||||
@@ -1664,8 +1664,7 @@ static int t1_sge_tx(struct sk_buff *skb
|
||||
struct cmdQ *q = &sge->cmdQ[qid];
|
||||
unsigned int credits, pidx, genbit, count, use_sched_skb = 0;
|
||||
|
||||
- if (!spin_trylock(&q->lock))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
+ spin_lock(&q->lock);
|
||||
|
||||
reclaim_completed_tx(sge, q);
|
||||
|
||||
--- a/drivers/net/ethernet/neterion/s2io.c
|
||||
+++ b/drivers/net/ethernet/neterion/s2io.c
|
||||
@@ -4084,12 +4084,7 @@ static netdev_tx_t s2io_xmit(struct sk_b
|
||||
[skb->priority & (MAX_TX_FIFOS - 1)];
|
||||
fifo = &mac_control->fifos[queue];
|
||||
|
||||
- if (do_spin_lock)
|
||||
- spin_lock_irqsave(&fifo->tx_lock, flags);
|
||||
- else {
|
||||
- if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&fifo->tx_lock, flags);
|
||||
|
||||
if (sp->config.multiq) {
|
||||
if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
|
||||
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
||||
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
||||
@@ -2137,10 +2137,8 @@ static int pch_gbe_xmit_frame(struct sk_
|
||||
struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
|
||||
unsigned long flags;
|
||||
|
||||
- if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) {
|
||||
- /* Collision - tell upper layer to requeue */
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&tx_ring->tx_lock, flags);
|
||||
+
|
||||
if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) {
|
||||
netif_stop_queue(netdev);
|
||||
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
|
||||
--- a/drivers/net/ethernet/tehuti/tehuti.c
|
||||
+++ b/drivers/net/ethernet/tehuti/tehuti.c
|
||||
@@ -1629,13 +1629,8 @@ static netdev_tx_t bdx_tx_transmit(struc
|
||||
unsigned long flags;
|
||||
|
||||
ENTER;
|
||||
- local_irq_save(flags);
|
||||
- if (!spin_trylock(&priv->tx_lock)) {
|
||||
- local_irq_restore(flags);
|
||||
- DBG("%s[%s]: TX locked, returning NETDEV_TX_LOCKED\n",
|
||||
- BDX_DRV_NAME, ndev->name);
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+
|
||||
+ spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
|
||||
/* build tx descriptor */
|
||||
BDX_ASSERT(f->m.wptr >= f->m.memsz); /* started with valid wptr */
|
||||
--- a/drivers/net/rionet.c
|
||||
+++ b/drivers/net/rionet.c
|
||||
@@ -174,11 +174,7 @@ static int rionet_start_xmit(struct sk_b
|
||||
unsigned long flags;
|
||||
int add_num = 1;
|
||||
|
||||
- local_irq_save(flags);
|
||||
- if (!spin_trylock(&rnet->tx_lock)) {
|
||||
- local_irq_restore(flags);
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&rnet->tx_lock, flags);
|
||||
|
||||
if (is_multicast_ether_addr(eth->h_dest))
|
||||
add_num = nets[rnet->mport->id].nact;
|
|
@ -1,49 +0,0 @@
|
|||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Fri, 3 Jul 2009 08:30:00 -0500
|
||||
Subject: drivers/net: vortex fix locking issues
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Argh, cut and paste wasn't enough...
|
||||
|
||||
Use this patch instead. It needs an irq disable. But, believe it or not,
|
||||
on SMP this is actually better. If the irq is shared (as it is in Mark's
|
||||
case), we don't stop the irq of other devices from being handled on
|
||||
another CPU (unfortunately for Mark, he pinned all interrupts to one CPU).
|
||||
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
drivers/net/ethernet/3com/3c59x.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
|
||||
--- a/drivers/net/ethernet/3com/3c59x.c
|
||||
+++ b/drivers/net/ethernet/3com/3c59x.c
|
||||
@@ -842,9 +842,9 @@ static void poll_vortex(struct net_devic
|
||||
{
|
||||
struct vortex_private *vp = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1916,12 +1916,12 @@ static void vortex_tx_timeout(struct net
|
||||
* Block interrupts because vortex_interrupt does a bare spin_lock()
|
||||
*/
|
||||
unsigned long flags;
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
if (vp->full_bus_master_tx)
|
||||
boomerang_interrupt(dev->irq, dev);
|
||||
else
|
||||
vortex_interrupt(dev->irq, dev);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From: Ingo Molnar <mingo@elte.hu>
|
||||
Date: Fri, 3 Jul 2009 08:29:30 -0500
|
||||
Subject: drivers: random: Reduce preempt disabled region
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
No need to keep preemption disabled across the whole function.
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/char/random.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/char/random.c
|
||||
+++ b/drivers/char/random.c
|
||||
@@ -796,8 +796,6 @@ static void add_timer_randomness(struct
|
||||
} sample;
|
||||
long delta, delta2, delta3;
|
||||
|
||||
- preempt_disable();
|
||||
-
|
||||
sample.jiffies = jiffies;
|
||||
sample.cycles = random_get_entropy();
|
||||
sample.num = num;
|
||||
@@ -838,7 +836,6 @@ static void add_timer_randomness(struct
|
||||
*/
|
||||
credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
|
||||
}
|
||||
- preempt_enable();
|
||||
}
|
||||
|
||||
void add_input_randomness(unsigned int type, unsigned int code,
|
|
@ -1,43 +0,0 @@
|
|||
Subject: tty/serial/omap: Make the locking RT aware
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Thu, 28 Jul 2011 13:32:57 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The lock is a sleeping lock and local_irq_save() is not the
|
||||
optimsation we are looking for. Redo it to make it work on -RT and
|
||||
non-RT.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
drivers/tty/serial/omap-serial.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/tty/serial/omap-serial.c
|
||||
+++ b/drivers/tty/serial/omap-serial.c
|
||||
@@ -1257,13 +1257,10 @@ serial_omap_console_write(struct console
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
- local_irq_save(flags);
|
||||
- if (up->port.sysrq)
|
||||
- locked = 0;
|
||||
- else if (oops_in_progress)
|
||||
- locked = spin_trylock(&up->port.lock);
|
||||
+ if (up->port.sysrq || oops_in_progress)
|
||||
+ locked = spin_trylock_irqsave(&up->port.lock, flags);
|
||||
else
|
||||
- spin_lock(&up->port.lock);
|
||||
+ spin_lock_irqsave(&up->port.lock, flags);
|
||||
|
||||
/*
|
||||
* First save the IER then disable the interrupts
|
||||
@@ -1292,8 +1289,7 @@ serial_omap_console_write(struct console
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
if (locked)
|
||||
- spin_unlock(&up->port.lock);
|
||||
- local_irq_restore(flags);
|
||||
+ spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
}
|
||||
|
||||
static int __init
|
|
@ -1,48 +0,0 @@
|
|||
Subject: tty/serial/pl011: Make the locking work on RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Tue, 08 Jan 2013 21:36:51 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The lock is a sleeping lock and local_irq_save() is not the optimsation
|
||||
we are looking for. Redo it to make it work on -RT and non-RT.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
drivers/tty/serial/amba-pl011.c | 15 ++++++++++-----
|
||||
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/tty/serial/amba-pl011.c
|
||||
+++ b/drivers/tty/serial/amba-pl011.c
|
||||
@@ -2067,13 +2067,19 @@ pl011_console_write(struct console *co,
|
||||
|
||||
clk_enable(uap->clk);
|
||||
|
||||
- local_irq_save(flags);
|
||||
+ /*
|
||||
+ * local_irq_save(flags);
|
||||
+ *
|
||||
+ * This local_irq_save() is nonsense. If we come in via sysrq
|
||||
+ * handling then interrupts are already disabled. Aside of
|
||||
+ * that the port.sysrq check is racy on SMP regardless.
|
||||
+ */
|
||||
if (uap->port.sysrq)
|
||||
locked = 0;
|
||||
else if (oops_in_progress)
|
||||
- locked = spin_trylock(&uap->port.lock);
|
||||
+ locked = spin_trylock_irqsave(&uap->port.lock, flags);
|
||||
else
|
||||
- spin_lock(&uap->port.lock);
|
||||
+ spin_lock_irqsave(&uap->port.lock, flags);
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
@@ -2098,8 +2104,7 @@ pl011_console_write(struct console *co,
|
||||
writew(old_cr, uap->port.membase + UART011_CR);
|
||||
|
||||
if (locked)
|
||||
- spin_unlock(&uap->port.lock);
|
||||
- local_irq_restore(flags);
|
||||
+ spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
|
||||
clk_disable(uap->clk);
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 25 Apr 2013 18:12:52 +0200
|
||||
Subject: drm/i915: drop trace_i915_gem_ring_dispatch on rt
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
This tracepoint is responsible for:
|
||||
|
||||
|[<814cc358>] __schedule_bug+0x4d/0x59
|
||||
|[<814d24cc>] __schedule+0x88c/0x930
|
||||
|[<814d3b90>] ? _raw_spin_unlock_irqrestore+0x40/0x50
|
||||
|[<814d3b95>] ? _raw_spin_unlock_irqrestore+0x45/0x50
|
||||
|[<810b57b5>] ? task_blocks_on_rt_mutex+0x1f5/0x250
|
||||
|[<814d27d9>] schedule+0x29/0x70
|
||||
|[<814d3423>] rt_spin_lock_slowlock+0x15b/0x278
|
||||
|[<814d3786>] rt_spin_lock+0x26/0x30
|
||||
|[<a00dced9>] gen6_gt_force_wake_get+0x29/0x60 [i915]
|
||||
|[<a00e183f>] gen6_ring_get_irq+0x5f/0x100 [i915]
|
||||
|[<a00b2a33>] ftrace_raw_event_i915_gem_ring_dispatch+0xe3/0x100 [i915]
|
||||
|[<a00ac1b3>] i915_gem_do_execbuffer.isra.13+0xbd3/0x1430 [i915]
|
||||
|[<810f8943>] ? trace_buffer_unlock_commit+0x43/0x60
|
||||
|[<8113e8d2>] ? ftrace_raw_event_kmem_alloc+0xd2/0x180
|
||||
|[<8101d063>] ? native_sched_clock+0x13/0x80
|
||||
|[<a00acf29>] i915_gem_execbuffer2+0x99/0x280 [i915]
|
||||
|[<a00114a3>] drm_ioctl+0x4c3/0x570 [drm]
|
||||
|[<8101d0d9>] ? sched_clock+0x9/0x10
|
||||
|[<a00ace90>] ? i915_gem_execbuffer+0x480/0x480 [i915]
|
||||
|[<810f1c18>] ? rb_commit+0x68/0xa0
|
||||
|[<810f1c6c>] ? ring_buffer_unlock_commit+0x1c/0xa0
|
||||
|[<81197467>] do_vfs_ioctl+0x97/0x540
|
||||
|[<81021318>] ? ftrace_raw_event_sys_enter+0xd8/0x130
|
||||
|[<811979a1>] sys_ioctl+0x91/0xb0
|
||||
|[<814db931>] tracesys+0xe1/0xe6
|
||||
|
||||
Chris Wilson does not like to move i915_trace_irq_get() out of the macro
|
||||
|
||||
|No. This enables the IRQ, as well as making a number of
|
||||
|very expensively serialised read, unconditionally.
|
||||
|
||||
so it is gone now on RT.
|
||||
|
||||
|
||||
Reported-by: Joakim Hernberg <jbh@alchemy.lu>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -1264,7 +1264,9 @@ i915_gem_ringbuffer_submission(struct i9
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
|
||||
+#endif
|
||||
|
||||
i915_gem_execbuffer_move_to_active(vmas, params->request);
|
||||
i915_gem_execbuffer_retire_commands(params);
|
|
@ -1,99 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Sun, 16 Aug 2015 14:27:50 +0200
|
||||
Subject: dump stack: don't disable preemption during trace
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
I see here large latencies during a stack dump on x86. The
|
||||
preempt_disable() and get_cpu() should forbid moving the task to another
|
||||
CPU during a stack dump and avoiding two stack traces in parallel on the
|
||||
same CPU. However a stack trace from a second CPU may still happen in
|
||||
parallel. Also nesting is allowed so a stack trace happens in
|
||||
process-context and we may have another one from IRQ context. With migrate
|
||||
disable we keep this code preemptible and allow a second backtrace on
|
||||
the same CPU by another task.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/x86/kernel/dumpstack_32.c | 4 ++--
|
||||
arch/x86/kernel/dumpstack_64.c | 8 ++++----
|
||||
lib/dump_stack.c | 4 ++--
|
||||
3 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/dumpstack_32.c
|
||||
+++ b/arch/x86/kernel/dumpstack_32.c
|
||||
@@ -42,7 +42,7 @@ void dump_trace(struct task_struct *task
|
||||
unsigned long *stack, unsigned long bp,
|
||||
const struct stacktrace_ops *ops, void *data)
|
||||
{
|
||||
- const unsigned cpu = get_cpu();
|
||||
+ const unsigned cpu = get_cpu_light();
|
||||
int graph = 0;
|
||||
u32 *prev_esp;
|
||||
|
||||
@@ -86,7 +86,7 @@ void dump_trace(struct task_struct *task
|
||||
break;
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
}
|
||||
EXPORT_SYMBOL(dump_trace);
|
||||
|
||||
--- a/arch/x86/kernel/dumpstack_64.c
|
||||
+++ b/arch/x86/kernel/dumpstack_64.c
|
||||
@@ -152,7 +152,7 @@ void dump_trace(struct task_struct *task
|
||||
unsigned long *stack, unsigned long bp,
|
||||
const struct stacktrace_ops *ops, void *data)
|
||||
{
|
||||
- const unsigned cpu = get_cpu();
|
||||
+ const unsigned cpu = get_cpu_light();
|
||||
struct thread_info *tinfo;
|
||||
unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
|
||||
unsigned long dummy;
|
||||
@@ -241,7 +241,7 @@ void dump_trace(struct task_struct *task
|
||||
* This handles the process stack:
|
||||
*/
|
||||
bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
}
|
||||
EXPORT_SYMBOL(dump_trace);
|
||||
|
||||
@@ -255,7 +255,7 @@ show_stack_log_lvl(struct task_struct *t
|
||||
int cpu;
|
||||
int i;
|
||||
|
||||
- preempt_disable();
|
||||
+ migrate_disable();
|
||||
cpu = smp_processor_id();
|
||||
|
||||
irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
|
||||
@@ -291,7 +291,7 @@ show_stack_log_lvl(struct task_struct *t
|
||||
pr_cont(" %016lx", *stack++);
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
- preempt_enable();
|
||||
+ migrate_enable();
|
||||
|
||||
pr_cont("\n");
|
||||
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
|
||||
--- a/lib/dump_stack.c
|
||||
+++ b/lib/dump_stack.c
|
||||
@@ -33,7 +33,7 @@ asmlinkage __visible void dump_stack(voi
|
||||
* Permit this cpu to perform nested stack dumps while serialising
|
||||
* against other CPUs
|
||||
*/
|
||||
- preempt_disable();
|
||||
+ migrate_disable();
|
||||
|
||||
retry:
|
||||
cpu = smp_processor_id();
|
||||
@@ -52,7 +52,7 @@ asmlinkage __visible void dump_stack(voi
|
||||
if (!was_locked)
|
||||
atomic_set(&dump_lock, -1);
|
||||
|
||||
- preempt_enable();
|
||||
+ migrate_enable();
|
||||
}
|
||||
#else
|
||||
asmlinkage __visible void dump_stack(void)
|
|
@ -1,31 +0,0 @@
|
|||
Subject: fs/epoll: Do not disable preemption on RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 08 Jul 2011 16:35:35 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
ep_call_nested() takes a sleeping lock so we can't disable preemption.
|
||||
The light version is enough since ep_call_nested() doesn't mind beeing
|
||||
invoked twice on the same CPU.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
fs/eventpoll.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/eventpoll.c
|
||||
+++ b/fs/eventpoll.c
|
||||
@@ -505,12 +505,12 @@ static int ep_poll_wakeup_proc(void *pri
|
||||
*/
|
||||
static void ep_poll_safewake(wait_queue_head_t *wq)
|
||||
{
|
||||
- int this_cpu = get_cpu();
|
||||
+ int this_cpu = get_cpu_light();
|
||||
|
||||
ep_call_nested(&poll_safewake_ncalls, EP_MAX_NESTS,
|
||||
ep_poll_wakeup_proc, NULL, wq, (void *) (long) this_cpu);
|
||||
|
||||
- put_cpu();
|
||||
+ put_cpu_light();
|
||||
}
|
||||
|
||||
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
|
|
@ -1,107 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Mon, 16 Feb 2015 18:49:10 +0100
|
||||
Subject: fs/aio: simple simple work
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
|BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:768
|
||||
|in_atomic(): 1, irqs_disabled(): 0, pid: 26, name: rcuos/2
|
||||
|2 locks held by rcuos/2/26:
|
||||
| #0: (rcu_callback){.+.+..}, at: [<ffffffff810b1a12>] rcu_nocb_kthread+0x1e2/0x380
|
||||
| #1: (rcu_read_lock_sched){.+.+..}, at: [<ffffffff812acd26>] percpu_ref_kill_rcu+0xa6/0x1c0
|
||||
|Preemption disabled at:[<ffffffff810b1a93>] rcu_nocb_kthread+0x263/0x380
|
||||
|Call Trace:
|
||||
| [<ffffffff81582e9e>] dump_stack+0x4e/0x9c
|
||||
| [<ffffffff81077aeb>] __might_sleep+0xfb/0x170
|
||||
| [<ffffffff81589304>] rt_spin_lock+0x24/0x70
|
||||
| [<ffffffff811c5790>] free_ioctx_users+0x30/0x130
|
||||
| [<ffffffff812ace34>] percpu_ref_kill_rcu+0x1b4/0x1c0
|
||||
| [<ffffffff810b1a93>] rcu_nocb_kthread+0x263/0x380
|
||||
| [<ffffffff8106e046>] kthread+0xd6/0xf0
|
||||
| [<ffffffff81591eec>] ret_from_fork+0x7c/0xb0
|
||||
|
||||
replace this preempt_disable() friendly swork.
|
||||
|
||||
Reported-By: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Suggested-by: Benjamin LaHaise <bcrl@kvack.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
fs/aio.c | 24 +++++++++++++++++-------
|
||||
1 file changed, 17 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/aio.c
|
||||
+++ b/fs/aio.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/ramfs.h>
|
||||
#include <linux/percpu-refcount.h>
|
||||
#include <linux/mount.h>
|
||||
+#include <linux/work-simple.h>
|
||||
|
||||
#include <asm/kmap_types.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -115,7 +116,7 @@ struct kioctx {
|
||||
struct page **ring_pages;
|
||||
long nr_pages;
|
||||
|
||||
- struct work_struct free_work;
|
||||
+ struct swork_event free_work;
|
||||
|
||||
/*
|
||||
* signals when all in-flight requests are done
|
||||
@@ -253,6 +254,7 @@ static int __init aio_setup(void)
|
||||
.mount = aio_mount,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
+ BUG_ON(swork_get());
|
||||
aio_mnt = kern_mount(&aio_fs);
|
||||
if (IS_ERR(aio_mnt))
|
||||
panic("Failed to create aio fs mount.");
|
||||
@@ -568,9 +570,9 @@ static int kiocb_cancel(struct aio_kiocb
|
||||
return cancel(&kiocb->common);
|
||||
}
|
||||
|
||||
-static void free_ioctx(struct work_struct *work)
|
||||
+static void free_ioctx(struct swork_event *sev)
|
||||
{
|
||||
- struct kioctx *ctx = container_of(work, struct kioctx, free_work);
|
||||
+ struct kioctx *ctx = container_of(sev, struct kioctx, free_work);
|
||||
|
||||
pr_debug("freeing %p\n", ctx);
|
||||
|
||||
@@ -589,8 +591,8 @@ static void free_ioctx_reqs(struct percp
|
||||
if (ctx->rq_wait && atomic_dec_and_test(&ctx->rq_wait->count))
|
||||
complete(&ctx->rq_wait->comp);
|
||||
|
||||
- INIT_WORK(&ctx->free_work, free_ioctx);
|
||||
- schedule_work(&ctx->free_work);
|
||||
+ INIT_SWORK(&ctx->free_work, free_ioctx);
|
||||
+ swork_queue(&ctx->free_work);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -598,9 +600,9 @@ static void free_ioctx_reqs(struct percp
|
||||
* and ctx->users has dropped to 0, so we know no more kiocbs can be submitted -
|
||||
* now it's safe to cancel any that need to be.
|
||||
*/
|
||||
-static void free_ioctx_users(struct percpu_ref *ref)
|
||||
+static void free_ioctx_users_work(struct swork_event *sev)
|
||||
{
|
||||
- struct kioctx *ctx = container_of(ref, struct kioctx, users);
|
||||
+ struct kioctx *ctx = container_of(sev, struct kioctx, free_work);
|
||||
struct aio_kiocb *req;
|
||||
|
||||
spin_lock_irq(&ctx->ctx_lock);
|
||||
@@ -619,6 +621,14 @@ static void free_ioctx_users(struct perc
|
||||
percpu_ref_put(&ctx->reqs);
|
||||
}
|
||||
|
||||
+static void free_ioctx_users(struct percpu_ref *ref)
|
||||
+{
|
||||
+ struct kioctx *ctx = container_of(ref, struct kioctx, users);
|
||||
+
|
||||
+ INIT_SWORK(&ctx->free_work, free_ioctx_users_work);
|
||||
+ swork_queue(&ctx->free_work);
|
||||
+}
|
||||
+
|
||||
static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
|
||||
{
|
||||
unsigned i, new_nr;
|
|
@ -1,23 +0,0 @@
|
|||
Subject: block: Turn off warning which is bogus on RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Tue, 14 Jun 2011 17:05:09 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
On -RT the context is always with IRQs enabled. Ignore this warning on -RT.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
block/blk-core.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/block/blk-core.c
|
||||
+++ b/block/blk-core.c
|
||||
@@ -233,7 +233,7 @@ EXPORT_SYMBOL(blk_start_queue_async);
|
||||
**/
|
||||
void blk_start_queue(struct request_queue *q)
|
||||
{
|
||||
- WARN_ON(!irqs_disabled());
|
||||
+ WARN_ON_NONRT(!irqs_disabled());
|
||||
|
||||
queue_flag_clear(QUEUE_FLAG_STOPPED, q);
|
||||
__blk_run_queue(q);
|
|
@ -1,86 +0,0 @@
|
|||
Subject: fs: dcache: Use cpu_chill() in trylock loops
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Wed, 07 Mar 2012 21:00:34 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Retry loops on RT might loop forever when the modifying side was
|
||||
preempted. Use cpu_chill() instead of cpu_relax() to let the system
|
||||
make progress.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
fs/autofs4/autofs_i.h | 1 +
|
||||
fs/autofs4/expire.c | 2 +-
|
||||
fs/dcache.c | 5 +++--
|
||||
fs/namespace.c | 3 ++-
|
||||
4 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/fs/autofs4/autofs_i.h
|
||||
+++ b/fs/autofs4/autofs_i.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
--- a/fs/autofs4/expire.c
|
||||
+++ b/fs/autofs4/expire.c
|
||||
@@ -150,7 +150,7 @@ static struct dentry *get_next_positive_
|
||||
parent = p->d_parent;
|
||||
if (!spin_trylock(&parent->d_lock)) {
|
||||
spin_unlock(&p->d_lock);
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
goto relock;
|
||||
}
|
||||
spin_unlock(&p->d_lock);
|
||||
--- a/fs/dcache.c
|
||||
+++ b/fs/dcache.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fsnotify.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/hash.h>
|
||||
@@ -589,7 +590,7 @@ static struct dentry *dentry_kill(struct
|
||||
|
||||
failed:
|
||||
spin_unlock(&dentry->d_lock);
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
return dentry; /* try again with same dentry */
|
||||
}
|
||||
|
||||
@@ -2398,7 +2399,7 @@ void d_delete(struct dentry * dentry)
|
||||
if (dentry->d_lockref.count == 1) {
|
||||
if (!spin_trylock(&inode->i_lock)) {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
goto again;
|
||||
}
|
||||
dentry->d_flags &= ~DCACHE_CANT_MOUNT;
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/mnt_namespace.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/namei.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/init.h> /* init_rootfs */
|
||||
@@ -355,7 +356,7 @@ int __mnt_want_write(struct vfsmount *m)
|
||||
smp_mb();
|
||||
while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD) {
|
||||
preempt_enable();
|
||||
- cpu_relax();
|
||||
+ cpu_chill();
|
||||
preempt_disable();
|
||||
}
|
||||
/*
|
|
@ -1,97 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 18 Mar 2011 10:11:25 +0100
|
||||
Subject: fs: jbd/jbd2: Make state lock and journal head lock rt safe
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
bit_spin_locks break under RT.
|
||||
|
||||
Based on a previous patch from Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
--
|
||||
include/linux/buffer_head.h | 8 ++++++++
|
||||
include/linux/jbd2.h | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 32 insertions(+)
|
||||
|
||||
--- a/include/linux/buffer_head.h
|
||||
+++ b/include/linux/buffer_head.h
|
||||
@@ -77,6 +77,10 @@ struct buffer_head {
|
||||
atomic_t b_count; /* users using this buffer_head */
|
||||
#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
spinlock_t b_uptodate_lock;
|
||||
+#if IS_ENABLED(CONFIG_JBD2)
|
||||
+ spinlock_t b_state_lock;
|
||||
+ spinlock_t b_journal_head_lock;
|
||||
+#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -108,6 +112,10 @@ static inline void buffer_head_init_lock
|
||||
{
|
||||
#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
spin_lock_init(&bh->b_uptodate_lock);
|
||||
+#if IS_ENABLED(CONFIG_JBD2)
|
||||
+ spin_lock_init(&bh->b_state_lock);
|
||||
+ spin_lock_init(&bh->b_journal_head_lock);
|
||||
+#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
--- a/include/linux/jbd2.h
|
||||
+++ b/include/linux/jbd2.h
|
||||
@@ -352,32 +352,56 @@ static inline struct journal_head *bh2jh
|
||||
|
||||
static inline void jbd_lock_bh_state(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
bit_spin_lock(BH_State, &bh->b_state);
|
||||
+#else
|
||||
+ spin_lock(&bh->b_state_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline int jbd_trylock_bh_state(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
return bit_spin_trylock(BH_State, &bh->b_state);
|
||||
+#else
|
||||
+ return spin_trylock(&bh->b_state_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
return bit_spin_is_locked(BH_State, &bh->b_state);
|
||||
+#else
|
||||
+ return spin_is_locked(&bh->b_state_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline void jbd_unlock_bh_state(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
bit_spin_unlock(BH_State, &bh->b_state);
|
||||
+#else
|
||||
+ spin_unlock(&bh->b_state_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
bit_spin_lock(BH_JournalHead, &bh->b_state);
|
||||
+#else
|
||||
+ spin_lock(&bh->b_journal_head_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
|
||||
{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
bit_spin_unlock(BH_JournalHead, &bh->b_state);
|
||||
+#else
|
||||
+ spin_unlock(&bh->b_journal_head_lock);
|
||||
+#endif
|
||||
}
|
||||
|
||||
#define J_ASSERT(assert) BUG_ON(!(assert))
|
|
@ -1,32 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Mon, 17 Feb 2014 17:30:03 +0100
|
||||
Subject: fs: jbd2: pull your plug when waiting for space
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Two cps in parallel managed to stall the the ext4 fs. It seems that
|
||||
journal code is either waiting for locks or sleeping waiting for
|
||||
something to happen. This seems similar to what Mike observed on ext3,
|
||||
here is his description:
|
||||
|
||||
|With an -rt kernel, and a heavy sync IO load, tasks can jam
|
||||
|up on journal locks without unplugging, which can lead to
|
||||
|terminal IO starvation. Unplug and schedule when waiting
|
||||
|for space.
|
||||
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
fs/jbd2/checkpoint.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/fs/jbd2/checkpoint.c
|
||||
+++ b/fs/jbd2/checkpoint.c
|
||||
@@ -116,6 +116,8 @@ void __jbd2_log_wait_for_space(journal_t
|
||||
nblocks = jbd2_space_needed(journal);
|
||||
while (jbd2_log_space_left(journal) < nblocks) {
|
||||
write_unlock(&journal->j_state_lock);
|
||||
+ if (current->plug)
|
||||
+ io_schedule();
|
||||
mutex_lock(&journal->j_checkpoint_mutex);
|
||||
|
||||
/*
|
|
@ -1,31 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sun, 19 Jul 2009 08:44:27 -0500
|
||||
Subject: fs: namespace preemption fix
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
On RT we cannot loop with preemption disabled here as
|
||||
mnt_make_readonly() might have been preempted. We can safely enable
|
||||
preemption while waiting for MNT_WRITE_HOLD to be cleared. Safe on !RT
|
||||
as well.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
fs/namespace.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -353,8 +353,11 @@ int __mnt_want_write(struct vfsmount *m)
|
||||
* incremented count after it has set MNT_WRITE_HOLD.
|
||||
*/
|
||||
smp_mb();
|
||||
- while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
|
||||
+ while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD) {
|
||||
+ preempt_enable();
|
||||
cpu_relax();
|
||||
+ preempt_disable();
|
||||
+ }
|
||||
/*
|
||||
* After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
|
||||
* be set to match its requirements. So we must not load that until
|
|
@ -1,60 +0,0 @@
|
|||
From: Mike Galbraith <efault@gmx.de>
|
||||
Date: Fri, 3 Jul 2009 08:44:12 -0500
|
||||
Subject: fs: ntfs: disable interrupt only on !RT
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
On Sat, 2007-10-27 at 11:44 +0200, Ingo Molnar wrote:
|
||||
> * Nick Piggin <nickpiggin@yahoo.com.au> wrote:
|
||||
>
|
||||
> > > [10138.175796] [<c0105de3>] show_trace+0x12/0x14
|
||||
> > > [10138.180291] [<c0105dfb>] dump_stack+0x16/0x18
|
||||
> > > [10138.184769] [<c011609f>] native_smp_call_function_mask+0x138/0x13d
|
||||
> > > [10138.191117] [<c0117606>] smp_call_function+0x1e/0x24
|
||||
> > > [10138.196210] [<c012f85c>] on_each_cpu+0x25/0x50
|
||||
> > > [10138.200807] [<c0115c74>] flush_tlb_all+0x1e/0x20
|
||||
> > > [10138.205553] [<c016caaf>] kmap_high+0x1b6/0x417
|
||||
> > > [10138.210118] [<c011ec88>] kmap+0x4d/0x4f
|
||||
> > > [10138.214102] [<c026a9d8>] ntfs_end_buffer_async_read+0x228/0x2f9
|
||||
> > > [10138.220163] [<c01a0e9e>] end_bio_bh_io_sync+0x26/0x3f
|
||||
> > > [10138.225352] [<c01a2b09>] bio_endio+0x42/0x6d
|
||||
> > > [10138.229769] [<c02c2a08>] __end_that_request_first+0x115/0x4ac
|
||||
> > > [10138.235682] [<c02c2da7>] end_that_request_chunk+0x8/0xa
|
||||
> > > [10138.241052] [<c0365943>] ide_end_request+0x55/0x10a
|
||||
> > > [10138.246058] [<c036dae3>] ide_dma_intr+0x6f/0xac
|
||||
> > > [10138.250727] [<c0366d83>] ide_intr+0x93/0x1e0
|
||||
> > > [10138.255125] [<c015afb4>] handle_IRQ_event+0x5c/0xc9
|
||||
> >
|
||||
> > Looks like ntfs is kmap()ing from interrupt context. Should be using
|
||||
> > kmap_atomic instead, I think.
|
||||
>
|
||||
> it's not atomic interrupt context but irq thread context - and -rt
|
||||
> remaps kmap_atomic() to kmap() internally.
|
||||
|
||||
Hm. Looking at the change to mm/bounce.c, perhaps I should do this
|
||||
instead?
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
fs/ntfs/aops.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/ntfs/aops.c
|
||||
+++ b/fs/ntfs/aops.c
|
||||
@@ -143,13 +143,13 @@ static void ntfs_end_buffer_async_read(s
|
||||
recs = PAGE_CACHE_SIZE / rec_size;
|
||||
/* Should have been verified before we got here... */
|
||||
BUG_ON(!recs);
|
||||
- local_irq_save(flags);
|
||||
+ local_irq_save_nort(flags);
|
||||
kaddr = kmap_atomic(page);
|
||||
for (i = 0; i < recs; i++)
|
||||
post_read_mst_fixup((NTFS_RECORD*)(kaddr +
|
||||
i * rec_size), rec_size);
|
||||
kunmap_atomic(kaddr);
|
||||
- local_irq_restore(flags);
|
||||
+ local_irq_restore_nort(flags);
|
||||
flush_dcache_page(page);
|
||||
if (likely(page_uptodate && !PageError(page)))
|
||||
SetPageUptodate(page);
|
|
@ -1,162 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 18 Mar 2011 09:18:52 +0100
|
||||
Subject: buffer_head: Replace bh_uptodate_lock for -rt
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Wrap the bit_spin_lock calls into a separate inline and add the RT
|
||||
replacements with a real spinlock.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
fs/buffer.c | 21 +++++++--------------
|
||||
fs/ntfs/aops.c | 10 +++-------
|
||||
include/linux/buffer_head.h | 34 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 44 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/fs/buffer.c
|
||||
+++ b/fs/buffer.c
|
||||
@@ -305,8 +305,7 @@ static void end_buffer_async_read(struct
|
||||
* decide that the page is now completely done.
|
||||
*/
|
||||
first = page_buffers(page);
|
||||
- local_irq_save(flags);
|
||||
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
|
||||
+ flags = bh_uptodate_lock_irqsave(first);
|
||||
clear_buffer_async_read(bh);
|
||||
unlock_buffer(bh);
|
||||
tmp = bh;
|
||||
@@ -319,8 +318,7 @@ static void end_buffer_async_read(struct
|
||||
}
|
||||
tmp = tmp->b_this_page;
|
||||
} while (tmp != bh);
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
|
||||
/*
|
||||
* If none of the buffers had errors and they are all
|
||||
@@ -332,9 +330,7 @@ static void end_buffer_async_read(struct
|
||||
return;
|
||||
|
||||
still_busy:
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
- return;
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -362,8 +358,7 @@ void end_buffer_async_write(struct buffe
|
||||
}
|
||||
|
||||
first = page_buffers(page);
|
||||
- local_irq_save(flags);
|
||||
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
|
||||
+ flags = bh_uptodate_lock_irqsave(first);
|
||||
|
||||
clear_buffer_async_write(bh);
|
||||
unlock_buffer(bh);
|
||||
@@ -375,15 +370,12 @@ void end_buffer_async_write(struct buffe
|
||||
}
|
||||
tmp = tmp->b_this_page;
|
||||
}
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
end_page_writeback(page);
|
||||
return;
|
||||
|
||||
still_busy:
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
- return;
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(end_buffer_async_write);
|
||||
|
||||
@@ -3325,6 +3317,7 @@ struct buffer_head *alloc_buffer_head(gf
|
||||
struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
|
||||
if (ret) {
|
||||
INIT_LIST_HEAD(&ret->b_assoc_buffers);
|
||||
+ buffer_head_init_locks(ret);
|
||||
preempt_disable();
|
||||
__this_cpu_inc(bh_accounting.nr);
|
||||
recalc_bh_state();
|
||||
--- a/fs/ntfs/aops.c
|
||||
+++ b/fs/ntfs/aops.c
|
||||
@@ -107,8 +107,7 @@ static void ntfs_end_buffer_async_read(s
|
||||
"0x%llx.", (unsigned long long)bh->b_blocknr);
|
||||
}
|
||||
first = page_buffers(page);
|
||||
- local_irq_save(flags);
|
||||
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
|
||||
+ flags = bh_uptodate_lock_irqsave(first);
|
||||
clear_buffer_async_read(bh);
|
||||
unlock_buffer(bh);
|
||||
tmp = bh;
|
||||
@@ -123,8 +122,7 @@ static void ntfs_end_buffer_async_read(s
|
||||
}
|
||||
tmp = tmp->b_this_page;
|
||||
} while (tmp != bh);
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
/*
|
||||
* If none of the buffers had errors then we can set the page uptodate,
|
||||
* but we first have to perform the post read mst fixups, if the
|
||||
@@ -159,9 +157,7 @@ static void ntfs_end_buffer_async_read(s
|
||||
unlock_page(page);
|
||||
return;
|
||||
still_busy:
|
||||
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
|
||||
- local_irq_restore(flags);
|
||||
- return;
|
||||
+ bh_uptodate_unlock_irqrestore(first, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
--- a/include/linux/buffer_head.h
|
||||
+++ b/include/linux/buffer_head.h
|
||||
@@ -75,8 +75,42 @@ struct buffer_head {
|
||||
struct address_space *b_assoc_map; /* mapping this buffer is
|
||||
associated with */
|
||||
atomic_t b_count; /* users using this buffer_head */
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ spinlock_t b_uptodate_lock;
|
||||
+#endif
|
||||
};
|
||||
|
||||
+static inline unsigned long bh_uptodate_lock_irqsave(struct buffer_head *bh)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
+ local_irq_save(flags);
|
||||
+ bit_spin_lock(BH_Uptodate_Lock, &bh->b_state);
|
||||
+#else
|
||||
+ spin_lock_irqsave(&bh->b_uptodate_lock, flags);
|
||||
+#endif
|
||||
+ return flags;
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+bh_uptodate_unlock_irqrestore(struct buffer_head *bh, unsigned long flags)
|
||||
+{
|
||||
+#ifndef CONFIG_PREEMPT_RT_BASE
|
||||
+ bit_spin_unlock(BH_Uptodate_Lock, &bh->b_state);
|
||||
+ local_irq_restore(flags);
|
||||
+#else
|
||||
+ spin_unlock_irqrestore(&bh->b_uptodate_lock, flags);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline void buffer_head_init_locks(struct buffer_head *bh)
|
||||
+{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ spin_lock_init(&bh->b_uptodate_lock);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* macro tricks to expand the set_buffer_foo(), clear_buffer_foo()
|
||||
* and buffer_foo() functions.
|
|
@ -1,74 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sun, 17 Jul 2011 21:56:42 +0200
|
||||
Subject: trace: Add migrate-disabled counter to tracing output
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
include/linux/trace_events.h | 2 ++
|
||||
kernel/trace/trace.c | 9 ++++++---
|
||||
kernel/trace/trace_events.c | 2 ++
|
||||
kernel/trace/trace_output.c | 5 +++++
|
||||
4 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/linux/trace_events.h
|
||||
+++ b/include/linux/trace_events.h
|
||||
@@ -66,6 +66,8 @@ struct trace_entry {
|
||||
unsigned char flags;
|
||||
unsigned char preempt_count;
|
||||
int pid;
|
||||
+ unsigned short migrate_disable;
|
||||
+ unsigned short padding;
|
||||
};
|
||||
|
||||
#define TRACE_EVENT_TYPE_MAX \
|
||||
--- a/kernel/trace/trace.c
|
||||
+++ b/kernel/trace/trace.c
|
||||
@@ -1663,6 +1663,8 @@ tracing_generic_entry_update(struct trac
|
||||
((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
|
||||
(tif_need_resched() ? TRACE_FLAG_NEED_RESCHED : 0) |
|
||||
(test_preempt_need_resched() ? TRACE_FLAG_PREEMPT_RESCHED : 0);
|
||||
+
|
||||
+ entry->migrate_disable = (tsk) ? __migrate_disabled(tsk) & 0xFF : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tracing_generic_entry_update);
|
||||
|
||||
@@ -2560,9 +2562,10 @@ static void print_lat_help_header(struct
|
||||
"# | / _----=> need-resched \n"
|
||||
"# || / _---=> hardirq/softirq \n"
|
||||
"# ||| / _--=> preempt-depth \n"
|
||||
- "# |||| / delay \n"
|
||||
- "# cmd pid ||||| time | caller \n"
|
||||
- "# \\ / ||||| \\ | / \n");
|
||||
+ "# |||| / _--=> migrate-disable\n"
|
||||
+ "# ||||| / delay \n"
|
||||
+ "# cmd pid |||||| time | caller \n"
|
||||
+ "# \\ / ||||| \\ | / \n");
|
||||
}
|
||||
|
||||
static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
|
||||
--- a/kernel/trace/trace_events.c
|
||||
+++ b/kernel/trace/trace_events.c
|
||||
@@ -186,6 +186,8 @@ static int trace_define_common_fields(vo
|
||||
__common_field(unsigned char, flags);
|
||||
__common_field(unsigned char, preempt_count);
|
||||
__common_field(int, pid);
|
||||
+ __common_field(unsigned short, migrate_disable);
|
||||
+ __common_field(unsigned short, padding);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- a/kernel/trace/trace_output.c
|
||||
+++ b/kernel/trace/trace_output.c
|
||||
@@ -428,6 +428,11 @@ int trace_print_lat_fmt(struct trace_seq
|
||||
else
|
||||
trace_seq_putc(s, '.');
|
||||
|
||||
+ if (entry->migrate_disable)
|
||||
+ trace_seq_printf(s, "%x", entry->migrate_disable);
|
||||
+ else
|
||||
+ trace_seq_putc(s, '.');
|
||||
+
|
||||
return !trace_seq_has_overflowed(s);
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Tue, 14 Jul 2015 14:26:34 +0200
|
||||
Subject: futex: Fix bug on when a requeued RT task times out
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Requeue with timeout causes a bug with PREEMPT_RT_FULL.
|
||||
|
||||
The bug comes from a timed out condition.
|
||||
|
||||
|
||||
TASK 1 TASK 2
|
||||
------ ------
|
||||
futex_wait_requeue_pi()
|
||||
futex_wait_queue_me()
|
||||
<timed out>
|
||||
|
||||
double_lock_hb();
|
||||
|
||||
raw_spin_lock(pi_lock);
|
||||
if (current->pi_blocked_on) {
|
||||
} else {
|
||||
current->pi_blocked_on = PI_WAKE_INPROGRESS;
|
||||
run_spin_unlock(pi_lock);
|
||||
spin_lock(hb->lock); <-- blocked!
|
||||
|
||||
|
||||
plist_for_each_entry_safe(this) {
|
||||
rt_mutex_start_proxy_lock();
|
||||
task_blocks_on_rt_mutex();
|
||||
BUG_ON(task->pi_blocked_on)!!!!
|
||||
|
||||
The BUG_ON() actually has a check for PI_WAKE_INPROGRESS, but the
|
||||
problem is that, after TASK 1 sets PI_WAKE_INPROGRESS, it then tries to
|
||||
grab the hb->lock, which it fails to do so. As the hb->lock is a mutex,
|
||||
it will block and set the "pi_blocked_on" to the hb->lock.
|
||||
|
||||
When TASK 2 goes to requeue it, the check for PI_WAKE_INPROGESS fails
|
||||
because the task1's pi_blocked_on is no longer set to that, but instead,
|
||||
set to the hb->lock.
|
||||
|
||||
The fix:
|
||||
|
||||
When calling rt_mutex_start_proxy_lock() a check is made to see
|
||||
if the proxy tasks pi_blocked_on is set. If so, exit out early.
|
||||
Otherwise set it to a new flag PI_REQUEUE_INPROGRESS, which notifies
|
||||
the proxy task that it is being requeued, and will handle things
|
||||
appropriately.
|
||||
|
||||
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/locking/rtmutex.c | 32 +++++++++++++++++++++++++++++++-
|
||||
kernel/locking/rtmutex_common.h | 1 +
|
||||
2 files changed, 32 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/locking/rtmutex.c
|
||||
+++ b/kernel/locking/rtmutex.c
|
||||
@@ -71,7 +71,8 @@ static void fixup_rt_mutex_waiters(struc
|
||||
|
||||
static int rt_mutex_real_waiter(struct rt_mutex_waiter *waiter)
|
||||
{
|
||||
- return waiter && waiter != PI_WAKEUP_INPROGRESS;
|
||||
+ return waiter && waiter != PI_WAKEUP_INPROGRESS &&
|
||||
+ waiter != PI_REQUEUE_INPROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1631,6 +1632,35 @@ int rt_mutex_start_proxy_lock(struct rt_
|
||||
return 1;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ /*
|
||||
+ * In PREEMPT_RT there's an added race.
|
||||
+ * If the task, that we are about to requeue, times out,
|
||||
+ * it can set the PI_WAKEUP_INPROGRESS. This tells the requeue
|
||||
+ * to skip this task. But right after the task sets
|
||||
+ * its pi_blocked_on to PI_WAKEUP_INPROGRESS it can then
|
||||
+ * block on the spin_lock(&hb->lock), which in RT is an rtmutex.
|
||||
+ * This will replace the PI_WAKEUP_INPROGRESS with the actual
|
||||
+ * lock that it blocks on. We *must not* place this task
|
||||
+ * on this proxy lock in that case.
|
||||
+ *
|
||||
+ * To prevent this race, we first take the task's pi_lock
|
||||
+ * and check if it has updated its pi_blocked_on. If it has,
|
||||
+ * we assume that it woke up and we return -EAGAIN.
|
||||
+ * Otherwise, we set the task's pi_blocked_on to
|
||||
+ * PI_REQUEUE_INPROGRESS, so that if the task is waking up
|
||||
+ * it will know that we are in the process of requeuing it.
|
||||
+ */
|
||||
+ raw_spin_lock_irq(&task->pi_lock);
|
||||
+ if (task->pi_blocked_on) {
|
||||
+ raw_spin_unlock_irq(&task->pi_lock);
|
||||
+ raw_spin_unlock(&lock->wait_lock);
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+ task->pi_blocked_on = PI_REQUEUE_INPROGRESS;
|
||||
+ raw_spin_unlock_irq(&task->pi_lock);
|
||||
+#endif
|
||||
+
|
||||
/* We enforce deadlock detection for futexes */
|
||||
ret = task_blocks_on_rt_mutex(lock, waiter, task,
|
||||
RT_MUTEX_FULL_CHAINWALK);
|
||||
--- a/kernel/locking/rtmutex_common.h
|
||||
+++ b/kernel/locking/rtmutex_common.h
|
||||
@@ -98,6 +98,7 @@ enum rtmutex_chainwalk {
|
||||
* PI-futex support (proxy locking functions, etc.):
|
||||
*/
|
||||
#define PI_WAKEUP_INPROGRESS ((struct rt_mutex_waiter *) 1)
|
||||
+#define PI_REQUEUE_INPROGRESS ((struct rt_mutex_waiter *) 2)
|
||||
|
||||
extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
|
||||
extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
|
|
@ -1,68 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 25 May 2012 16:59:47 +0200
|
||||
Subject: genirq: Add default affinity mask command line option
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
If we isolate CPUs, then we don't want random device interrupts on them. Even
|
||||
w/o the user space irq balancer enabled we can end up with irqs on non boot
|
||||
cpus and chasing newly requested interrupts is a tedious task.
|
||||
|
||||
Allow to restrict the default irq affinity mask.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
Documentation/kernel-parameters.txt | 9 +++++++++
|
||||
kernel/irq/irqdesc.c | 21 +++++++++++++++++++--
|
||||
2 files changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -1629,6 +1629,15 @@ bytes respectively. Such letter suffixes
|
||||
ip= [IP_PNP]
|
||||
See Documentation/filesystems/nfs/nfsroot.txt.
|
||||
|
||||
+ irqaffinity= [SMP] Set the default irq affinity mask
|
||||
+ Format:
|
||||
+ <cpu number>,...,<cpu number>
|
||||
+ or
|
||||
+ <cpu number>-<cpu number>
|
||||
+ (must be a positive range in ascending order)
|
||||
+ or a mixture
|
||||
+ <cpu number>,...,<cpu number>-<cpu number>
|
||||
+
|
||||
irqfixup [HW]
|
||||
When an interrupt is not handled search all handlers
|
||||
for it. Intended to get systems with badly broken
|
||||
--- a/kernel/irq/irqdesc.c
|
||||
+++ b/kernel/irq/irqdesc.c
|
||||
@@ -24,10 +24,27 @@
|
||||
static struct lock_class_key irq_desc_lock_class;
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
+static int __init irq_affinity_setup(char *str)
|
||||
+{
|
||||
+ zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
|
||||
+ cpulist_parse(str, irq_default_affinity);
|
||||
+ /*
|
||||
+ * Set at least the boot cpu. We don't want to end up with
|
||||
+ * bugreports caused by random comandline masks
|
||||
+ */
|
||||
+ cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
|
||||
+ return 1;
|
||||
+}
|
||||
+__setup("irqaffinity=", irq_affinity_setup);
|
||||
+
|
||||
static void __init init_irq_default_affinity(void)
|
||||
{
|
||||
- alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
|
||||
- cpumask_setall(irq_default_affinity);
|
||||
+#ifdef CONFIG_CPUMASK_OFFSTACK
|
||||
+ if (!irq_default_affinity)
|
||||
+ zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
|
||||
+#endif
|
||||
+ if (cpumask_empty(irq_default_affinity))
|
||||
+ cpumask_setall(irq_default_affinity);
|
||||
}
|
||||
#else
|
||||
static void __init init_irq_default_affinity(void)
|
|
@ -1,38 +0,0 @@
|
|||
From: Ingo Molnar <mingo@elte.hu>
|
||||
Date: Fri, 3 Jul 2009 08:29:57 -0500
|
||||
Subject: genirq: Disable irqpoll on -rt
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Creates long latencies for no value
|
||||
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
kernel/irq/spurious.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/kernel/irq/spurious.c
|
||||
+++ b/kernel/irq/spurious.c
|
||||
@@ -444,6 +444,10 @@ MODULE_PARM_DESC(noirqdebug, "Disable ir
|
||||
|
||||
static int __init irqfixup_setup(char *str)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ pr_warn("irqfixup boot option not supported w/ CONFIG_PREEMPT_RT_BASE\n");
|
||||
+ return 1;
|
||||
+#endif
|
||||
irqfixup = 1;
|
||||
printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
|
||||
printk(KERN_WARNING "This may impact system performance.\n");
|
||||
@@ -456,6 +460,10 @@ module_param(irqfixup, int, 0644);
|
||||
|
||||
static int __init irqpoll_setup(char *str)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ pr_warn("irqpoll boot option not supported w/ CONFIG_PREEMPT_RT_BASE\n");
|
||||
+ return 1;
|
||||
+#endif
|
||||
irqfixup = 2;
|
||||
printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
|
||||
"enabled\n");
|
|
@ -1,153 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 21 Aug 2013 17:48:46 +0200
|
||||
Subject: genirq: Do not invoke the affinity callback via a workqueue on RT
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Joe Korty reported, that __irq_set_affinity_locked() schedules a
|
||||
workqueue while holding a rawlock which results in a might_sleep()
|
||||
warning.
|
||||
This patch moves the invokation into a process context so that we only
|
||||
wakeup() a process while holding the lock.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/linux/interrupt.h | 2 +
|
||||
kernel/irq/manage.c | 79 ++++++++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 78 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/linux/interrupt.h
|
||||
+++ b/include/linux/interrupt.h
|
||||
@@ -206,6 +206,7 @@ extern void resume_device_irqs(void);
|
||||
* @irq: Interrupt to which notification applies
|
||||
* @kref: Reference count, for internal use
|
||||
* @work: Work item, for internal use
|
||||
+ * @list: List item for deferred callbacks
|
||||
* @notify: Function to be called on change. This will be
|
||||
* called in process context.
|
||||
* @release: Function to be called on release. This will be
|
||||
@@ -217,6 +218,7 @@ struct irq_affinity_notify {
|
||||
unsigned int irq;
|
||||
struct kref kref;
|
||||
struct work_struct work;
|
||||
+ struct list_head list;
|
||||
void (*notify)(struct irq_affinity_notify *, const cpumask_t *mask);
|
||||
void (*release)(struct kref *ref);
|
||||
};
|
||||
--- a/kernel/irq/manage.c
|
||||
+++ b/kernel/irq/manage.c
|
||||
@@ -183,6 +183,62 @@ static inline void
|
||||
irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { }
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+static void _irq_affinity_notify(struct irq_affinity_notify *notify);
|
||||
+static struct task_struct *set_affinity_helper;
|
||||
+static LIST_HEAD(affinity_list);
|
||||
+static DEFINE_RAW_SPINLOCK(affinity_list_lock);
|
||||
+
|
||||
+static int set_affinity_thread(void *unused)
|
||||
+{
|
||||
+ while (1) {
|
||||
+ struct irq_affinity_notify *notify;
|
||||
+ int empty;
|
||||
+
|
||||
+ set_current_state(TASK_INTERRUPTIBLE);
|
||||
+
|
||||
+ raw_spin_lock_irq(&affinity_list_lock);
|
||||
+ empty = list_empty(&affinity_list);
|
||||
+ raw_spin_unlock_irq(&affinity_list_lock);
|
||||
+
|
||||
+ if (empty)
|
||||
+ schedule();
|
||||
+ if (kthread_should_stop())
|
||||
+ break;
|
||||
+ set_current_state(TASK_RUNNING);
|
||||
+try_next:
|
||||
+ notify = NULL;
|
||||
+
|
||||
+ raw_spin_lock_irq(&affinity_list_lock);
|
||||
+ if (!list_empty(&affinity_list)) {
|
||||
+ notify = list_first_entry(&affinity_list,
|
||||
+ struct irq_affinity_notify, list);
|
||||
+ list_del_init(¬ify->list);
|
||||
+ }
|
||||
+ raw_spin_unlock_irq(&affinity_list_lock);
|
||||
+
|
||||
+ if (!notify)
|
||||
+ continue;
|
||||
+ _irq_affinity_notify(notify);
|
||||
+ goto try_next;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void init_helper_thread(void)
|
||||
+{
|
||||
+ if (set_affinity_helper)
|
||||
+ return;
|
||||
+ set_affinity_helper = kthread_run(set_affinity_thread, NULL,
|
||||
+ "affinity-cb");
|
||||
+ WARN_ON(IS_ERR(set_affinity_helper));
|
||||
+}
|
||||
+#else
|
||||
+
|
||||
+static inline void init_helper_thread(void) { }
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
|
||||
bool force)
|
||||
{
|
||||
@@ -222,7 +278,17 @@ int irq_set_affinity_locked(struct irq_d
|
||||
|
||||
if (desc->affinity_notify) {
|
||||
kref_get(&desc->affinity_notify->kref);
|
||||
+
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ raw_spin_lock(&affinity_list_lock);
|
||||
+ if (list_empty(&desc->affinity_notify->list))
|
||||
+ list_add_tail(&affinity_list,
|
||||
+ &desc->affinity_notify->list);
|
||||
+ raw_spin_unlock(&affinity_list_lock);
|
||||
+ wake_up_process(set_affinity_helper);
|
||||
+#else
|
||||
schedule_work(&desc->affinity_notify->work);
|
||||
+#endif
|
||||
}
|
||||
irqd_set(data, IRQD_AFFINITY_SET);
|
||||
|
||||
@@ -260,10 +326,8 @@ int irq_set_affinity_hint(unsigned int i
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
|
||||
|
||||
-static void irq_affinity_notify(struct work_struct *work)
|
||||
+static void _irq_affinity_notify(struct irq_affinity_notify *notify)
|
||||
{
|
||||
- struct irq_affinity_notify *notify =
|
||||
- container_of(work, struct irq_affinity_notify, work);
|
||||
struct irq_desc *desc = irq_to_desc(notify->irq);
|
||||
cpumask_var_t cpumask;
|
||||
unsigned long flags;
|
||||
@@ -285,6 +349,13 @@ static void irq_affinity_notify(struct w
|
||||
kref_put(¬ify->kref, notify->release);
|
||||
}
|
||||
|
||||
+static void irq_affinity_notify(struct work_struct *work)
|
||||
+{
|
||||
+ struct irq_affinity_notify *notify =
|
||||
+ container_of(work, struct irq_affinity_notify, work);
|
||||
+ _irq_affinity_notify(notify);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* irq_set_affinity_notifier - control notification of IRQ affinity changes
|
||||
* @irq: Interrupt for which to enable/disable notification
|
||||
@@ -314,6 +385,8 @@ irq_set_affinity_notifier(unsigned int i
|
||||
notify->irq = irq;
|
||||
kref_init(¬ify->kref);
|
||||
INIT_WORK(¬ify->work, irq_affinity_notify);
|
||||
+ INIT_LIST_HEAD(¬ify->list);
|
||||
+ init_helper_thread();
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue