Compare commits
280 Commits
Author | SHA1 | Date |
---|---|---|
Chuck Ebbert | 4f60038bf4 | |
Josh Boyer | cf59e182a8 | |
Josh Boyer | df53fa5f95 | |
Josh Boyer | 445b543dc9 | |
Josh Boyer | 4f79121e0c | |
Dave Jones | 6c4e09df79 | |
Josh Boyer | ff37d2b109 | |
Josh Boyer | 3ea9b96c57 | |
Josh Boyer | 29298df87d | |
Josh Boyer | 528c087e36 | |
Chuck Ebbert | 4d20e68f2c | |
Dave Jones | c8c0a79ec2 | |
Dave Jones | 87d5560157 | |
Josh Boyer | 379959bc82 | |
Dave Jones | 6f7506e776 | |
Josh Boyer | c6232b615c | |
Dave Jones | 80bd8b191d | |
Dave Jones | 6cf4af8ebf | |
Dave Jones | 712881a12e | |
Dave Jones | 7e156f0d65 | |
Josh Boyer | 646ec82800 | |
Josh Boyer | 18a614272e | |
Josh Boyer | b45a41b9eb | |
Josh Boyer | c0d43b7963 | |
Josh Boyer | 398017defd | |
Josh Boyer | b2fe2ed5a1 | |
Josh Boyer | 51ba367fb0 | |
Josh Boyer | bc96a9d65d | |
Josh Boyer | cf5a635e41 | |
Josh Boyer | d078fed40e | |
Josh Boyer | 3aec185937 | |
Josh Boyer | 2702d51eae | |
Josh Boyer | fad102a10b | |
Josh Boyer | 248cf7df49 | |
Josh Boyer | a62b54cb1c | |
Josh Boyer | 92fb0ab0ab | |
Chuck Ebbert | 29f392610c | |
Dave Jones | b5c25fa75f | |
Dave Jones | 83a9139012 | |
Chuck Ebbert | e7409b2d7e | |
Chuck Ebbert | c9e8c10a43 | |
Chuck Ebbert | 8ba25ec095 | |
Chuck Ebbert | f77745ccf7 | |
Chuck Ebbert | bdfca38df2 | |
Chuck Ebbert | fa21cb2d4c | |
Chuck Ebbert | 7760c97dcd | |
Kyle McMartin | 398aba2d45 | |
Chuck Ebbert | fcf9248627 | |
Chuck Ebbert | 7e51f2f324 | |
Chuck Ebbert | dd4a4083bb | |
Chuck Ebbert | 64c2b6747d | |
Chuck Ebbert | 6047d0e750 | |
Kyle McMartin | cc37b46764 | |
Chuck Ebbert | 3bf2bfa0d8 | |
Chuck Ebbert | ca79828415 | |
Chuck Ebbert | 2c4c81ad30 | |
Chuck Ebbert | b8c6e51855 | |
Chuck Ebbert | 9e4696b4a4 | |
Kyle McMartin | c6f2ed6008 | |
Chuck Ebbert | 1caa10e2d5 | |
Chuck Ebbert | d54c89365e | |
Kyle McMartin | 3472dfdd75 | |
Kyle McMartin | 21c6036496 | |
Ben Skeggs | e372080592 | |
Kyle McMartin | 20692ec6bc | |
Jarod Wilson | eb037c6bac | |
Chuck Ebbert | d564948d65 | |
Chuck Ebbert | 6143eb5b67 | |
Chuck Ebbert | fcca07d327 | |
Chuck Ebbert | d65a153150 | |
Chuck Ebbert | b4877f1260 | |
Dan Horák | d84ac0f64e | |
Chuck Ebbert | 6e3a83fee3 | |
Matthew Garrett | c7ff2c5553 | |
Chuck Ebbert | 841a0e2190 | |
Chuck Ebbert | f9c2b4dd6f | |
Chuck Ebbert | 57d9bc3966 | |
Chuck Ebbert | d85fb28313 | |
Jarod Wilson | e2f91db6ff | |
Jarod Wilson | 639fa258dc | |
Jarod Wilson | 1875248d2a | |
Jarod Wilson | ef402ae0aa | |
Jarod Wilson | c998b6666e | |
Jarod Wilson | dd3abe2b99 | |
Jarod Wilson | 893aff6339 | |
Kyle McMartin | 7aeac617c0 | |
Jarod Wilson | 0252aa3de3 | |
Jarod Wilson | 5423b80362 | |
Jarod Wilson | a49e3abdff | |
Chuck Ebbert | b11f51521b | |
Jarod Wilson | b97dc7392d | |
Jarod Wilson | 49ee500dd9 | |
Jarod Wilson | f0f13be684 | |
Jarod Wilson | 4b2adb7be5 | |
Chuck Ebbert | aee782a97f | |
Chuck Ebbert | 1f90e5b6f6 | |
Chuck Ebbert | b1f2f04a2b | |
Jarod Wilson | 3ebdcc0e61 | |
Jarod Wilson | d1877af9bb | |
Matthew Garrett | 70d2ada596 | |
Matthew Garrett | 73ab1e483b | |
Kyle McMartin | c60b83ee86 | |
Kyle McMartin | 0cb25895ed | |
Kyle McMartin | bd64b2b5de | |
Jarod Wilson | 1328b3a839 | |
Kyle McMartin | 249677902c | |
Kyle McMartin | 646207ff5c | |
Jarod Wilson | 1cd0593638 | |
Jarod Wilson | 42434a4dc9 | |
Jarod Wilson | d3e2823f71 | |
Kyle McMartin | 358f4a55c5 | |
Kyle McMartin | 825b8ce73a | |
Kyle McMartin | f8d75b80e6 | |
Kyle McMartin | 3dbb45b665 | |
Kyle McMartin | 68b623121d | |
Kyle McMartin | 558463d9fb | |
Jarod Wilson | 703515438b | |
Jarod Wilson | fbfed34fec | |
Jarod Wilson | 92d37ba1d3 | |
Chuck Ebbert | 8f007394cd | |
Kyle McMartin | f045c5648e | |
Kyle McMartin | f2ed8cf30b | |
Kyle McMartin | 5a95077aa5 | |
Kyle McMartin | 54f1e03004 | |
Kyle McMartin | 9d6e5dc425 | |
Kyle McMartin | 4bd3ae5daa | |
Kyle McMartin | bd61adb09d | |
Chuck Ebbert | 983a2bb5c5 | |
Kyle McMartin | bed92c4e50 | |
Kyle McMartin | 20b0493429 | |
Kyle McMartin | 65c06ec080 | |
Kyle McMartin | 76a7ebfb42 | |
Kyle McMartin | d40233bb75 | |
Kyle McMartin | 592f4fb443 | |
Kyle McMartin | 48eb5c319b | |
Kyle McMartin | 26ea0f2631 | |
Kyle McMartin | ca2a17f441 | |
Kyle McMartin | 6abfea1c89 | |
kyle | 7a80ec3e7d | |
kyle | e1c14200b1 | |
John W. Linville | dd99fe005c | |
Kyle McMartin | 003654d6ca | |
Kyle McMartin | c86d4707a6 | |
Kyle McMartin | de964e3639 | |
Kyle McMartin | 55415ebd4a | |
Kyle McMartin | cc7fb594a9 | |
Jarod Wilson | 51157289c8 | |
Chuck Ebbert | 0081a7139c | |
Ben Skeggs | 466450dbeb | |
Kyle McMartin | b2e700d12a | |
Kyle McMartin | 4c76cc7f94 | |
Dave Airlie | d5b83e3877 | |
Dave Airlie | 5f72d41789 | |
Dave Airlie | 171d7cfb89 | |
Justin M. Forbes | adfff05db3 | |
Jarod Wilson | 28683a07fb | |
Dave Airlie | 5ddd90a5d8 | |
Dave Airlie | a474625d92 | |
Dave Airlie | 05493c4e57 | |
Ben Skeggs | 383a70142a | |
Ben Skeggs | c7b0072805 | |
Ben Skeggs | df57a85a75 | |
Jarod Wilson | 030d3b3b4b | |
Chuck Ebbert | 643d353feb | |
Kyle McMartin | cbdb312a9e | |
Kyle McMartin | 8311d5168d | |
Jarod Wilson | 61d7a69fe6 | |
Jarod Wilson | 59a83bd584 | |
Kyle McMartin | c4e830cb35 | |
Kyle McMartin | e38a760c9a | |
Kyle McMartin | f1b58c7ca8 | |
Kyle McMartin | a1b8c4ed84 | |
Kyle McMartin | 6268215f01 | |
Kyle McMartin | 6aca938822 | |
kyle | c76455ec66 | |
kyle | 915df7f6de | |
Kyle McMartin | 7d350a94ee | |
Kyle McMartin | 9ee136bcf7 | |
Kyle McMartin | 97e19f7196 | |
Peter Jones | 7810142e6c | |
Dave Jones | c13cbf3b7d | |
Kyle McMartin | c19187e334 | |
Kyle McMartin | a2d889c53a | |
Kyle McMartin | 7140c9dd2d | |
Jarod Wilson | 167ee12e60 | |
Jarod Wilson | 870acad08e | |
Jarod Wilson | 866bf4f059 | |
Ben Skeggs | bd31d54eac | |
Kyle McMartin | f7f1f5ef4a | |
Dave Jones | a09b817bc1 | |
Kyle McMartin | 2fe1e8e397 | |
Kyle McMartin | eaab8be2d4 | |
Kyle McMartin | bc9e072d9b | |
Ben Skeggs | 2e4b75da82 | |
Dave Jones | db140fac23 | |
Ben Skeggs | 7043d42b5a | |
Dave Jones | 452369b936 | |
Dave Jones | 8f3d6a8c3f | |
Dave Jones | fbce23b0ff | |
Dave Jones | bbaea70ee5 | |
Dave Jones | 04093b926b | |
Chuck Ebbert | 4141bfc9b1 | |
Kyle McMartin | 05f615c82e | |
Chuck Ebbert | b999dfdb6a | |
Chuck Ebbert | b49b116bb0 | |
Chuck Ebbert | eda054e8bd | |
Kyle McMartin | c2aa9135d2 | |
Kyle McMartin | 2348a607b7 | |
Kyle McMartin | b13dd03f62 | |
Kyle McMartin | 6289a5fca9 | |
Ben Skeggs | 31ce2e5e16 | |
Chuck Ebbert | b2398b3ef3 | |
Chuck Ebbert | 69a476baa9 | |
Kyle McMartin | 027325ab53 | |
Chuck Ebbert | b218718b2b | |
Chuck Ebbert | 7a68cb0b55 | |
Dennis Gilmore | 42589b1be2 | |
Dennis Gilmore | 6daeb4142a | |
Dennis Gilmore | c549b813ae | |
Hans de Goede | 7193965656 | |
Dave Jones | 291833d307 | |
Hans de Goede | cb6f3ab735 | |
Chuck Ebbert | db056c27c3 | |
Chuck Ebbert | 14525abb6d | |
Kyle McMartin | a1b0ec05b6 | |
Chuck Ebbert | 9bd241a830 | |
Ben Skeggs | 4badda4370 | |
Jarod Wilson | 17a76a95c4 | |
Bastien Nocera | 9ea075ebba | |
Bastien Nocera | ea6d873cc2 | |
Kyle McMartin | 88a50a0b1d | |
Kyle McMartin | 102e2d6718 | |
Chuck Ebbert | 63fcde2459 | |
Ben Skeggs | fbc4283e12 | |
Kyle McMartin | 3ceeb77a79 | |
Kyle McMartin | 72b3bf972e | |
Ben Skeggs | 0fe99e9810 | |
Ben Skeggs | 215a71b03d | |
Dave Jones | 2eba9aa0ec | |
Jarod Wilson | f4da561c3d | |
Kyle McMartin | 8b695bdd15 | |
Kyle McMartin | 426c30b2f1 | |
Kyle McMartin | cfdae029cc | |
Jarod Wilson | 8ccfe4ce6a | |
Ben Skeggs | 1001ab34f7 | |
Kyle McMartin | d3a72eaedc | |
Chuck Ebbert | 44c4f071d9 | |
Dave Jones | 7def7eaed3 | |
Dave Jones | 35cc504508 | |
Dave Jones | 705539efb5 | |
Dave Jones | c348adbe39 | |
Chuck Ebbert | 0c8a5559c3 | |
Kyle McMartin | 3c5d4de07c | |
Dave Jones | 90303f9462 | |
Dave Jones | 10931f1112 | |
Chuck Ebbert | 27e8302707 | |
Chuck Ebbert | 8f132e348c | |
Chuck Ebbert | b30c150da1 | |
Chuck Ebbert | 3e8e94e0cd | |
Chuck Ebbert | 74e18cdf9e | |
Dave Jones | 4135368fb0 | |
Chuck Ebbert | 13dcde2426 | |
Chuck Ebbert | bfc8e84a86 | |
Kyle McMartin | e2302e0109 | |
Kyle McMartin | 4cfceabb6c | |
Jarod Wilson | b9878dcfec | |
Chuck Ebbert | e1151597d5 | |
Chuck Ebbert | d6d51a1a42 | |
Chuck Ebbert | 4ed348073c | |
Ben Skeggs | 71e9b6763f | |
Chuck Ebbert | 74b9092d38 | |
Chuck Ebbert | 9a98a7ebe3 | |
Chuck Ebbert | 6c58ce89ec | |
Chuck Ebbert | 85a693ce78 | |
Dave Jones | 4326aa56d8 | |
Chuck Ebbert | 4d5b945030 | |
Chuck Ebbert | b6805461ca | |
Chuck Ebbert | 557b0fb7c4 | |
Dave Jones | f8200febc9 | |
Dave Jones | 37cd8b7c4c |
|
@ -1,5 +1,6 @@
|
||||||
linux-*.tar.bz2
|
|
||||||
patch-*.bz2
|
|
||||||
clog
|
clog
|
||||||
|
*.bz2
|
||||||
*.rpm
|
*.rpm
|
||||||
|
*.orig
|
||||||
kernel-2.6.*/
|
kernel-2.6.*/
|
||||||
|
kernel-3.*/
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
From 1729d20333739e6cc23023e405fe8668f08117a2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
Date: Tue, 17 May 2011 10:40:51 -0400
|
||||||
|
Subject: [PATCH 1/2] EHCI: don't rescan interrupt QHs needlessly
|
||||||
|
|
||||||
|
This patch (as1466) speeds up processing of ehci-hcd's periodic list.
|
||||||
|
The existing code will pointlessly rescan an interrupt endpoint queue
|
||||||
|
each time it encounters the queue's QH in the periodic list, which can
|
||||||
|
happen quite a few times if the endpoint's period is low. On some
|
||||||
|
embedded systems, this useless overhead can waste so much time that
|
||||||
|
the driver falls hopelessly behind and loses events.
|
||||||
|
|
||||||
|
The patch introduces a "periodic_stamp" variable, which gets
|
||||||
|
incremented each time scan_periodic() runs and each time the scan
|
||||||
|
advances to a new frame. If the corresponding stamp in an interrupt
|
||||||
|
QH is equal to the current periodic_stamp, we assume the QH has
|
||||||
|
already been scanned and skip over it. Otherwise we scan the QH as
|
||||||
|
usual, and if none of its URBs have completed then we store the
|
||||||
|
current periodic_stamp in the QH's stamp, preventing it from being
|
||||||
|
scanned again.
|
||||||
|
|
||||||
|
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
drivers/usb/host/ehci-q.c | 1 +
|
||||||
|
drivers/usb/host/ehci-sched.c | 14 ++++++++++----
|
||||||
|
drivers/usb/host/ehci.h | 1 +
|
||||||
|
3 files changed, 12 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
|
||||||
|
index ed8db6a..0079610 100644
|
||||||
|
--- a/drivers/usb/host/ehci-q.c
|
||||||
|
+++ b/drivers/usb/host/ehci-q.c
|
||||||
|
@@ -826,6 +826,7 @@ qh_make (
|
||||||
|
is_input, 0,
|
||||||
|
hb_mult(maxp) * max_packet(maxp)));
|
||||||
|
qh->start = NO_FRAME;
|
||||||
|
+ qh->stamp = ehci->periodic_stamp;
|
||||||
|
|
||||||
|
if (urb->dev->speed == USB_SPEED_HIGH) {
|
||||||
|
qh->c_usecs = 0;
|
||||||
|
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
|
||||||
|
index a530856..9e54e85 100644
|
||||||
|
--- a/drivers/usb/host/ehci-sched.c
|
||||||
|
+++ b/drivers/usb/host/ehci-sched.c
|
||||||
|
@@ -2351,6 +2351,7 @@ scan_periodic (struct ehci_hcd *ehci)
|
||||||
|
}
|
||||||
|
clock %= mod;
|
||||||
|
clock_frame = clock >> 3;
|
||||||
|
+ ++ehci->periodic_stamp;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
union ehci_shadow q, *q_p;
|
||||||
|
@@ -2379,10 +2380,14 @@ restart:
|
||||||
|
temp.qh = qh_get (q.qh);
|
||||||
|
type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
|
||||||
|
q = q.qh->qh_next;
|
||||||
|
- modified = qh_completions (ehci, temp.qh);
|
||||||
|
- if (unlikely(list_empty(&temp.qh->qtd_list) ||
|
||||||
|
- temp.qh->needs_rescan))
|
||||||
|
- intr_deschedule (ehci, temp.qh);
|
||||||
|
+ if (temp.qh->stamp != ehci->periodic_stamp) {
|
||||||
|
+ modified = qh_completions(ehci, temp.qh);
|
||||||
|
+ if (!modified)
|
||||||
|
+ temp.qh->stamp = ehci->periodic_stamp;
|
||||||
|
+ if (unlikely(list_empty(&temp.qh->qtd_list) ||
|
||||||
|
+ temp.qh->needs_rescan))
|
||||||
|
+ intr_deschedule(ehci, temp.qh);
|
||||||
|
+ }
|
||||||
|
qh_put (temp.qh);
|
||||||
|
break;
|
||||||
|
case Q_TYPE_FSTN:
|
||||||
|
@@ -2515,6 +2520,7 @@ restart:
|
||||||
|
if (ehci->clock_frame != clock_frame) {
|
||||||
|
free_cached_lists(ehci);
|
||||||
|
ehci->clock_frame = clock_frame;
|
||||||
|
+ ++ehci->periodic_stamp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
now_uframe++;
|
||||||
|
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
|
||||||
|
index c702e4b..c2c2f9d 100644
|
||||||
|
--- a/drivers/usb/host/ehci.h
|
||||||
|
+++ b/drivers/usb/host/ehci.h
|
||||||
|
@@ -117,6 +117,7 @@ struct ehci_hcd { /* one per controller */
|
||||||
|
struct timer_list watchdog;
|
||||||
|
unsigned long actions;
|
||||||
|
unsigned stamp;
|
||||||
|
+ unsigned periodic_stamp;
|
||||||
|
unsigned random_frame;
|
||||||
|
unsigned long next_statechange;
|
||||||
|
ktime_t last_periodic_enable;
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
From e8b80056d07bc849777d032bc699a59cc28f9ddb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
Date: Tue, 5 Jul 2011 12:34:05 -0400
|
||||||
|
Subject: [PATCH 2/2] USB: EHCI: go back to using the system clock for QH
|
||||||
|
unlinks
|
||||||
|
|
||||||
|
This patch (as1477) fixes a problem affecting a few types of EHCI
|
||||||
|
controller. Contrary to what one might expect, these controllers
|
||||||
|
automatically stop their internal frame counter when no ports are
|
||||||
|
enabled. Since ehci-hcd currently relies on the frame counter for
|
||||||
|
determining when it should unlink QHs from the async schedule, those
|
||||||
|
controllers run into trouble: The frame counter stops and the QHs
|
||||||
|
never get unlinked.
|
||||||
|
|
||||||
|
Some systems have also experienced other problems traced back to
|
||||||
|
commit b963801164618e25fbdc0cd452ce49c3628b46c8 (USB: ehci-hcd unlink
|
||||||
|
speedups), which made the original switch from using the system clock
|
||||||
|
to using the frame counter. It never became clear what the reason was
|
||||||
|
for these problems, but evidently it is related to use of the frame
|
||||||
|
counter.
|
||||||
|
|
||||||
|
To fix all these problems, this patch more or less reverts that commit
|
||||||
|
and goes back to using the system clock. But this can't be done
|
||||||
|
cleanly because other changes have since been made to the scan_async()
|
||||||
|
subroutine. One of these changes involved the tricky logic that tries
|
||||||
|
to avoid rescanning QHs that have already been seen when the scanning
|
||||||
|
loop is restarted, which happens whenever an URB is given back.
|
||||||
|
Switching back to clock-based unlinks would make this logic even more
|
||||||
|
complicated.
|
||||||
|
|
||||||
|
Therefore the new code doesn't rescan the entire async list whenever a
|
||||||
|
giveback occurs. Instead it rescans only the current QH and continues
|
||||||
|
on from there. This requires the use of a separate pointer to keep
|
||||||
|
track of the next QH to scan, since the current QH may be unlinked
|
||||||
|
while the scanning is in progress. That new pointer must be global,
|
||||||
|
so that it can be adjusted forward whenever the _next_ QH gets
|
||||||
|
unlinked. (uhci-hcd uses this same trick.)
|
||||||
|
|
||||||
|
Simplification of the scanning loop removes a level of indentation,
|
||||||
|
which accounts for the size of the patch. The amount of code changed
|
||||||
|
is relatively small, and it isn't exactly a reversion of the
|
||||||
|
b963801164 commit.
|
||||||
|
|
||||||
|
This fixes Bugzilla #32432.
|
||||||
|
|
||||||
|
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
CC: <stable@kernel.org>
|
||||||
|
Tested-by: Matej Kenda <matejken@gmail.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
drivers/usb/host/ehci-hcd.c | 8 ++---
|
||||||
|
drivers/usb/host/ehci-q.c | 82 +++++++++++++++++++++----------------------
|
||||||
|
drivers/usb/host/ehci.h | 3 +-
|
||||||
|
3 files changed, 45 insertions(+), 48 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
|
||||||
|
index 761bbb3..8e5b995 100644
|
||||||
|
--- a/drivers/usb/host/ehci-hcd.c
|
||||||
|
+++ b/drivers/usb/host/ehci-hcd.c
|
||||||
|
@@ -83,7 +83,8 @@ static const char hcd_name [] = "ehci_hcd";
|
||||||
|
#define EHCI_IAA_MSECS 10 /* arbitrary */
|
||||||
|
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
|
||||||
|
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
|
||||||
|
-#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
|
||||||
|
+#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
|
||||||
|
+ /* 200-ms async qh unlink delay */
|
||||||
|
|
||||||
|
/* Initial IRQ latency: faster than hw default */
|
||||||
|
static int log2_irq_thresh = 0; // 0 to 6
|
||||||
|
@@ -138,10 +139,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
|
||||||
|
break;
|
||||||
|
/* case TIMER_ASYNC_SHRINK: */
|
||||||
|
default:
|
||||||
|
- /* add a jiffie since we synch against the
|
||||||
|
- * 8 KHz uframe counter.
|
||||||
|
- */
|
||||||
|
- t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
|
||||||
|
+ t = EHCI_SHRINK_JIFFIES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mod_timer(&ehci->watchdog, t + jiffies);
|
||||||
|
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
|
||||||
|
index 0079610..a664203 100644
|
||||||
|
--- a/drivers/usb/host/ehci-q.c
|
||||||
|
+++ b/drivers/usb/host/ehci-q.c
|
||||||
|
@@ -1226,6 +1226,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||||
|
|
||||||
|
prev->hw->hw_next = qh->hw->hw_next;
|
||||||
|
prev->qh_next = qh->qh_next;
|
||||||
|
+ if (ehci->qh_scan_next == qh)
|
||||||
|
+ ehci->qh_scan_next = qh->qh_next.qh;
|
||||||
|
wmb ();
|
||||||
|
|
||||||
|
/* If the controller isn't running, we don't have to wait for it */
|
||||||
|
@@ -1251,53 +1253,49 @@ static void scan_async (struct ehci_hcd *ehci)
|
||||||
|
struct ehci_qh *qh;
|
||||||
|
enum ehci_timer_action action = TIMER_IO_WATCHDOG;
|
||||||
|
|
||||||
|
- ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
|
||||||
|
timer_action_done (ehci, TIMER_ASYNC_SHRINK);
|
||||||
|
-rescan:
|
||||||
|
stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
|
||||||
|
- qh = ehci->async->qh_next.qh;
|
||||||
|
- if (likely (qh != NULL)) {
|
||||||
|
- do {
|
||||||
|
- /* clean any finished work for this qh */
|
||||||
|
- if (!list_empty(&qh->qtd_list) && (stopped ||
|
||||||
|
- qh->stamp != ehci->stamp)) {
|
||||||
|
- int temp;
|
||||||
|
-
|
||||||
|
- /* unlinks could happen here; completion
|
||||||
|
- * reporting drops the lock. rescan using
|
||||||
|
- * the latest schedule, but don't rescan
|
||||||
|
- * qhs we already finished (no looping)
|
||||||
|
- * unless the controller is stopped.
|
||||||
|
- */
|
||||||
|
- qh = qh_get (qh);
|
||||||
|
- qh->stamp = ehci->stamp;
|
||||||
|
- temp = qh_completions (ehci, qh);
|
||||||
|
- if (qh->needs_rescan)
|
||||||
|
- unlink_async(ehci, qh);
|
||||||
|
- qh_put (qh);
|
||||||
|
- if (temp != 0) {
|
||||||
|
- goto rescan;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
|
||||||
|
- /* unlink idle entries, reducing DMA usage as well
|
||||||
|
- * as HCD schedule-scanning costs. delay for any qh
|
||||||
|
- * we just scanned, there's a not-unusual case that it
|
||||||
|
- * doesn't stay idle for long.
|
||||||
|
- * (plus, avoids some kind of re-activation race.)
|
||||||
|
+ ehci->qh_scan_next = ehci->async->qh_next.qh;
|
||||||
|
+ while (ehci->qh_scan_next) {
|
||||||
|
+ qh = ehci->qh_scan_next;
|
||||||
|
+ ehci->qh_scan_next = qh->qh_next.qh;
|
||||||
|
+ rescan:
|
||||||
|
+ /* clean any finished work for this qh */
|
||||||
|
+ if (!list_empty(&qh->qtd_list)) {
|
||||||
|
+ int temp;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Unlinks could happen here; completion reporting
|
||||||
|
+ * drops the lock. That's why ehci->qh_scan_next
|
||||||
|
+ * always holds the next qh to scan; if the next qh
|
||||||
|
+ * gets unlinked then ehci->qh_scan_next is adjusted
|
||||||
|
+ * in start_unlink_async().
|
||||||
|
*/
|
||||||
|
- if (list_empty(&qh->qtd_list)
|
||||||
|
- && qh->qh_state == QH_STATE_LINKED) {
|
||||||
|
- if (!ehci->reclaim && (stopped ||
|
||||||
|
- ((ehci->stamp - qh->stamp) & 0x1fff)
|
||||||
|
- >= EHCI_SHRINK_FRAMES * 8))
|
||||||
|
- start_unlink_async(ehci, qh);
|
||||||
|
- else
|
||||||
|
- action = TIMER_ASYNC_SHRINK;
|
||||||
|
- }
|
||||||
|
+ qh = qh_get(qh);
|
||||||
|
+ temp = qh_completions(ehci, qh);
|
||||||
|
+ if (qh->needs_rescan)
|
||||||
|
+ unlink_async(ehci, qh);
|
||||||
|
+ qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
|
||||||
|
+ qh_put(qh);
|
||||||
|
+ if (temp != 0)
|
||||||
|
+ goto rescan;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- qh = qh->qh_next.qh;
|
||||||
|
- } while (qh);
|
||||||
|
+ /* unlink idle entries, reducing DMA usage as well
|
||||||
|
+ * as HCD schedule-scanning costs. delay for any qh
|
||||||
|
+ * we just scanned, there's a not-unusual case that it
|
||||||
|
+ * doesn't stay idle for long.
|
||||||
|
+ * (plus, avoids some kind of re-activation race.)
|
||||||
|
+ */
|
||||||
|
+ if (list_empty(&qh->qtd_list)
|
||||||
|
+ && qh->qh_state == QH_STATE_LINKED) {
|
||||||
|
+ if (!ehci->reclaim && (stopped ||
|
||||||
|
+ time_after_eq(jiffies, qh->unlink_time)))
|
||||||
|
+ start_unlink_async(ehci, qh);
|
||||||
|
+ else
|
||||||
|
+ action = TIMER_ASYNC_SHRINK;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (action == TIMER_ASYNC_SHRINK)
|
||||||
|
timer_action (ehci, TIMER_ASYNC_SHRINK);
|
||||||
|
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
|
||||||
|
index c2c2f9d..23d9a5e 100644
|
||||||
|
--- a/drivers/usb/host/ehci.h
|
||||||
|
+++ b/drivers/usb/host/ehci.h
|
||||||
|
@@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
|
||||||
|
/* async schedule support */
|
||||||
|
struct ehci_qh *async;
|
||||||
|
struct ehci_qh *reclaim;
|
||||||
|
+ struct ehci_qh *qh_scan_next;
|
||||||
|
unsigned scanning : 1;
|
||||||
|
|
||||||
|
/* periodic schedule support */
|
||||||
|
@@ -116,7 +117,6 @@ struct ehci_hcd { /* one per controller */
|
||||||
|
struct timer_list iaa_watchdog;
|
||||||
|
struct timer_list watchdog;
|
||||||
|
unsigned long actions;
|
||||||
|
- unsigned stamp;
|
||||||
|
unsigned periodic_stamp;
|
||||||
|
unsigned random_frame;
|
||||||
|
unsigned long next_statechange;
|
||||||
|
@@ -337,6 +337,7 @@ struct ehci_qh {
|
||||||
|
struct ehci_qh *reclaim; /* next to reclaim */
|
||||||
|
|
||||||
|
struct ehci_hcd *ehci;
|
||||||
|
+ unsigned long unlink_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do NOT use atomic operations for QH refcounting. On some CPUs
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
From ed62f63919f93dcb040109959ee19983eda8ea84 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Johansen <john.johansen@canonical.com>
|
||||||
|
Date: Thu, 15 Sep 2011 12:48:12 -0400
|
||||||
|
Subject: [PATCH] Ecryptfs: Add mount option to check uid of device being
|
||||||
|
mounted = expect uid
|
||||||
|
|
||||||
|
Close a TOCTOU race for mounts done via ecryptfs-mount-private. The mount
|
||||||
|
source (device) can be raced when the ownership test is done in userspace.
|
||||||
|
Provide Ecryptfs a means to force the uid check at mount time.
|
||||||
|
|
||||||
|
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||||
|
Cc: <stable@kernel.org>
|
||||||
|
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
Backported to 2.6.35.14 by Josh Boyer <jwboyer@redhat.com>
|
||||||
|
---
|
||||||
|
fs/ecryptfs/main.c | 27 ++++++++++++++++++++++-----
|
||||||
|
1 files changed, 22 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
|
||||||
|
index cbd4e18..c249d14 100644
|
||||||
|
--- a/fs/ecryptfs/main.c
|
||||||
|
+++ b/fs/ecryptfs/main.c
|
||||||
|
@@ -208,7 +208,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
|
||||||
|
ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
|
||||||
|
ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
|
||||||
|
ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
|
||||||
|
- ecryptfs_opt_unlink_sigs, ecryptfs_opt_err };
|
||||||
|
+ ecryptfs_opt_unlink_sigs, ecryptfs_opt_check_dev_ruid, ecryptfs_opt_err };
|
||||||
|
|
||||||
|
static const match_table_t tokens = {
|
||||||
|
{ecryptfs_opt_sig, "sig=%s"},
|
||||||
|
@@ -223,6 +223,7 @@ static const match_table_t tokens = {
|
||||||
|
{ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"},
|
||||||
|
{ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
|
||||||
|
{ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
|
||||||
|
+ {ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"},
|
||||||
|
{ecryptfs_opt_err, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -266,6 +267,7 @@ static void ecryptfs_init_mount_crypt_stat(
|
||||||
|
* ecryptfs_parse_options
|
||||||
|
* @sb: The ecryptfs super block
|
||||||
|
* @options: The options pased to the kernel
|
||||||
|
+ * @check_ruid: set to 1 if device uid should be checked against the ruid
|
||||||
|
*
|
||||||
|
* Parse mount options:
|
||||||
|
* debug=N - ecryptfs_verbosity level for debug output
|
||||||
|
@@ -281,7 +283,7 @@ static void ecryptfs_init_mount_crypt_stat(
|
||||||
|
*
|
||||||
|
* Returns zero on success; non-zero on error
|
||||||
|
*/
|
||||||
|
-static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
||||||
|
+static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, uid_t *check_ruid)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int rc = 0;
|
||||||
|
@@ -306,6 +308,8 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
||||||
|
char *cipher_key_bytes_src;
|
||||||
|
char *fn_cipher_key_bytes_src;
|
||||||
|
|
||||||
|
+ *check_ruid = 0;
|
||||||
|
+
|
||||||
|
if (!options) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
@@ -406,6 +410,9 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
||||||
|
case ecryptfs_opt_unlink_sigs:
|
||||||
|
mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS;
|
||||||
|
break;
|
||||||
|
+ case ecryptfs_opt_check_dev_ruid:
|
||||||
|
+ *check_ruid = 1;
|
||||||
|
+ break;
|
||||||
|
case ecryptfs_opt_err:
|
||||||
|
default:
|
||||||
|
printk(KERN_WARNING
|
||||||
|
@@ -494,7 +501,7 @@ static struct file_system_type ecryptfs_fs_type;
|
||||||
|
* ecryptfs_interpose to create our initial inode and super block
|
||||||
|
* struct.
|
||||||
|
*/
|
||||||
|
-static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
|
||||||
|
+static int ecryptfs_read_super(struct super_block *sb, const char *dev_name, uid_t check_ruid)
|
||||||
|
{
|
||||||
|
struct path path;
|
||||||
|
int rc;
|
||||||
|
@@ -511,6 +518,15 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
|
||||||
|
"known incompatibilities\n");
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) {
|
||||||
|
+ rc = -EPERM;
|
||||||
|
+ printk(KERN_ERR "Mount of device (uid: %d) not owned by "
|
||||||
|
+ "requested user (uid: %d)\n",
|
||||||
|
+ path.dentry->d_inode->i_uid, current_uid());
|
||||||
|
+ goto out_free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ecryptfs_set_superblock_lower(sb, path.dentry->d_sb);
|
||||||
|
sb->s_maxbytes = path.dentry->d_sb->s_maxbytes;
|
||||||
|
sb->s_blocksize = path.dentry->d_sb->s_blocksize;
|
||||||
|
@@ -549,6 +565,7 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
struct ecryptfs_dentry_info *root_info;
|
||||||
|
const char *err = "Getting sb failed";
|
||||||
|
int rc;
|
||||||
|
+ uid_t check_ruid;
|
||||||
|
|
||||||
|
sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL);
|
||||||
|
if (!sbi) {
|
||||||
|
@@ -556,7 +573,7 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- rc = ecryptfs_parse_options(sbi, raw_data);
|
||||||
|
+ rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid);
|
||||||
|
if (rc) {
|
||||||
|
err = "Error parsing options";
|
||||||
|
goto out;
|
||||||
|
@@ -601,7 +618,7 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
/* ->kill_sb() will take care of root_info */
|
||||||
|
ecryptfs_set_dentry_private(s->s_root, root_info);
|
||||||
|
s->s_flags |= MS_ACTIVE;
|
||||||
|
- rc = ecryptfs_read_super(s, dev_name);
|
||||||
|
+ rc = ecryptfs_read_super(s, dev_name, check_ruid);
|
||||||
|
if (rc) {
|
||||||
|
deactivate_locked_super(s);
|
||||||
|
err = "Reading sb failed";
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
From f8789858be5c1b13543040b74d978ea448461155 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Howells <dhowells@redhat.com>
|
||||||
|
Date: Tue, 15 Nov 2011 22:09:45 +0000
|
||||||
|
Subject: [PATCH] KEYS: Fix a NULL pointer deref in the user-defined key type
|
||||||
|
|
||||||
|
commit 9f35a33b8d06263a165efe3541d9aa0cdbd70b3b upstream.
|
||||||
|
|
||||||
|
Fix a NULL pointer deref in the user-defined key type whereby updating a
|
||||||
|
negative key into a fully instantiated key will cause an oops to occur
|
||||||
|
when the code attempts to free the non-existent old payload.
|
||||||
|
|
||||||
|
This results in an oops that looks something like the following:
|
||||||
|
|
||||||
|
BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
|
||||||
|
IP: [<ffffffff81085fa1>] __call_rcu+0x11/0x13e
|
||||||
|
PGD 3391d067 PUD 3894a067 PMD 0
|
||||||
|
Oops: 0002 [#1] SMP
|
||||||
|
CPU 1
|
||||||
|
Pid: 4354, comm: keyctl Not tainted 3.1.0-fsdevel+ #1140 /DG965RY
|
||||||
|
RIP: 0010:[<ffffffff81085fa1>] [<ffffffff81085fa1>] __call_rcu+0x11/0x13e
|
||||||
|
RSP: 0018:ffff88003d591df8 EFLAGS: 00010246
|
||||||
|
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000000000006e
|
||||||
|
RDX: ffffffff8161d0c0 RSI: 0000000000000000 RDI: 0000000000000000
|
||||||
|
RBP: ffff88003d591e18 R08: 0000000000000000 R09: ffffffff8152fa6c
|
||||||
|
R10: 0000000000000000 R11: 0000000000000300 R12: ffff88003b8f9538
|
||||||
|
R13: ffffffff8161d0c0 R14: ffff88003b8f9d50 R15: ffff88003c69f908
|
||||||
|
FS: 00007f97eb18c720(0000) GS:ffff88003bd00000(0000) knlGS:0000000000000000
|
||||||
|
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
||||||
|
CR2: 0000000000000008 CR3: 000000003d47a000 CR4: 00000000000006e0
|
||||||
|
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
|
||||||
|
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
|
||||||
|
Process keyctl (pid: 4354, threadinfo ffff88003d590000, task ffff88003c78a040)
|
||||||
|
Stack:
|
||||||
|
ffff88003e0ffde0 ffff88003b8f9538 0000000000000001 ffff88003b8f9d50
|
||||||
|
ffff88003d591e28 ffffffff810860f0 ffff88003d591e68 ffffffff8117bfea
|
||||||
|
ffff88003d591e68 ffffffff00000000 ffff88003e0ffde1 ffff88003e0ffde0
|
||||||
|
Call Trace:
|
||||||
|
[<ffffffff810860f0>] call_rcu_sched+0x10/0x12
|
||||||
|
[<ffffffff8117bfea>] user_update+0x8d/0xa2
|
||||||
|
[<ffffffff8117723a>] key_create_or_update+0x236/0x270
|
||||||
|
[<ffffffff811789b1>] sys_add_key+0x123/0x17e
|
||||||
|
[<ffffffff813b84bb>] system_call_fastpath+0x16/0x1b
|
||||||
|
|
||||||
|
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||||
|
Acked-by: Jeff Layton <jlayton@redhat.com>
|
||||||
|
Acked-by: Neil Horman <nhorman@redhat.com>
|
||||||
|
Acked-by: Steve Dickson <steved@redhat.com>
|
||||||
|
Acked-by: James Morris <jmorris@namei.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
security/keys/user_defined.c | 3 ++-
|
||||||
|
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
|
||||||
|
index e9aa079..d6781b9 100644
|
||||||
|
--- a/security/keys/user_defined.c
|
||||||
|
+++ b/security/keys/user_defined.c
|
||||||
|
@@ -119,7 +119,8 @@ int user_update(struct key *key, const void *data, size_t datalen)
|
||||||
|
key->expiry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- call_rcu(&zap->rcu, user_update_rcu_disposal);
|
||||||
|
+ if (zap)
|
||||||
|
+ call_rcu(&zap->rcu, user_update_rcu_disposal);
|
||||||
|
|
||||||
|
error:
|
||||||
|
return ret;
|
||||||
|
--
|
||||||
|
1.7.7.1
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -88,6 +88,7 @@ debug:
|
||||||
@perl -pi -e 's/# CONFIG_KDB_KEYBOARD is not set/CONFIG_KDB_KEYBOARD=y/' config-nodebug
|
@perl -pi -e 's/# CONFIG_KDB_KEYBOARD is not set/CONFIG_KDB_KEYBOARD=y/' config-nodebug
|
||||||
@perl -pi -e 's/# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set/CONFIG_CPU_NOTIFIER_ERROR_INJECT=m/' config-nodebug
|
@perl -pi -e 's/# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set/CONFIG_CPU_NOTIFIER_ERROR_INJECT=m/' config-nodebug
|
||||||
@perl -pi -e 's/# CONFIG_DEBUG_PER_CPU_MAPS is not set/CONFIG_DEBUG_PER_CPU_MAPS=y/' config-nodebug
|
@perl -pi -e 's/# CONFIG_DEBUG_PER_CPU_MAPS is not set/CONFIG_DEBUG_PER_CPU_MAPS=y/' config-nodebug
|
||||||
|
#@perl -pi -e 's/# CONFIG_PCI_DEFAULT_USE_CRS is not set/CONFIG_PCI_DEFAULT_USE_CRS=y/' config-nodebug
|
||||||
|
|
||||||
@# just in case we're going from extremedebug -> debug
|
@# just in case we're going from extremedebug -> debug
|
||||||
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug
|
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug
|
||||||
|
@ -97,6 +98,10 @@ debug:
|
||||||
@perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec
|
@perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec
|
||||||
@perl -pi -e 's/^%define rawhide_skip_docs 0/%define rawhide_skip_docs 1/' kernel.spec
|
@perl -pi -e 's/^%define rawhide_skip_docs 0/%define rawhide_skip_docs 1/' kernel.spec
|
||||||
|
|
||||||
|
nodebuginfo:
|
||||||
|
@perl -pi -e 's/^%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 1\}/%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 0\}/' kernel.spec
|
||||||
|
nodebug: release
|
||||||
|
@perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec
|
||||||
release:
|
release:
|
||||||
@perl -pi -e 's/CONFIG_SLUB_DEBUG_ON=y/# CONFIG_SLUB_DEBUG_ON is not set/' config-nodebug
|
@perl -pi -e 's/CONFIG_SLUB_DEBUG_ON=y/# CONFIG_SLUB_DEBUG_ON is not set/' config-nodebug
|
||||||
@perl -pi -e 's/CONFIG_LOCK_STAT=y/# CONFIG_LOCK_STAT is not set/' config-nodebug
|
@perl -pi -e 's/CONFIG_LOCK_STAT=y/# CONFIG_LOCK_STAT is not set/' config-nodebug
|
||||||
|
@ -156,6 +161,7 @@ release:
|
||||||
#@perl -pi -e 's/CONFIG_KGDB_KDB=y/# CONFIG_KGDB_KDB is not set/' config-nodebug
|
#@perl -pi -e 's/CONFIG_KGDB_KDB=y/# CONFIG_KGDB_KDB is not set/' config-nodebug
|
||||||
#@perl -pi -e 's/CONFIG_KDB_KEYBOARD=y/# CONFIG_KDB_KEYBOARD is not set/' config-nodebug
|
#@perl -pi -e 's/CONFIG_KDB_KEYBOARD=y/# CONFIG_KDB_KEYBOARD is not set/' config-nodebug
|
||||||
@perl -pi -e 's/CONFIG_DEBUG_PER_CPU_MAPS=y/# CONFIG_DEBUG_PER_CPU_MAPS is not set/' config-nodebug
|
@perl -pi -e 's/CONFIG_DEBUG_PER_CPU_MAPS=y/# CONFIG_DEBUG_PER_CPU_MAPS is not set/' config-nodebug
|
||||||
|
#@perl -pi -e 's/CONFIG_PCI_DEFAULT_USE_CRS=y/# CONFIG_PCI_DEFAULT_USE_CRS is not set/' config-nodebug
|
||||||
|
|
||||||
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-debug
|
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-debug
|
||||||
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug
|
@perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
From 6b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Huewe <huewe.external.infineon@googlemail.com>
|
||||||
|
Date: Thu, 15 Sep 2011 14:37:43 -0300
|
||||||
|
Subject: [PATCH] TPM: Call tpm_transmit with correct size
|
||||||
|
|
||||||
|
This patch changes the call of tpm_transmit by supplying the size of the
|
||||||
|
userspace buffer instead of TPM_BUFSIZE.
|
||||||
|
|
||||||
|
This got assigned CVE-2011-1161.
|
||||||
|
|
||||||
|
[The first hunk didn't make sense given one could expect
|
||||||
|
way less data than TPM_BUFSIZE, so added tpm_transmit boundary
|
||||||
|
check over bufsiz instead
|
||||||
|
The last parameter of tpm_transmit() reflects the amount
|
||||||
|
of data expected from the device, and not the buffer size
|
||||||
|
being supplied to it. It isn't ideal to parse it directly,
|
||||||
|
so we just set it to the maximum the input buffer can handle
|
||||||
|
and let the userspace API to do such job.]
|
||||||
|
|
||||||
|
Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
|
||||||
|
Cc: Stable Kernel <stable@kernel.org>
|
||||||
|
Signed-off-by: James Morris <jmorris@namei.org>
|
||||||
|
---
|
||||||
|
drivers/char/tpm/tpm.c | 3 +++
|
||||||
|
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
|
||||||
|
index caf8012..1fe9793 100644
|
||||||
|
--- a/drivers/char/tpm/tpm.c
|
||||||
|
+++ b/drivers/char/tpm/tpm.c
|
||||||
|
@@ -383,6 +383,9 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
|
||||||
|
u32 count, ordinal;
|
||||||
|
unsigned long stop;
|
||||||
|
|
||||||
|
+ if (bufsiz > TPM_BUFSIZE)
|
||||||
|
+ bufsiz = TPM_BUFSIZE;
|
||||||
|
+
|
||||||
|
count = be32_to_cpu(*((__be32 *) (buf + 2)));
|
||||||
|
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
|
||||||
|
if (count == 0)
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
From 3321c07ae5068568cd61ac9f4ba749006a7185c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Huewe <huewe.external.infineon@googlemail.com>
|
||||||
|
Date: Thu, 15 Sep 2011 14:47:42 -0300
|
||||||
|
Subject: [PATCH] TPM: Zero buffer after copying to userspace
|
||||||
|
|
||||||
|
Since the buffer might contain security related data it might be a good idea to
|
||||||
|
zero the buffer after we have copied it to userspace.
|
||||||
|
|
||||||
|
This got assigned CVE-2011-1162.
|
||||||
|
|
||||||
|
Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
|
||||||
|
Cc: Stable Kernel <stable@kernel.org>
|
||||||
|
Signed-off-by: James Morris <jmorris@namei.org>
|
||||||
|
---
|
||||||
|
drivers/char/tpm/tpm.c | 6 +++++-
|
||||||
|
1 files changed, 5 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
|
||||||
|
index 1fe9793..9ca5c02 100644
|
||||||
|
--- a/drivers/char/tpm/tpm.c
|
||||||
|
+++ b/drivers/char/tpm/tpm.c
|
||||||
|
@@ -1105,6 +1105,7 @@ ssize_t tpm_read(struct file *file, char __user *buf,
|
||||||
|
{
|
||||||
|
struct tpm_chip *chip = file->private_data;
|
||||||
|
ssize_t ret_size;
|
||||||
|
+ int rc;
|
||||||
|
|
||||||
|
del_singleshot_timer_sync(&chip->user_read_timer);
|
||||||
|
flush_work_sync(&chip->work);
|
||||||
|
@@ -1115,8 +1116,11 @@ ssize_t tpm_read(struct file *file, char __user *buf,
|
||||||
|
ret_size = size;
|
||||||
|
|
||||||
|
mutex_lock(&chip->buffer_mutex);
|
||||||
|
- if (copy_to_user(buf, chip->data_buffer, ret_size))
|
||||||
|
+ rc = copy_to_user(buf, chip->data_buffer, ret_size);
|
||||||
|
+ memset(chip->data_buffer, 0, ret_size);
|
||||||
|
+ if (rc)
|
||||||
|
ret_size = -EFAULT;
|
||||||
|
+
|
||||||
|
mutex_unlock(&chip->buffer_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
commit 08a0799d5736f1494ef35d386570d177447acbfb
|
||||||
|
Author: Lee, Chun-Yi <joeyli.kernel@gmail.com>
|
||||||
|
Date: Wed Apr 6 17:40:06 2011 +0800
|
||||||
|
|
||||||
|
acer-wmi: Fix capitalisation of GUID in module alias
|
||||||
|
|
||||||
|
wmi:6AF4F258-B401-42Fd-BE91-3D4AC2D7C0D3 needs to be
|
||||||
|
wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3 in module alias for acer-wmi is
|
||||||
|
automatically loaded.
|
||||||
|
|
||||||
|
Cc: Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
Cc: Carlos Corbacho <carlos@strangeworlds.co.uk>
|
||||||
|
Cc: Matthew Garrett <mjg@redhat.com>
|
||||||
|
Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
|
||||||
|
Signed-off-by: Matthew Garrett <mjg@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
|
||||||
|
index 5ea6c34..ac4e7f8 100644
|
||||||
|
--- a/drivers/platform/x86/acer-wmi.c
|
||||||
|
+++ b/drivers/platform/x86/acer-wmi.c
|
||||||
|
@@ -95,7 +95,7 @@ struct acer_quirks {
|
||||||
|
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
|
||||||
|
|
||||||
|
MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
|
||||||
|
-MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3");
|
||||||
|
+MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface capability flags
|
|
@ -0,0 +1,38 @@
|
||||||
|
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
|
||||||
|
index 3ed80b2..17fc718 100644
|
||||||
|
--- a/drivers/acpi/sleep.c
|
||||||
|
+++ b/drivers/acpi/sleep.c
|
||||||
|
@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.callback = init_nvs_nosave,
|
||||||
|
+ .ident = "Sony Vaio VGN-FW21E",
|
||||||
|
+ .matches = {
|
||||||
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
||||||
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .callback = init_nvs_nosave,
|
||||||
|
.ident = "Sony Vaio VGN-SR11M",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
||||||
|
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
|
||||||
|
index 0e46fae..6d9a3ab 100644
|
||||||
|
--- a/drivers/acpi/sleep.c
|
||||||
|
+++ b/drivers/acpi/sleep.c
|
||||||
|
@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.callback = init_nvs_nosave,
|
||||||
|
+ .ident = "Sony Vaio VPCEB17FX",
|
||||||
|
+ .matches = {
|
||||||
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
||||||
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .callback = init_nvs_nosave,
|
||||||
|
.ident = "Sony Vaio VGN-SR11M",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
|
@ -0,0 +1,68 @@
|
||||||
|
--- linux-2.6.35.x86_64/drivers/acpi/battery.c.orig 2010-12-23 10:42:09.291854595 -0500
|
||||||
|
+++ linux-2.6.35.x86_64/drivers/acpi/battery.c 2010-12-23 10:44:30.996045838 -0500
|
||||||
|
@@ -596,9 +596,10 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int acpi_battery_update(struct acpi_battery *battery)
|
||||||
|
+static int acpi_battery_update(struct acpi_battery *battery, bool get_info)
|
||||||
|
{
|
||||||
|
int result, old_present = acpi_battery_present(battery);
|
||||||
|
+ int old_power_unit = battery->power_unit;
|
||||||
|
result = acpi_battery_get_status(battery);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
@@ -621,6 +622,16 @@
|
||||||
|
if (!battery->bat.dev)
|
||||||
|
sysfs_add_battery(battery);
|
||||||
|
#endif
|
||||||
|
+ if (get_info) {
|
||||||
|
+ acpi_battery_get_info(battery);
|
||||||
|
+#ifdef CONFIG_ACPI_SYSFS_POWER
|
||||||
|
+ if (old_power_unit != battery->power_unit) {
|
||||||
|
+ /* The battery has changed its reporting units */
|
||||||
|
+ sysfs_remove_battery(battery);
|
||||||
|
+ sysfs_add_battery(battery);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
result = acpi_battery_get_state(battery);
|
||||||
|
acpi_battery_quirks2(battery);
|
||||||
|
return result;
|
||||||
|
@@ -798,7 +809,7 @@
|
||||||
|
static int acpi_battery_read(int fid, struct seq_file *seq)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery = seq->private;
|
||||||
|
- int result = acpi_battery_update(battery);
|
||||||
|
+ int result = acpi_battery_update(battery, false);
|
||||||
|
return acpi_print_funcs[fid](seq, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -913,7 +924,8 @@
|
||||||
|
#ifdef CONFIG_ACPI_SYSFS_POWER
|
||||||
|
old = battery->bat.dev;
|
||||||
|
#endif
|
||||||
|
- acpi_battery_update(battery);
|
||||||
|
+ acpi_battery_update(battery, (event == ACPI_BATTERY_NOTIFY_INFO ? true
|
||||||
|
+ : false));
|
||||||
|
acpi_bus_generate_proc_event(device, event,
|
||||||
|
acpi_battery_present(battery));
|
||||||
|
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||||
|
@@ -944,7 +956,7 @@
|
||||||
|
if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
|
||||||
|
"_BIX", &handle)))
|
||||||
|
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
||||||
|
- acpi_battery_update(battery);
|
||||||
|
+ acpi_battery_update(battery, false);
|
||||||
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
result = acpi_battery_add_fs(device);
|
||||||
|
#endif
|
||||||
|
@@ -987,7 +999,7 @@
|
||||||
|
return -EINVAL;
|
||||||
|
battery = acpi_driver_data(device);
|
||||||
|
battery->update_time = 0;
|
||||||
|
- acpi_battery_update(battery);
|
||||||
|
+ acpi_battery_update(battery, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,702 @@
|
||||||
|
From 46fadae732d825141f45bf2fbd6381451da26ad7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bastien Nocera <hadess@hadess.net>
|
||||||
|
Date: Fri, 10 Sep 2010 16:40:46 +0100
|
||||||
|
Subject: [PATCH] Input: add appleir USB driver
|
||||||
|
|
||||||
|
This driver was originally written by James McKenzie, updated by
|
||||||
|
Greg Kroah-Hartman, further updated by myself, with suspend support
|
||||||
|
added.
|
||||||
|
|
||||||
|
More recent versions of the IR receiver are also supported through
|
||||||
|
a patch by Alex Karpenko. The patch also adds support for the 2nd
|
||||||
|
and 5th generation of the controller, and the menu key on newer
|
||||||
|
brushed metal remotes.
|
||||||
|
|
||||||
|
Tested on a MacbookAir1,1
|
||||||
|
|
||||||
|
Signed-off-by: Bastien Nocera <hadess@hadess.net>
|
||||||
|
---
|
||||||
|
Documentation/input/appleir.txt | 46 ++++
|
||||||
|
drivers/hid/hid-apple.c | 4 -
|
||||||
|
drivers/hid/hid-core.c | 7 +-
|
||||||
|
drivers/hid/hid-ids.h | 5 +-
|
||||||
|
drivers/input/misc/Kconfig | 13 +
|
||||||
|
drivers/input/misc/Makefile | 1 +
|
||||||
|
drivers/input/misc/appleir.c | 519 +++++++++++++++++++++++++++++++++++++++
|
||||||
|
7 files changed, 588 insertions(+), 7 deletions(-)
|
||||||
|
create mode 100644 Documentation/input/appleir.txt
|
||||||
|
create mode 100644 drivers/input/misc/appleir.c
|
||||||
|
|
||||||
|
diff --git a/Documentation/input/appleir.txt b/Documentation/input/appleir.txt
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..db637fb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/input/appleir.txt
|
||||||
|
@@ -0,0 +1,46 @@
|
||||||
|
+Apple IR receiver Driver (appleir)
|
||||||
|
+----------------------------------
|
||||||
|
+ Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
|
||||||
|
+
|
||||||
|
+The appleir driver is a kernel input driver to handle Apple's IR
|
||||||
|
+receivers (and associated remotes) in the kernel.
|
||||||
|
+
|
||||||
|
+The driver is an input driver which only handles "official" remotes
|
||||||
|
+as built and sold by Apple.
|
||||||
|
+
|
||||||
|
+Authors
|
||||||
|
+-------
|
||||||
|
+
|
||||||
|
+James McKenzie (original driver)
|
||||||
|
+Alex Karpenko (05ac:8242 support)
|
||||||
|
+Greg Kroah-Hartman (cleanups and original submission)
|
||||||
|
+Bastien Nocera (further cleanups, brushed metal "enter"
|
||||||
|
+button support and suspend support)
|
||||||
|
+
|
||||||
|
+Supported hardware
|
||||||
|
+------------------
|
||||||
|
+
|
||||||
|
+- All Apple laptops and desktops from 2005 onwards, except:
|
||||||
|
+ - the unibody Macbook (2009)
|
||||||
|
+ - Mac Pro (all versions)
|
||||||
|
+- Apple TV (all revisions prior to September 2010)
|
||||||
|
+
|
||||||
|
+The remote will only support the 6 (old white) or 7 (brushed metal) buttons
|
||||||
|
+of the remotes as sold by Apple. See the next section if you want to use
|
||||||
|
+other remotes or want to use lirc with the device instead of the kernel driver.
|
||||||
|
+
|
||||||
|
+Using lirc (native) instead of the kernel driver
|
||||||
|
+------------------------------------------------
|
||||||
|
+
|
||||||
|
+First, you will need to disable the kernel driver for the receiver.
|
||||||
|
+
|
||||||
|
+This can be achieved by passing quirks to the usbhid driver.
|
||||||
|
+The quirk line would be:
|
||||||
|
+usbhid.quirks=0x05ac:0x8242:0x40000010
|
||||||
|
+
|
||||||
|
+With 0x05ac being the vendor ID (Apple, you shouldn't need to change this)
|
||||||
|
+With 0x8242 being the product ID (check the output of lsusb for your hardware)
|
||||||
|
+And 0x10 being "HID_QUIRK_HIDDEV_FORCE" and 0x40000000 being "HID_QUIRK_NO_IGNORE"
|
||||||
|
+
|
||||||
|
+This should force the creation of a hiddev device for the receiver, and
|
||||||
|
+make it usable under lirc.
|
||||||
|
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
|
||||||
|
index bba05d0..0059d5a 100644
|
||||||
|
--- a/drivers/hid/hid-apple.c
|
||||||
|
+++ b/drivers/hid/hid-apple.c
|
||||||
|
@@ -361,10 +361,6 @@ static void apple_remove(struct hid_device *hdev)
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id apple_devices[] = {
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
|
||||||
|
- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
|
||||||
|
- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
|
||||||
|
.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||||||
|
index 866e54e..1d5e284 100644
|
||||||
|
--- a/drivers/hid/hid-core.c
|
||||||
|
+++ b/drivers/hid/hid-core.c
|
||||||
|
@@ -1239,8 +1239,6 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
|
||||||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
|
||||||
|
@@ -1571,6 +1569,11 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)},
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)},
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)},
|
||||||
|
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||||
|
index 31601ee..9afe3bc 100644
|
||||||
|
--- a/drivers/hid/hid-ids.h
|
||||||
|
+++ b/drivers/hid/hid-ids.h
|
||||||
|
@@ -98,8 +98,11 @@
|
||||||
|
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
|
||||||
|
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
|
||||||
|
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
|
||||||
|
-#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241
|
||||||
|
#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID_ASUS 0x0486
|
||||||
|
#define USB_DEVICE_ID_ASUS_T91MT 0x0185
|
||||||
|
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
|
||||||
|
index c44b9ea..76a12b7 100644
|
||||||
|
--- a/drivers/input/misc/Kconfig
|
||||||
|
+++ b/drivers/input/misc/Kconfig
|
||||||
|
@@ -199,6 +199,19 @@ config INPUT_KEYSPAN_REMOTE
|
||||||
|
To compile this driver as a module, choose M here: the module will
|
||||||
|
be called keyspan_remote.
|
||||||
|
|
||||||
|
+config INPUT_APPLEIR
|
||||||
|
+ tristate "Apple infrared receiver (built in)"
|
||||||
|
+ depends on USB_ARCH_HAS_HCD
|
||||||
|
+ select USB
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want to use a Apple infrared remote control. All
|
||||||
|
+ the Apple computers from 2005 onwards include such a port, except
|
||||||
|
+ the unibody Macbook (2009), and Mac Pros. This receiver is also
|
||||||
|
+ used in the Apple TV set-top box prior to the 2010 model.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the module will
|
||||||
|
+ be called appleir.
|
||||||
|
+
|
||||||
|
config INPUT_POWERMATE
|
||||||
|
tristate "Griffin PowerMate and Contour Jog support"
|
||||||
|
depends on USB_ARCH_HAS_HCD
|
||||||
|
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
|
||||||
|
index 71fe57d..62a5c60 100644
|
||||||
|
--- a/drivers/input/misc/Makefile
|
||||||
|
+++ b/drivers/input/misc/Makefile
|
||||||
|
@@ -9,6 +9,7 @@ obj-$(CONFIG_INPUT_AD714X) += ad714x.o
|
||||||
|
obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o
|
||||||
|
obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o
|
||||||
|
obj-$(CONFIG_INPUT_APANEL) += apanel.o
|
||||||
|
+obj-$(CONFIG_INPUT_APPLEIR) += appleir.o
|
||||||
|
obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
|
||||||
|
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
|
||||||
|
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
|
||||||
|
diff --git a/drivers/input/misc/appleir.c b/drivers/input/misc/appleir.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..3817a3c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/input/misc/appleir.c
|
||||||
|
@@ -0,0 +1,519 @@
|
||||||
|
+/*
|
||||||
|
+ * appleir: USB driver for the apple ir device
|
||||||
|
+ *
|
||||||
|
+ * Original driver written by James McKenzie
|
||||||
|
+ * Ported to recent 2.6 kernel versions by Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2006 James McKenzie
|
||||||
|
+ * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
|
||||||
|
+ * Copyright (C) 2008 Novell Inc.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify it
|
||||||
|
+ * under the terms of the GNU General Public License as published by the Free
|
||||||
|
+ * Software Foundation, version 2.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/slab.h>
|
||||||
|
+#include <linux/input.h>
|
||||||
|
+#include <linux/usb/input.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/init.h>
|
||||||
|
+#include <linux/usb.h>
|
||||||
|
+#include <linux/usb/input.h>
|
||||||
|
+#include <asm/unaligned.h>
|
||||||
|
+#include <asm/byteorder.h>
|
||||||
|
+
|
||||||
|
+#define DRIVER_VERSION "v1.2"
|
||||||
|
+#define DRIVER_AUTHOR "James McKenzie"
|
||||||
|
+#define DRIVER_DESC "Apple infrared receiver driver"
|
||||||
|
+#define DRIVER_LICENSE "GPL"
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
|
+MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
|
+MODULE_LICENSE(DRIVER_LICENSE);
|
||||||
|
+
|
||||||
|
+#define USB_VENDOR_ID_APPLE 0x05ac
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
|
||||||
|
+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243
|
||||||
|
+
|
||||||
|
+#define URB_SIZE 32
|
||||||
|
+
|
||||||
|
+#define MAX_KEYS 9
|
||||||
|
+#define MAX_KEYS_MASK (MAX_KEYS - 1)
|
||||||
|
+
|
||||||
|
+#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
|
||||||
|
+
|
||||||
|
+static int debug;
|
||||||
|
+module_param(debug, int, 0644);
|
||||||
|
+MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
|
||||||
|
+
|
||||||
|
+/* I have two devices both of which report the following */
|
||||||
|
+/* 25 87 ee 83 0a + */
|
||||||
|
+/* 25 87 ee 83 0c - */
|
||||||
|
+/* 25 87 ee 83 09 << */
|
||||||
|
+/* 25 87 ee 83 06 >> */
|
||||||
|
+/* 25 87 ee 83 05 >" */
|
||||||
|
+/* 25 87 ee 83 03 menu */
|
||||||
|
+/* 26 00 00 00 00 for key repeat*/
|
||||||
|
+
|
||||||
|
+/* Thomas Glanzmann reports the following responses */
|
||||||
|
+/* 25 87 ee ca 0b + */
|
||||||
|
+/* 25 87 ee ca 0d - */
|
||||||
|
+/* 25 87 ee ca 08 << */
|
||||||
|
+/* 25 87 ee ca 07 >> */
|
||||||
|
+/* 25 87 ee ca 04 >" */
|
||||||
|
+/* 25 87 ee ca 02 menu */
|
||||||
|
+/* 26 00 00 00 00 for key repeat*/
|
||||||
|
+/* He also observes the following event sometimes */
|
||||||
|
+/* sent after a key is release, which I interpret */
|
||||||
|
+/* as a flat battery message */
|
||||||
|
+/* 25 87 e0 ca 06 flat battery */
|
||||||
|
+
|
||||||
|
+/* Alexandre Karpenko reports the following responses for Device ID 0x8242 */
|
||||||
|
+/* 25 87 ee 47 0b + */
|
||||||
|
+/* 25 87 ee 47 0d - */
|
||||||
|
+/* 25 87 ee 47 08 << */
|
||||||
|
+/* 25 87 ee 47 07 >> */
|
||||||
|
+/* 25 87 ee 47 04 >" */
|
||||||
|
+/* 25 87 ee 47 02 menu */
|
||||||
|
+/* 26 87 ee 47 ** for key repeat (** is the code of the key being held) */
|
||||||
|
+
|
||||||
|
+/* Bastien Nocera's "new" remote */
|
||||||
|
+/* 25 87 ee 91 5f followed by
|
||||||
|
+ * 25 87 ee 91 05 gives you >"
|
||||||
|
+ *
|
||||||
|
+ * 25 87 ee 91 5c followed by
|
||||||
|
+ * 25 87 ee 91 05 gives you the middle button */
|
||||||
|
+
|
||||||
|
+static const unsigned short appleir_key_table[] = {
|
||||||
|
+ KEY_RESERVED,
|
||||||
|
+ KEY_MENU,
|
||||||
|
+ KEY_PLAYPAUSE,
|
||||||
|
+ KEY_FORWARD,
|
||||||
|
+ KEY_BACK,
|
||||||
|
+ KEY_VOLUMEUP,
|
||||||
|
+ KEY_VOLUMEDOWN,
|
||||||
|
+ KEY_ENTER,
|
||||||
|
+ KEY_RESERVED,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct appleir {
|
||||||
|
+ struct input_dev *input_dev;
|
||||||
|
+ unsigned short keymap[ARRAY_SIZE(appleir_key_table)];
|
||||||
|
+ u8 *data;
|
||||||
|
+ dma_addr_t dma_buf;
|
||||||
|
+ struct usb_device *usbdev;
|
||||||
|
+ unsigned int flags;
|
||||||
|
+ struct urb *urb;
|
||||||
|
+ struct timer_list key_up_timer;
|
||||||
|
+ int current_key;
|
||||||
|
+ int prev_key_idx;
|
||||||
|
+ char phys[32];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static DEFINE_MUTEX(appleir_mutex);
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ APPLEIR_OPENED = 0x1,
|
||||||
|
+ APPLEIR_SUSPENDED = 0x2,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct usb_device_id appleir_ids[] = {
|
||||||
|
+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
|
||||||
|
+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
|
||||||
|
+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
|
||||||
|
+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||||
|
+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
|
||||||
|
+ {}
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(usb, appleir_ids);
|
||||||
|
+
|
||||||
|
+static void dump_packet(struct appleir *appleir, char *msg, u8 *data, int len)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ printk(KERN_ERR "appleir: %s (%d bytes)", msg, len);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < len; ++i)
|
||||||
|
+ printk(" %02x", data[i]);
|
||||||
|
+ printk(" (should be command %d)\n", (data[4] >> 1) & MAX_KEYS_MASK);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int get_key(int data)
|
||||||
|
+{
|
||||||
|
+ switch (data) {
|
||||||
|
+ case 0x02:
|
||||||
|
+ case 0x03:
|
||||||
|
+ /* menu */
|
||||||
|
+ return 1;
|
||||||
|
+ case 0x04:
|
||||||
|
+ case 0x05:
|
||||||
|
+ /* >" */
|
||||||
|
+ return 2;
|
||||||
|
+ case 0x06:
|
||||||
|
+ case 0x07:
|
||||||
|
+ /* >> */
|
||||||
|
+ return 3;
|
||||||
|
+ case 0x08:
|
||||||
|
+ case 0x09:
|
||||||
|
+ /* << */
|
||||||
|
+ return 4;
|
||||||
|
+ case 0x0a:
|
||||||
|
+ case 0x0b:
|
||||||
|
+ /* + */
|
||||||
|
+ return 5;
|
||||||
|
+ case 0x0c:
|
||||||
|
+ case 0x0d:
|
||||||
|
+ /* - */
|
||||||
|
+ return 6;
|
||||||
|
+ case 0x5c:
|
||||||
|
+ /* Middle button, on newer remotes,
|
||||||
|
+ * part of a 2 packet-command */
|
||||||
|
+ return -7;
|
||||||
|
+ default:
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void key_up(struct appleir *appleir, int key)
|
||||||
|
+{
|
||||||
|
+ dbginfo(&appleir->input_dev->dev, "key %d up\n", key);
|
||||||
|
+ input_report_key(appleir->input_dev, key, 0);
|
||||||
|
+ input_sync(appleir->input_dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void key_down(struct appleir *appleir, int key)
|
||||||
|
+{
|
||||||
|
+ dbginfo(&appleir->input_dev->dev, "key %d down\n", key);
|
||||||
|
+ input_report_key(appleir->input_dev, key, 1);
|
||||||
|
+ input_sync(appleir->input_dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void battery_flat(struct appleir *appleir)
|
||||||
|
+{
|
||||||
|
+ dev_err(&appleir->input_dev->dev, "possible flat battery?\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void key_up_tick(unsigned long data)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = (struct appleir *)data;
|
||||||
|
+
|
||||||
|
+ if (appleir->current_key) {
|
||||||
|
+ key_up(appleir, appleir->current_key);
|
||||||
|
+ appleir->current_key = 0;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void new_data(struct appleir *appleir, u8 *data, int len)
|
||||||
|
+{
|
||||||
|
+ static const u8 keydown[] = { 0x25, 0x87, 0xee };
|
||||||
|
+ static const u8 keyrepeat[] = { 0x26, };
|
||||||
|
+ static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 };
|
||||||
|
+
|
||||||
|
+ if (debug)
|
||||||
|
+ dump_packet(appleir, "received", data, len);
|
||||||
|
+
|
||||||
|
+ if (len != 5)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (!memcmp(data, keydown, sizeof(keydown))) {
|
||||||
|
+ int index;
|
||||||
|
+
|
||||||
|
+ /* If we already have a key down, take it up before marking
|
||||||
|
+ this one down */
|
||||||
|
+ if (appleir->current_key)
|
||||||
|
+ key_up(appleir, appleir->current_key);
|
||||||
|
+
|
||||||
|
+ /* Handle dual packet commands */
|
||||||
|
+ if (appleir->prev_key_idx > 0)
|
||||||
|
+ index = appleir->prev_key_idx;
|
||||||
|
+ else
|
||||||
|
+ index = get_key(data[4]);
|
||||||
|
+
|
||||||
|
+ if (index > 0) {
|
||||||
|
+ appleir->current_key = appleir->keymap[index];
|
||||||
|
+
|
||||||
|
+ key_down(appleir, appleir->current_key);
|
||||||
|
+ /* Remote doesn't do key up, either pull them up, in the test
|
||||||
|
+ above, or here set a timer which pulls them up after 1/8 s */
|
||||||
|
+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
|
||||||
|
+ appleir->prev_key_idx = 0;
|
||||||
|
+ return;
|
||||||
|
+ } else if (index == -7) {
|
||||||
|
+ /* Remember key for next packet */
|
||||||
|
+ appleir->prev_key_idx = 0 - index;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ appleir->prev_key_idx = 0;
|
||||||
|
+
|
||||||
|
+ if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) {
|
||||||
|
+ key_down(appleir, appleir->current_key);
|
||||||
|
+ /* Remote doesn't do key up, either pull them up, in the test
|
||||||
|
+ above, or here set a timer which pulls them up after 1/8 s */
|
||||||
|
+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!memcmp(data, flatbattery, sizeof(flatbattery))) {
|
||||||
|
+ battery_flat(appleir);
|
||||||
|
+ /* Fall through */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dump_packet(appleir, "unknown packet", data, len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void appleir_urb(struct urb *urb)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = urb->context;
|
||||||
|
+ int status = urb->status;
|
||||||
|
+ int retval;
|
||||||
|
+
|
||||||
|
+ switch (status) {
|
||||||
|
+ case 0:
|
||||||
|
+ new_data(appleir, urb->transfer_buffer, urb->actual_length);
|
||||||
|
+ break;
|
||||||
|
+ case -ECONNRESET:
|
||||||
|
+ case -ENOENT:
|
||||||
|
+ case -ESHUTDOWN:
|
||||||
|
+ /* This urb is terminated, clean up */
|
||||||
|
+ dbginfo(&appleir->input_dev->dev, "%s - urb shutting down with status: %d", __func__,
|
||||||
|
+ urb->status);
|
||||||
|
+ return;
|
||||||
|
+ default:
|
||||||
|
+ dbginfo(&appleir->input_dev->dev, "%s - nonzero urb status received: %d", __func__,
|
||||||
|
+ urb->status);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
|
+ if (retval)
|
||||||
|
+ err("%s - usb_submit_urb failed with result %d", __func__,
|
||||||
|
+ retval);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appleir_open(struct input_dev *dev)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = input_get_drvdata(dev);
|
||||||
|
+ struct usb_interface *intf = usb_ifnum_to_if(appleir->usbdev, 0);
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ r = usb_autopm_get_interface(intf);
|
||||||
|
+ if (r) {
|
||||||
|
+ dev_err(&intf->dev,
|
||||||
|
+ "%s(): usb_autopm_get_interface() = %d\n", __func__, r);
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ mutex_lock(&appleir_mutex);
|
||||||
|
+
|
||||||
|
+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC)) {
|
||||||
|
+ r = -EIO;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ appleir->flags |= APPLEIR_OPENED;
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&appleir_mutex);
|
||||||
|
+
|
||||||
|
+ usb_autopm_put_interface(intf);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+fail:
|
||||||
|
+ mutex_unlock(&appleir_mutex);
|
||||||
|
+ usb_autopm_put_interface(intf);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void appleir_close(struct input_dev *dev)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = input_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ mutex_lock(&appleir_mutex);
|
||||||
|
+
|
||||||
|
+ if (!(appleir->flags & APPLEIR_SUSPENDED)) {
|
||||||
|
+ usb_kill_urb(appleir->urb);
|
||||||
|
+ del_timer_sync(&appleir->key_up_timer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ appleir->flags &= ~APPLEIR_OPENED;
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&appleir_mutex);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appleir_probe(struct usb_interface *intf,
|
||||||
|
+ const struct usb_device_id *id)
|
||||||
|
+{
|
||||||
|
+ struct usb_device *dev = interface_to_usbdev(intf);
|
||||||
|
+ struct usb_endpoint_descriptor *endpoint;
|
||||||
|
+ struct appleir *appleir = NULL;
|
||||||
|
+ struct input_dev *input_dev;
|
||||||
|
+ int retval = -ENOMEM;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ appleir = kzalloc(sizeof(struct appleir), GFP_KERNEL);
|
||||||
|
+ if (!appleir)
|
||||||
|
+ goto allocfail;
|
||||||
|
+
|
||||||
|
+ appleir->data = usb_alloc_coherent(dev, URB_SIZE, GFP_KERNEL,
|
||||||
|
+ &appleir->dma_buf);
|
||||||
|
+ if (!appleir->data)
|
||||||
|
+ goto usbfail;
|
||||||
|
+
|
||||||
|
+ appleir->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
+ if (!appleir->urb)
|
||||||
|
+ goto urbfail;
|
||||||
|
+
|
||||||
|
+ appleir->usbdev = dev;
|
||||||
|
+
|
||||||
|
+ input_dev = input_allocate_device();
|
||||||
|
+ if (!input_dev)
|
||||||
|
+ goto inputfail;
|
||||||
|
+
|
||||||
|
+ appleir->input_dev = input_dev;
|
||||||
|
+
|
||||||
|
+ usb_make_path(dev, appleir->phys, sizeof(appleir->phys));
|
||||||
|
+ strlcpy(appleir->phys, "/input0", sizeof(appleir->phys));
|
||||||
|
+
|
||||||
|
+ input_dev->name = "Apple Infrared Remote Controller";
|
||||||
|
+ input_dev->phys = appleir->phys;
|
||||||
|
+ usb_to_input_id(dev, &input_dev->id);
|
||||||
|
+ input_dev->dev.parent = &intf->dev;
|
||||||
|
+ input_dev->keycode = appleir->keymap;
|
||||||
|
+ input_dev->keycodesize = sizeof(unsigned short);
|
||||||
|
+ input_dev->keycodemax = ARRAY_SIZE(appleir->keymap);
|
||||||
|
+
|
||||||
|
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
|
||||||
|
+
|
||||||
|
+ memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap));
|
||||||
|
+ for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
|
||||||
|
+ set_bit(appleir->keymap[i], input_dev->keybit);
|
||||||
|
+ clear_bit(KEY_RESERVED, input_dev->keybit);
|
||||||
|
+
|
||||||
|
+ input_set_drvdata(input_dev, appleir);
|
||||||
|
+ input_dev->open = appleir_open;
|
||||||
|
+ input_dev->close = appleir_close;
|
||||||
|
+
|
||||||
|
+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
|
||||||
|
+
|
||||||
|
+ usb_fill_int_urb(appleir->urb, dev,
|
||||||
|
+ usb_rcvintpipe(dev, endpoint->bEndpointAddress),
|
||||||
|
+ appleir->data, 8,
|
||||||
|
+ appleir_urb, appleir, endpoint->bInterval);
|
||||||
|
+
|
||||||
|
+ appleir->urb->transfer_dma = appleir->dma_buf;
|
||||||
|
+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||||
|
+
|
||||||
|
+ setup_timer(&appleir->key_up_timer,
|
||||||
|
+ key_up_tick, (unsigned long) appleir);
|
||||||
|
+
|
||||||
|
+ retval = input_register_device(appleir->input_dev);
|
||||||
|
+ if (retval)
|
||||||
|
+ goto inputfail;
|
||||||
|
+
|
||||||
|
+ usb_set_intfdata(intf, appleir);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+inputfail:
|
||||||
|
+ input_free_device(appleir->input_dev);
|
||||||
|
+
|
||||||
|
+urbfail:
|
||||||
|
+ usb_free_urb(appleir->urb);
|
||||||
|
+
|
||||||
|
+usbfail:
|
||||||
|
+ usb_free_coherent(dev, URB_SIZE, appleir->data,
|
||||||
|
+ appleir->dma_buf);
|
||||||
|
+
|
||||||
|
+allocfail:
|
||||||
|
+ kfree(appleir);
|
||||||
|
+
|
||||||
|
+ return retval;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void appleir_disconnect(struct usb_interface *intf)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = usb_get_intfdata(intf);
|
||||||
|
+
|
||||||
|
+ usb_set_intfdata(intf, NULL);
|
||||||
|
+ input_unregister_device(appleir->input_dev);
|
||||||
|
+ usb_free_urb(appleir->urb);
|
||||||
|
+ usb_free_coherent(interface_to_usbdev(intf), URB_SIZE,
|
||||||
|
+ appleir->data, appleir->dma_buf);
|
||||||
|
+ kfree(appleir);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appleir_suspend(struct usb_interface *interface,
|
||||||
|
+ pm_message_t message)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir = usb_get_intfdata(interface);
|
||||||
|
+
|
||||||
|
+ mutex_lock(&appleir_mutex);
|
||||||
|
+ if (appleir->flags & APPLEIR_OPENED)
|
||||||
|
+ usb_kill_urb(appleir->urb);
|
||||||
|
+
|
||||||
|
+ appleir->flags |= APPLEIR_SUSPENDED;
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&appleir_mutex);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appleir_resume(struct usb_interface *interface)
|
||||||
|
+{
|
||||||
|
+ struct appleir *appleir;
|
||||||
|
+ int r = 0;
|
||||||
|
+
|
||||||
|
+ appleir = usb_get_intfdata(interface);
|
||||||
|
+
|
||||||
|
+ mutex_lock(&appleir_mutex);
|
||||||
|
+ if (appleir->flags & APPLEIR_OPENED) {
|
||||||
|
+ struct usb_endpoint_descriptor *endpoint;
|
||||||
|
+
|
||||||
|
+ endpoint = &interface->cur_altsetting->endpoint[0].desc;
|
||||||
|
+ usb_fill_int_urb(appleir->urb, appleir->usbdev,
|
||||||
|
+ usb_rcvintpipe(appleir->usbdev, endpoint->bEndpointAddress),
|
||||||
|
+ appleir->data, 8,
|
||||||
|
+ appleir_urb, appleir, endpoint->bInterval);
|
||||||
|
+ appleir->urb->transfer_dma = appleir->dma_buf;
|
||||||
|
+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||||
|
+
|
||||||
|
+ /* And reset the USB device */
|
||||||
|
+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC))
|
||||||
|
+ r = -EIO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ appleir->flags &= ~APPLEIR_SUSPENDED;
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&appleir_mutex);
|
||||||
|
+
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct usb_driver appleir_driver = {
|
||||||
|
+ .name = "appleir",
|
||||||
|
+ .probe = appleir_probe,
|
||||||
|
+ .disconnect = appleir_disconnect,
|
||||||
|
+ .suspend = appleir_suspend,
|
||||||
|
+ .resume = appleir_resume,
|
||||||
|
+ .reset_resume = appleir_resume,
|
||||||
|
+ .id_table = appleir_ids,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init appleir_init(void)
|
||||||
|
+{
|
||||||
|
+ return usb_register(&appleir_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit appleir_exit(void)
|
||||||
|
+{
|
||||||
|
+ usb_deregister(&appleir_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+module_init(appleir_init);
|
||||||
|
+module_exit(appleir_exit);
|
||||||
|
--
|
||||||
|
1.7.2.2
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
From: Eric W. Biederman <ebiederm@xmission.com>
|
||||||
|
Date: Sun, 13 Jun 2010 03:31:06 +0000 (+0000)
|
||||||
|
Subject: af_netlink: Add needed scm_destroy after scm_send.
|
||||||
|
X-Git-Tag: v2.6.36-rc1~571^2~552
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=b47030c71dfd6c8cd5cb6e551b6f7f7cfc96f6a6
|
||||||
|
|
||||||
|
af_netlink: Add needed scm_destroy after scm_send.
|
||||||
|
|
||||||
|
scm_send occasionally allocates state in the scm_cookie, so I have
|
||||||
|
modified netlink_sendmsg to guarantee that when scm_send succeeds
|
||||||
|
scm_destory will be called to free that state.
|
||||||
|
|
||||||
|
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
|
||||||
|
Reviewed-by: Daniel Lezcano <daniel.lezcano@free.fr>
|
||||||
|
Acked-by: Pavel Emelyanov <xemul@openvz.org>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
|
||||||
|
index a2eb965..7aeaa83 100644
|
||||||
|
--- a/net/netlink/af_netlink.c
|
||||||
|
+++ b/net/netlink/af_netlink.c
|
||||||
|
@@ -1323,19 +1323,23 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||||
|
if (msg->msg_flags&MSG_OOB)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
- if (NULL == siocb->scm)
|
||||||
|
+ if (NULL == siocb->scm) {
|
||||||
|
siocb->scm = &scm;
|
||||||
|
+ memset(&scm, 0, sizeof(scm));
|
||||||
|
+ }
|
||||||
|
err = scm_send(sock, msg, siocb->scm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (msg->msg_namelen) {
|
||||||
|
+ err = -EINVAL;
|
||||||
|
if (addr->nl_family != AF_NETLINK)
|
||||||
|
- return -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
dst_pid = addr->nl_pid;
|
||||||
|
dst_group = ffs(addr->nl_groups);
|
||||||
|
+ err = -EPERM;
|
||||||
|
if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
|
||||||
|
- return -EPERM;
|
||||||
|
+ goto out;
|
||||||
|
} else {
|
||||||
|
dst_pid = nlk->dst_pid;
|
||||||
|
dst_group = nlk->dst_group;
|
||||||
|
@@ -1387,6 +1391,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||||
|
err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
|
||||||
|
|
||||||
|
out:
|
||||||
|
+ scm_destroy(siocb->scm);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
From f4680d3db71f13d2764340a9880745bf54f2469d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Arnaud Ebalard <arno@natisbad.org>
|
||||||
|
Date: Wed, 15 Dec 2010 12:16:30 +0000
|
||||||
|
Subject: [PATCH] asix: add USB ID for Logitec LAN-GTJ U2A
|
||||||
|
|
||||||
|
Logitec LAN-GTJ U2A (http://www.pro.logitec.co.jp/pro/g/gLAN-GTJU2A/)
|
||||||
|
USB 2.0 10/10/1000 Ethernet adapter is based on ASIX AX88178 chipset.
|
||||||
|
|
||||||
|
This patch adds missing USB ID for the device.
|
||||||
|
|
||||||
|
Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
drivers/net/usb/asix.c | 4 ++++
|
||||||
|
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
|
||||||
|
index aea4645..6140b56 100644
|
||||||
|
--- a/drivers/net/usb/asix.c
|
||||||
|
+++ b/drivers/net/usb/asix.c
|
||||||
|
@@ -1508,6 +1508,10 @@ static const struct usb_device_id products [] = {
|
||||||
|
USB_DEVICE (0x0b95, 0x1780),
|
||||||
|
.driver_info = (unsigned long) &ax88178_info,
|
||||||
|
}, {
|
||||||
|
+ // Logitec LAN-GTJ/U2A
|
||||||
|
+ USB_DEVICE (0x0789, 0x0160),
|
||||||
|
+ .driver_info = (unsigned long) &ax88178_info,
|
||||||
|
+}, {
|
||||||
|
// Linksys USB200M Rev 2
|
||||||
|
USB_DEVICE (0x13b1, 0x0018),
|
||||||
|
.driver_info = (unsigned long) &ax88772_info,
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
From 338d0f0a6fbc82407864606f5b64b75aeb3c70f2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Warns <Warns@pre-sense.de>
|
||||||
|
Date: Wed, 17 Aug 2011 17:59:56 +0200
|
||||||
|
Subject: [PATCH] befs: Validate length of long symbolic links.
|
||||||
|
|
||||||
|
Signed-off-by: Timo Warns <warns@pre-sense.de>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
---
|
||||||
|
fs/befs/linuxvfs.c | 23 ++++++++++++++---------
|
||||||
|
1 files changed, 14 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
|
||||||
|
index 54b8c28..720d885 100644
|
||||||
|
--- a/fs/befs/linuxvfs.c
|
||||||
|
+++ b/fs/befs/linuxvfs.c
|
||||||
|
@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||||
|
befs_data_stream *data = &befs_ino->i_data.ds;
|
||||||
|
befs_off_t len = data->size;
|
||||||
|
|
||||||
|
- befs_debug(sb, "Follow long symlink");
|
||||||
|
-
|
||||||
|
- link = kmalloc(len, GFP_NOFS);
|
||||||
|
- if (!link) {
|
||||||
|
- link = ERR_PTR(-ENOMEM);
|
||||||
|
- } else if (befs_read_lsymlink(sb, data, link, len) != len) {
|
||||||
|
- kfree(link);
|
||||||
|
- befs_error(sb, "Failed to read entire long symlink");
|
||||||
|
+ if (len == 0) {
|
||||||
|
+ befs_error(sb, "Long symlink with illegal length");
|
||||||
|
link = ERR_PTR(-EIO);
|
||||||
|
} else {
|
||||||
|
- link[len - 1] = '\0';
|
||||||
|
+ befs_debug(sb, "Follow long symlink");
|
||||||
|
+
|
||||||
|
+ link = kmalloc(len, GFP_NOFS);
|
||||||
|
+ if (!link) {
|
||||||
|
+ link = ERR_PTR(-ENOMEM);
|
||||||
|
+ } else if (befs_read_lsymlink(sb, data, link, len) != len) {
|
||||||
|
+ kfree(link);
|
||||||
|
+ befs_error(sb, "Failed to read entire long symlink");
|
||||||
|
+ link = ERR_PTR(-EIO);
|
||||||
|
+ } else {
|
||||||
|
+ link[len - 1] = '\0';
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
link = befs_ino->i_data.symlink;
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
From: Xiaotian Feng <dfeng@redhat.com>
|
||||||
|
Date: Mon, 29 Nov 2010 09:03:55 +0000 (+0100)
|
||||||
|
Subject: block: check for proper length of iov entries earlier in blk_rq_map_user_iov()
|
||||||
|
X-Git-Tag: v2.6.37-rc7~10^2~5
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=54787556
|
||||||
|
|
||||||
|
block: check for proper length of iov entries earlier in blk_rq_map_user_iov()
|
||||||
|
|
||||||
|
commit 9284bcf checks for proper length of iov entries in
|
||||||
|
blk_rq_map_user_iov(). But if the map is unaligned, kernel
|
||||||
|
will break out the loop without checking for the proper length.
|
||||||
|
So we need to check the proper length before the unalign check.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/block/blk-map.c b/block/blk-map.c
|
||||||
|
index 5d5dbe4..e663ac2 100644
|
||||||
|
--- a/block/blk-map.c
|
||||||
|
+++ b/block/blk-map.c
|
||||||
|
@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
|
||||||
|
for (i = 0; i < iov_count; i++) {
|
||||||
|
unsigned long uaddr = (unsigned long)iov[i].iov_base;
|
||||||
|
|
||||||
|
+ if (!iov[i].iov_len)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
if (uaddr & queue_dma_alignment(q)) {
|
||||||
|
unaligned = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (!iov[i].iov_len)
|
||||||
|
- return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unaligned || (q->dma_pad_mask & len) || map_data)
|
|
@ -0,0 +1,32 @@
|
||||||
|
From: Dan Rosenberg <drosenberg@vsecurity.com>
|
||||||
|
Date: Fri, 24 Jun 2011 12:38:05 +0000 (-0400)
|
||||||
|
Subject: Bluetooth: Prevent buffer overflow in l2cap config request
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpadovan%2Fbluetooth-2.6.git;a=commitdiff_plain;h=7ac28817536797fd40e9646452183606f9e17f71
|
||||||
|
|
||||||
|
Bluetooth: Prevent buffer overflow in l2cap config request
|
||||||
|
[ backport to 2.6.35 ]
|
||||||
|
|
||||||
|
A remote user can provide a small value for the command size field in
|
||||||
|
the command header of an l2cap configuration request, resulting in an
|
||||||
|
integer underflow when subtracting the size of the configuration request
|
||||||
|
header. This results in copying a very large amount of data via
|
||||||
|
memcpy() and destroying the kernel heap. Check for underflow.
|
||||||
|
|
||||||
|
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
|
||||||
|
Cc: stable <stable@kernel.org>
|
||||||
|
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
||||||
|
index 56fdd91..7d8a66b 100644
|
||||||
|
--- a/net/bluetooth/l2cap.c
|
||||||
|
+++ b/net/bluetooth/l2cap.c
|
||||||
|
@@ -2962,7 +2962,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
|
||||||
|
|
||||||
|
/* Reject if config buffer is too small. */
|
||||||
|
len = cmd_len - sizeof(*req);
|
||||||
|
- if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
|
||||||
|
+ if (len < 0 || l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
|
||||||
|
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
|
||||||
|
l2cap_build_conf_rsp(sk, rsp,
|
||||||
|
L2CAP_CONF_REJECT, flags), rsp);
|
|
@ -0,0 +1,42 @@
|
||||||
|
bridge: Fix mglist corruption that leads to memory corruption
|
||||||
|
|
||||||
|
The list mp->mglist is used to indicate whether a multicast group
|
||||||
|
is active on the bridge interface itself as opposed to one of the
|
||||||
|
constituent interfaces in the bridge.
|
||||||
|
|
||||||
|
Unfortunately the operation that adds the mp->mglist node to the
|
||||||
|
list neglected to check whether it has already been added. This
|
||||||
|
leads to list corruption in the form of nodes pointing to itself.
|
||||||
|
|
||||||
|
Normally this would be quite obvious as it would cause an infinite
|
||||||
|
loop when walking the list. However, as this list is never actually
|
||||||
|
walked (which means that we don't really need it, I'll get rid of
|
||||||
|
it in a subsequent patch), this instead is hidden until we perform
|
||||||
|
a delete operation on the affected nodes.
|
||||||
|
|
||||||
|
As the same node may now be pointed to by more than one node, the
|
||||||
|
delete operations can then cause modification of freed memory.
|
||||||
|
|
||||||
|
This was observed in practice to cause corruption in 512-byte slabs,
|
||||||
|
most commonly leading to crashes in jbd2.
|
||||||
|
|
||||||
|
Thanks to Josef Bacik for pointing me in the right direction.
|
||||||
|
|
||||||
|
Reported-by: Ian Page Hands <ihands@redhat.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
|
||||||
|
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
||||||
|
index f701a21..802d3f8 100644
|
||||||
|
--- a/net/bridge/br_multicast.c
|
||||||
|
+++ b/net/bridge/br_multicast.c
|
||||||
|
@@ -719,7 +719,8 @@ static int br_multicast_add_group(struct net_bridge *br,
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!port) {
|
||||||
|
- hlist_add_head(&mp->mglist, &br->mglist);
|
||||||
|
+ if (hlist_unhashed(&mp->mglist))
|
||||||
|
+ hlist_add_head(&mp->mglist, &br->mglist);
|
||||||
|
mod_timer(&mp->timer, now + br->multicast_membership_interval);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
From 8f172904b45a6b530eaa345b23956682629bddee Mon Sep 17 00:00:00 2001
|
||||||
|
From: Josef Bacik <josef@redhat.com>
|
||||||
|
Date: Fri, 22 Oct 2010 15:26:53 -0400
|
||||||
|
Subject: Btrfs: fix error handling in btrfs_get_sb
|
||||||
|
|
||||||
|
If we failed to find the root subvol id, or the subvol=<name>, we would
|
||||||
|
deactivate the locked super and close the devices. The problem is at this point
|
||||||
|
we have gotten the SB all setup, which includes setting super_operations, so
|
||||||
|
when we'd deactiveate the super, we'd do a close_ctree() which closes the
|
||||||
|
devices, so we'd end up closing the devices twice. So if you do something like
|
||||||
|
this
|
||||||
|
|
||||||
|
mount /dev/sda1 /mnt/test1
|
||||||
|
mount /dev/sda1 /mnt/test2 -o subvol=xxx
|
||||||
|
umount /mnt/test1
|
||||||
|
|
||||||
|
it would blow up (if subvol xxx doesn't exist). This patch fixes that problem.
|
||||||
|
Thanks,
|
||||||
|
|
||||||
|
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||||
|
---
|
||||||
|
fs/btrfs/super.c | 7 +++----
|
||||||
|
1 files changed, 3 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
|
||||||
|
index f2393b3..c246f25 100644
|
||||||
|
--- a/fs/btrfs/super.c
|
||||||
|
+++ b/fs/btrfs/super.c
|
||||||
|
@@ -629,7 +629,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
if (IS_ERR(root)) {
|
||||||
|
error = PTR_ERR(root);
|
||||||
|
deactivate_locked_super(s);
|
||||||
|
- goto error;
|
||||||
|
+ goto error_free_subvol_name;
|
||||||
|
}
|
||||||
|
/* if they gave us a subvolume name bind mount into that */
|
||||||
|
if (strcmp(subvol_name, ".")) {
|
||||||
|
@@ -643,14 +643,14 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
deactivate_locked_super(s);
|
||||||
|
error = PTR_ERR(new_root);
|
||||||
|
dput(root);
|
||||||
|
- goto error_close_devices;
|
||||||
|
+ goto error_free_subvol_name;
|
||||||
|
}
|
||||||
|
if (!new_root->d_inode) {
|
||||||
|
dput(root);
|
||||||
|
dput(new_root);
|
||||||
|
deactivate_locked_super(s);
|
||||||
|
error = -ENXIO;
|
||||||
|
- goto error_close_devices;
|
||||||
|
+ goto error_free_subvol_name;
|
||||||
|
}
|
||||||
|
dput(root);
|
||||||
|
root = new_root;
|
||||||
|
@@ -668,7 +668,6 @@ error_close_devices:
|
||||||
|
btrfs_close_devices(fs_devices);
|
||||||
|
error_free_subvol_name:
|
||||||
|
kfree(subvol_name);
|
||||||
|
-error:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.3.3
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
From 3d07b06c5d62e98b46ef21980e5c2a904990149f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kyle McMartin <kyle@mcmartin.ca>
|
||||||
|
Date: Fri, 10 Dec 2010 10:32:29 -0500
|
||||||
|
Subject: [PATCH] Btrfs - fix race between btrfs_get_sb() and umount
|
||||||
|
|
||||||
|
When mounting a btrfs file system btrfs_test_super() may attempt to
|
||||||
|
use sb->s_fs_info, the btrfs root, of a super block that is going away
|
||||||
|
and that has had the btrfs root set to NULL in its ->put_super(). But
|
||||||
|
if the super block is going away it cannot be an existing super block
|
||||||
|
so we can return false in this case.
|
||||||
|
|
||||||
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
||||||
|
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
fs/btrfs/super.c
|
||||||
|
---
|
||||||
|
fs/btrfs/super.c | 6 ++++++
|
||||||
|
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
|
||||||
|
index 89e299f..f4a4dd3 100644
|
||||||
|
--- a/fs/btrfs/super.c
|
||||||
|
+++ b/fs/btrfs/super.c
|
||||||
|
@@ -551,6 +551,12 @@ static int btrfs_test_super(struct super_block *s, void *data)
|
||||||
|
struct btrfs_root *test_root = data;
|
||||||
|
struct btrfs_root *root = btrfs_sb(s);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * If this super block is going away, return false as it
|
||||||
|
+ * can't match as an existing super block.
|
||||||
|
+ */
|
||||||
|
+ if (!atomic_read(&s->s_active))
|
||||||
|
+ return 0;
|
||||||
|
return root->fs_info->fs_devices == test_root->fs_info->fs_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.3.3
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
From: Josef Bacik <josef@redhat.com>
|
||||||
|
Date: Mon, 22 Nov 2010 18:50:32 +0000 (+0000)
|
||||||
|
Subject: Btrfs: fix typo in fallocate to make it honor actual size
|
||||||
|
X-Git-Tag: v2.6.37-rc4~6^2~7
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=55a61d1d06a3dc443d0db8aaa613365dcb83b98a
|
||||||
|
|
||||||
|
Btrfs: fix typo in fallocate to make it honor actual size
|
||||||
|
|
||||||
|
[ Trivial backport to 2.6.35/2.6.36 ]
|
||||||
|
|
||||||
|
There is a typo in __btrfs_prealloc_file_range() where we set the i_size to
|
||||||
|
actual_len/cur_offset, and then just set it to cur_offset again, and do the same
|
||||||
|
with btrfs_ordered_update_i_size(). This fixes it back to keeping i_size in a
|
||||||
|
local variable and then updating i_size properly. Tested this with
|
||||||
|
|
||||||
|
xfs_io -F -f -c "falloc 0 1" -c "pwrite 0 1" foo
|
||||||
|
|
||||||
|
stat'ing foo gives us a size of 1 instead of 4096 like it was. Thanks,
|
||||||
|
|
||||||
|
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||||
|
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
||||||
|
index 37cc177..0058fb3 100644
|
||||||
|
--- a/fs/btrfs/inode.c
|
||||||
|
+++ b/fs/btrfs/inode.c
|
||||||
|
@@ -7002,6 +7002,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
|
||||||
|
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||||
|
struct btrfs_key ins;
|
||||||
|
u64 cur_offset = start;
|
||||||
|
+ u64 i_size;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (num_bytes > 0) {
|
||||||
|
@@ -7043,11 +7044,11 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
|
||||||
|
(actual_len > inode->i_size) &&
|
||||||
|
(cur_offset > inode->i_size)) {
|
||||||
|
if (cur_offset > actual_len)
|
||||||
|
- i_size_write(inode, actual_len);
|
||||||
|
+ i_size = actual_len;
|
||||||
|
else
|
||||||
|
- i_size_write(inode, cur_offset);
|
||||||
|
- i_size_write(inode, cur_offset);
|
||||||
|
- btrfs_ordered_update_i_size(inode, cur_offset, NULL);
|
||||||
|
+ i_size = cur_offset;
|
||||||
|
+ i_size_write(inode, i_size);
|
||||||
|
+ btrfs_ordered_update_i_size(inode, i_size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = btrfs_update_inode(trans, root, inode);
|
|
@ -0,0 +1,117 @@
|
||||||
|
From 2049a8887f699650cd66c3da220e84d5c140c546 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kyle McMartin <kyle@mcmartin.ca>
|
||||||
|
Date: Fri, 10 Dec 2010 10:09:15 -0500
|
||||||
|
Subject: [PATCH] Btrfs: setup blank root and fs_info for mount time
|
||||||
|
|
||||||
|
There is a problem with how we use sget, it searches through the list of supers
|
||||||
|
attached to the fs_type looking for a super with the same fs_devices as what
|
||||||
|
we're trying to mount. This depends on sb->s_fs_info being filled, but we don't
|
||||||
|
fill that in until we get to btrfs_fill_super, so we could hit supers on the
|
||||||
|
fs_type super list that have a null s_fs_info. In order to fix that we need to
|
||||||
|
go ahead and setup a blank root with a blank fs_info to hold fs_devices, that
|
||||||
|
way our test will work out right and then we can set s_fs_info in
|
||||||
|
btrfs_set_super, and then open_ctree will simply use our pre-allocated root and
|
||||||
|
fs_info when setting everything up. Thanks,
|
||||||
|
|
||||||
|
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||||
|
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
fs/btrfs/super.c
|
||||||
|
---
|
||||||
|
fs/btrfs/disk-io.c | 6 ++----
|
||||||
|
fs/btrfs/super.c | 34 +++++++++++++++++++++++++++++++---
|
||||||
|
2 files changed, 33 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
||||||
|
index 34f7c37..b6c3dad 100644
|
||||||
|
--- a/fs/btrfs/disk-io.c
|
||||||
|
+++ b/fs/btrfs/disk-io.c
|
||||||
|
@@ -1539,10 +1539,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||||
|
GFP_NOFS);
|
||||||
|
struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
|
||||||
|
GFP_NOFS);
|
||||||
|
- struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root),
|
||||||
|
- GFP_NOFS);
|
||||||
|
- struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
|
||||||
|
- GFP_NOFS);
|
||||||
|
+ struct btrfs_root *tree_root = btrfs_sb(sb);
|
||||||
|
+ struct btrfs_fs_info *fs_info = tree_root->fs_info;
|
||||||
|
struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
|
||||||
|
GFP_NOFS);
|
||||||
|
struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
|
||||||
|
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
|
||||||
|
index f2393b3..89e299f 100644
|
||||||
|
--- a/fs/btrfs/super.c
|
||||||
|
+++ b/fs/btrfs/super.c
|
||||||
|
@@ -548,12 +548,20 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
||||||
|
|
||||||
|
static int btrfs_test_super(struct super_block *s, void *data)
|
||||||
|
{
|
||||||
|
- struct btrfs_fs_devices *test_fs_devices = data;
|
||||||
|
+ struct btrfs_root *test_root = data;
|
||||||
|
struct btrfs_root *root = btrfs_sb(s);
|
||||||
|
|
||||||
|
- return root->fs_info->fs_devices == test_fs_devices;
|
||||||
|
+ return root->fs_info->fs_devices == test_root->fs_info->fs_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int btrfs_set_super(struct super_block *s, void *data)
|
||||||
|
+{
|
||||||
|
+ s->s_fs_info = data;
|
||||||
|
+
|
||||||
|
+ return set_anon_super(s, data);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Find a superblock for the given device / mount point.
|
||||||
|
*
|
||||||
|
@@ -567,6 +575,8 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
struct super_block *s;
|
||||||
|
struct dentry *root;
|
||||||
|
struct btrfs_fs_devices *fs_devices = NULL;
|
||||||
|
+ struct btrfs_root *tree_root = NULL;
|
||||||
|
+ struct btrfs_fs_info *fs_info = NULL;
|
||||||
|
fmode_t mode = FMODE_READ;
|
||||||
|
char *subvol_name = NULL;
|
||||||
|
u64 subvol_objectid = 0;
|
||||||
|
@@ -595,8 +605,24 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
goto error_close_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Setup a dummy root and fs_info for test/set super. This is because
|
||||||
|
+ * we don't actually fill this stuff out until open_ctree, but we need
|
||||||
|
+ * it for searching for existing supers, so this lets us do that and
|
||||||
|
+ * then open_ctree will properly initialize everything later.
|
||||||
|
+ */
|
||||||
|
+ fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
|
||||||
|
+ tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
|
||||||
|
+ if (!fs_info || !tree_root) {
|
||||||
|
+ error = -ENOMEM;
|
||||||
|
+ goto error_close_devices;
|
||||||
|
+ }
|
||||||
|
+ fs_info->tree_root = tree_root;
|
||||||
|
+ fs_info->fs_devices = fs_devices;
|
||||||
|
+ tree_root->fs_info = fs_info;
|
||||||
|
+
|
||||||
|
bdev = fs_devices->latest_bdev;
|
||||||
|
- s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
|
||||||
|
+ s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);
|
||||||
|
if (IS_ERR(s))
|
||||||
|
goto error_s;
|
||||||
|
|
||||||
|
@@ -666,6 +692,8 @@ error_s:
|
||||||
|
error = PTR_ERR(s);
|
||||||
|
error_close_devices:
|
||||||
|
btrfs_close_devices(fs_devices);
|
||||||
|
+ kfree(fs_info);
|
||||||
|
+ kfree(tree_root);
|
||||||
|
error_free_subvol_name:
|
||||||
|
kfree(subvol_name);
|
||||||
|
error:
|
||||||
|
--
|
||||||
|
1.7.3.3
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
Path: news.gmane.org!not-for-mail
|
||||||
|
From: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
|
||||||
|
Newsgroups: gmane.linux.kernel.cifs
|
||||||
|
Subject: [PATCH] cifs: fix possible memory corruption in CIFSFindNext
|
||||||
|
Date: Tue, 23 Aug 2011 07:21:28 -0400
|
||||||
|
Lines: 37
|
||||||
|
Approved: news@gmane.org
|
||||||
|
Message-ID: <1314098488-1547-1-git-send-email-jlayton@redhat.com>
|
||||||
|
NNTP-Posting-Host: lo.gmane.org
|
||||||
|
X-Trace: dough.gmane.org 1314098501 27164 80.91.229.12 (23 Aug 2011 11:21:41 GMT)
|
||||||
|
X-Complaints-To: usenet@dough.gmane.org
|
||||||
|
NNTP-Posting-Date: Tue, 23 Aug 2011 11:21:41 +0000 (UTC)
|
||||||
|
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org
|
||||||
|
To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
|
||||||
|
Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Tue Aug 23 13:21:37 2011
|
||||||
|
Return-path: <linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
|
||||||
|
Envelope-to: glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org
|
||||||
|
Original-Received: from vger.kernel.org ([209.132.180.67])
|
||||||
|
by lo.gmane.org with esmtp (Exim 4.69)
|
||||||
|
(envelope-from <linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>)
|
||||||
|
id 1Qvp33-0003JC-05
|
||||||
|
for glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Tue, 23 Aug 2011 13:21:37 +0200
|
||||||
|
Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand
|
||||||
|
id S1752435Ab1HWLVg (ORCPT <rfc822;glkc-linux-cifs@m.gmane.org>);
|
||||||
|
Tue, 23 Aug 2011 07:21:36 -0400
|
||||||
|
Original-Received: from mail-gy0-f174.google.com ([209.85.160.174]:43114 "EHLO
|
||||||
|
mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||||
|
with ESMTP id S1751065Ab1HWLVf (ORCPT
|
||||||
|
<rfc822;linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>); Tue, 23 Aug 2011 07:21:35 -0400
|
||||||
|
Original-Received: by gya6 with SMTP id 6so4228912gya.19
|
||||||
|
for <linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; Tue, 23 Aug 2011 04:21:35 -0700 (PDT)
|
||||||
|
Original-Received: by 10.101.144.18 with SMTP id w18mr3505731ann.133.1314098494691;
|
||||||
|
Tue, 23 Aug 2011 04:21:34 -0700 (PDT)
|
||||||
|
Original-Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com [75.177.182.191])
|
||||||
|
by mx.google.com with ESMTPS id d33sm48355ano.35.2011.08.23.04.21.32
|
||||||
|
(version=SSLv3 cipher=OTHER);
|
||||||
|
Tue, 23 Aug 2011 04:21:33 -0700 (PDT)
|
||||||
|
X-Mailer: git-send-email 1.7.6
|
||||||
|
Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
|
||||||
|
Precedence: bulk
|
||||||
|
List-ID: <linux-cifs.vger.kernel.org>
|
||||||
|
X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
|
||||||
|
Xref: news.gmane.org gmane.linux.kernel.cifs:4006
|
||||||
|
Archived-At: <http://permalink.gmane.org/gmane.linux.kernel.cifs/4006>
|
||||||
|
|
||||||
|
The name_len variable in CIFSFindNext is a signed int that gets set to
|
||||||
|
the resume_name_len in the cifs_search_info. The resume_name_len however
|
||||||
|
is unsigned and for some infolevels is populated directly from a 32 bit
|
||||||
|
value sent by the server.
|
||||||
|
|
||||||
|
If the server sends a very large value for this, then that value could
|
||||||
|
look negative when converted to a signed int. That would make that
|
||||||
|
value pass the PATH_MAX check later in CIFSFindNext. The name_len would
|
||||||
|
then be used as a length value for a memcpy. It would then be treated
|
||||||
|
as unsigned again, and the memcpy scribbles over a ton of memory.
|
||||||
|
|
||||||
|
Fix this by making the name_len an unsigned value in CIFSFindNext.
|
||||||
|
|
||||||
|
Cc: <stable-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
|
||||||
|
Reported-by: Darren Lavender <dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org>
|
||||||
|
Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
|
||||||
|
---
|
||||||
|
fs/cifs/cifssmb.c | 3 ++-
|
||||||
|
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
|
||||||
|
index f4d0988..950464d 100644
|
||||||
|
--- a/fs/cifs/cifssmb.c
|
||||||
|
+++ b/fs/cifs/cifssmb.c
|
||||||
|
@@ -4089,7 +4089,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
|
||||||
|
T2_FNEXT_RSP_PARMS *parms;
|
||||||
|
char *response_data;
|
||||||
|
int rc = 0;
|
||||||
|
- int bytes_returned, name_len;
|
||||||
|
+ int bytes_returned;
|
||||||
|
+ unsigned int name_len;
|
||||||
|
__u16 params, byte_count;
|
||||||
|
|
||||||
|
cFYI(1, "In FindNext");
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -87,5 +87,7 @@ CONFIG_PM_ADVANCED_DEBUG=y
|
||||||
CONFIG_CEPH_FS_PRETTYDEBUG=y
|
CONFIG_CEPH_FS_PRETTYDEBUG=y
|
||||||
CONFIG_QUOTA_DEBUG=y
|
CONFIG_QUOTA_DEBUG=y
|
||||||
|
|
||||||
|
# CONFIG_PCI_DEFAULT_USE_CRS is not set
|
||||||
|
|
||||||
CONFIG_KGDB_KDB=y
|
CONFIG_KGDB_KDB=y
|
||||||
CONFIG_KDB_KEYBOARD=y
|
CONFIG_KDB_KEYBOARD=y
|
||||||
|
|
|
@ -684,7 +684,7 @@ CONFIG_MD_RAID0=m
|
||||||
CONFIG_MD_RAID1=m
|
CONFIG_MD_RAID1=m
|
||||||
CONFIG_MD_RAID10=m
|
CONFIG_MD_RAID10=m
|
||||||
CONFIG_MD_RAID456=m
|
CONFIG_MD_RAID456=m
|
||||||
CONFIG_MULTICORE_RAID456=y
|
# CONFIG_MULTICORE_RAID456 is not set
|
||||||
CONFIG_ASYNC_RAID6_TEST=m
|
CONFIG_ASYNC_RAID6_TEST=m
|
||||||
CONFIG_BLK_DEV_DM=y
|
CONFIG_BLK_DEV_DM=y
|
||||||
CONFIG_DM_CRYPT=m
|
CONFIG_DM_CRYPT=m
|
||||||
|
@ -1423,11 +1423,11 @@ CONFIG_ATMEL=m
|
||||||
CONFIG_B43=m
|
CONFIG_B43=m
|
||||||
CONFIG_B43_PCMCIA=y
|
CONFIG_B43_PCMCIA=y
|
||||||
CONFIG_B43_SDIO=y
|
CONFIG_B43_SDIO=y
|
||||||
CONFIG_B43_DEBUG=y
|
# CONFIG_B43_DEBUG is not set
|
||||||
CONFIG_B43_PHY_LP=y
|
CONFIG_B43_PHY_LP=y
|
||||||
# CONFIG_B43_FORCE_PIO is not set
|
# CONFIG_B43_FORCE_PIO is not set
|
||||||
CONFIG_B43LEGACY=m
|
CONFIG_B43LEGACY=m
|
||||||
CONFIG_B43LEGACY_DEBUG=y
|
# CONFIG_B43LEGACY_DEBUG is not set
|
||||||
CONFIG_B43LEGACY_DMA=y
|
CONFIG_B43LEGACY_DMA=y
|
||||||
CONFIG_B43LEGACY_PIO=y
|
CONFIG_B43LEGACY_PIO=y
|
||||||
CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
|
CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
|
||||||
|
@ -2193,7 +2193,7 @@ CONFIG_WDTPCI=m
|
||||||
# CONFIG_ACQUIRE_WDT is not set
|
# CONFIG_ACQUIRE_WDT is not set
|
||||||
# CONFIG_ADVANTECH_WDT is not set
|
# CONFIG_ADVANTECH_WDT is not set
|
||||||
# CONFIG_EUROTECH_WDT is not set
|
# CONFIG_EUROTECH_WDT is not set
|
||||||
# CONFIG_IB700_WDT is not set
|
CONFIG_IB700_WDT=m
|
||||||
# CONFIG_MIXCOMWD is not set
|
# CONFIG_MIXCOMWD is not set
|
||||||
# CONFIG_SCx200_WDT is not set
|
# CONFIG_SCx200_WDT is not set
|
||||||
# CONFIG_60XX_WDT is not set
|
# CONFIG_60XX_WDT is not set
|
||||||
|
@ -2308,6 +2308,7 @@ CONFIG_DRM_NOUVEAU=m
|
||||||
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
|
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
|
||||||
CONFIG_DRM_NOUVEAU_DEBUG=y
|
CONFIG_DRM_NOUVEAU_DEBUG=y
|
||||||
CONFIG_DRM_I2C_CH7006=m
|
CONFIG_DRM_I2C_CH7006=m
|
||||||
|
CONFIG_DRM_I2C_SIL164=m
|
||||||
CONFIG_DRM_VMWGFX=m
|
CONFIG_DRM_VMWGFX=m
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -2366,6 +2367,7 @@ CONFIG_VIDEO_EM28XX_DVB=m
|
||||||
CONFIG_VIDEO_CX231XX=m
|
CONFIG_VIDEO_CX231XX=m
|
||||||
CONFIG_VIDEO_CX231XX_ALSA=m
|
CONFIG_VIDEO_CX231XX_ALSA=m
|
||||||
CONFIG_VIDEO_CX231XX_DVB=m
|
CONFIG_VIDEO_CX231XX_DVB=m
|
||||||
|
CONFIG_VIDEO_CX231XX_RC=y
|
||||||
CONFIG_VIDEO_HEXIUM_ORION=m
|
CONFIG_VIDEO_HEXIUM_ORION=m
|
||||||
CONFIG_VIDEO_HEXIUM_GEMINI=m
|
CONFIG_VIDEO_HEXIUM_GEMINI=m
|
||||||
CONFIG_VIDEO_IVTV=m
|
CONFIG_VIDEO_IVTV=m
|
||||||
|
@ -2380,6 +2382,7 @@ CONFIG_VIDEO_SAA6588=m
|
||||||
CONFIG_VIDEO_SAA7134=m
|
CONFIG_VIDEO_SAA7134=m
|
||||||
CONFIG_VIDEO_SAA7134_ALSA=m
|
CONFIG_VIDEO_SAA7134_ALSA=m
|
||||||
CONFIG_VIDEO_SAA7134_DVB=m
|
CONFIG_VIDEO_SAA7134_DVB=m
|
||||||
|
CONFIG_VIDEO_SAA7134_RC=y
|
||||||
CONFIG_VIDEO_STRADIS=m
|
CONFIG_VIDEO_STRADIS=m
|
||||||
CONFIG_VIDEO_USBVISION=m
|
CONFIG_VIDEO_USBVISION=m
|
||||||
CONFIG_VIDEO_W9966=m
|
CONFIG_VIDEO_W9966=m
|
||||||
|
@ -2394,6 +2397,11 @@ CONFIG_VIDEO_ZORAN_ZR36060=m
|
||||||
CONFIG_VIDEO_FB_IVTV=m
|
CONFIG_VIDEO_FB_IVTV=m
|
||||||
CONFIG_VIDEO_SAA7164=m
|
CONFIG_VIDEO_SAA7164=m
|
||||||
CONFIG_VIDEO_TLG2300=m
|
CONFIG_VIDEO_TLG2300=m
|
||||||
|
# CONFIG_VIDEO_TIMBERDALE is not set
|
||||||
|
CONFIG_VIDEO_SR030PC30=m
|
||||||
|
# Doesn't build on 2.6.35
|
||||||
|
# CONFIG_VIDEO_VIA_CAMERA is not set
|
||||||
|
# CONFIG_VIDEO_NOON010PC30 is not set
|
||||||
|
|
||||||
CONFIG_USB_VIDEO_CLASS=m
|
CONFIG_USB_VIDEO_CLASS=m
|
||||||
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
|
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
|
||||||
|
@ -2409,6 +2417,7 @@ CONFIG_MEDIA_ATTACH=y
|
||||||
CONFIG_MEDIA_TUNER_CUSTOMISE=y
|
CONFIG_MEDIA_TUNER_CUSTOMISE=y
|
||||||
CONFIG_MEDIA_TUNER_SIMPLE=m
|
CONFIG_MEDIA_TUNER_SIMPLE=m
|
||||||
CONFIG_MEDIA_TUNER_TDA8290=m
|
CONFIG_MEDIA_TUNER_TDA8290=m
|
||||||
|
CONFIG_MEDIA_TUNER_TDA18218=m
|
||||||
CONFIG_MEDIA_TUNER_TEA5761=m
|
CONFIG_MEDIA_TUNER_TEA5761=m
|
||||||
CONFIG_MEDIA_TUNER_TEA5767=m
|
CONFIG_MEDIA_TUNER_TEA5767=m
|
||||||
CONFIG_MEDIA_TUNER_MT20XX=m
|
CONFIG_MEDIA_TUNER_MT20XX=m
|
||||||
|
@ -2491,6 +2500,10 @@ CONFIG_DVB_ATBM8830=m
|
||||||
CONFIG_DVB_TDA665x=m
|
CONFIG_DVB_TDA665x=m
|
||||||
CONFIG_DVB_STV0299=m
|
CONFIG_DVB_STV0299=m
|
||||||
CONFIG_DVB_MB86A16=m
|
CONFIG_DVB_MB86A16=m
|
||||||
|
CONFIG_DVB_USB_LME2510=m
|
||||||
|
CONFIG_DVB_S5H1432=m
|
||||||
|
CONFIG_DVB_MB86A20S=m
|
||||||
|
CONFIG_DVB_IX2505V=m
|
||||||
|
|
||||||
#
|
#
|
||||||
# Supported Frontend Modules
|
# Supported Frontend Modules
|
||||||
|
@ -2517,6 +2530,7 @@ CONFIG_DVB_LGS8GL5=m
|
||||||
CONFIG_DVB_DUMMY_FE=m
|
CONFIG_DVB_DUMMY_FE=m
|
||||||
CONFIG_DVB_FIREDTV=m
|
CONFIG_DVB_FIREDTV=m
|
||||||
CONFIG_DVB_NGENE=m
|
CONFIG_DVB_NGENE=m
|
||||||
|
# CONFIG_DVB_CXD2099 is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Supported SAA7146 based PCI Adapters
|
# Supported SAA7146 based PCI Adapters
|
||||||
|
@ -2571,6 +2585,8 @@ CONFIG_DVB_PT1=m
|
||||||
CONFIG_MANTIS_CORE=m
|
CONFIG_MANTIS_CORE=m
|
||||||
CONFIG_DVB_MANTIS=m
|
CONFIG_DVB_MANTIS=m
|
||||||
CONFIG_DVB_HOPPER=m
|
CONFIG_DVB_HOPPER=m
|
||||||
|
CONFIG_DVB_USB_TECHNISAT_USB2=m
|
||||||
|
CONFIG_DVB_DIB9000=m
|
||||||
|
|
||||||
CONFIG_VIDEO_SAA7146=m
|
CONFIG_VIDEO_SAA7146=m
|
||||||
CONFIG_VIDEO_SAA7146_VV=m
|
CONFIG_VIDEO_SAA7146_VV=m
|
||||||
|
@ -2581,14 +2597,22 @@ CONFIG_VIDEO_PVRUSB2_SYSFS=y
|
||||||
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
|
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
|
||||||
|
|
||||||
CONFIG_RC_MAP=m
|
CONFIG_RC_MAP=m
|
||||||
|
CONFIG_RC_CORE=m
|
||||||
CONFIG_IR_NEC_DECODER=m
|
CONFIG_IR_NEC_DECODER=m
|
||||||
CONFIG_IR_RC5_DECODER=m
|
CONFIG_IR_RC5_DECODER=m
|
||||||
CONFIG_IR_RC6_DECODER=m
|
CONFIG_IR_RC6_DECODER=m
|
||||||
CONFIG_IR_JVC_DECODER=m
|
CONFIG_IR_JVC_DECODER=m
|
||||||
CONFIG_IR_SONY_DECODER=m
|
CONFIG_IR_SONY_DECODER=m
|
||||||
|
CONFIG_IR_RC5_SZ_DECODER=m
|
||||||
CONFIG_IR_LIRC_CODEC=m
|
CONFIG_IR_LIRC_CODEC=m
|
||||||
|
CONFIG_IR_ENE=m
|
||||||
CONFIG_IR_IMON=m
|
CONFIG_IR_IMON=m
|
||||||
|
CONFIG_IR_ITE_CIR=m
|
||||||
CONFIG_IR_MCEUSB=m
|
CONFIG_IR_MCEUSB=m
|
||||||
|
CONFIG_IR_NUVOTON=m
|
||||||
|
CONFIG_IR_STREAMZAP=m
|
||||||
|
CONFIG_IR_WINBOND_CIR=m
|
||||||
|
CONFIG_RC_LOOPBACK=m
|
||||||
|
|
||||||
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||||
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
|
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
|
||||||
|
@ -3031,6 +3055,8 @@ CONFIG_USB_GL860=m
|
||||||
CONFIG_USB_GSPCA_JEILINJ=m
|
CONFIG_USB_GSPCA_JEILINJ=m
|
||||||
CONFIG_USB_GSPCA_SPCA1528=m
|
CONFIG_USB_GSPCA_SPCA1528=m
|
||||||
CONFIG_USB_GSPCA_SQ930X=m
|
CONFIG_USB_GSPCA_SQ930X=m
|
||||||
|
CONFIG_USB_GSPCA_KONICA=m
|
||||||
|
CONFIG_USB_GSPCA_XIRLINK_CIT=m
|
||||||
|
|
||||||
CONFIG_USB_IBMCAM=m
|
CONFIG_USB_IBMCAM=m
|
||||||
CONFIG_USB_KONICAWC=m
|
CONFIG_USB_KONICAWC=m
|
||||||
|
@ -3038,6 +3064,7 @@ CONFIG_USB_KONICAWC=m
|
||||||
CONFIG_USB_S2255=m
|
CONFIG_USB_S2255=m
|
||||||
CONFIG_USB_SE401=m
|
CONFIG_USB_SE401=m
|
||||||
# CONFIG_VIDEO_SH_MOBILE_CEU is not set
|
# CONFIG_VIDEO_SH_MOBILE_CEU is not set
|
||||||
|
# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
|
||||||
# CONFIG_USB_STV680 is not set
|
# CONFIG_USB_STV680 is not set
|
||||||
# CONFIG_USB_SN9C102 is not set
|
# CONFIG_USB_SN9C102 is not set
|
||||||
CONFIG_USB_ZR364XX=m
|
CONFIG_USB_ZR364XX=m
|
||||||
|
@ -3052,6 +3079,9 @@ CONFIG_SOC_CAMERA_OV772X=m
|
||||||
CONFIG_SOC_CAMERA_MT9T112=m
|
CONFIG_SOC_CAMERA_MT9T112=m
|
||||||
CONFIG_SOC_CAMERA_RJ54N1=m
|
CONFIG_SOC_CAMERA_RJ54N1=m
|
||||||
CONFIG_SOC_CAMERA_OV9640=m
|
CONFIG_SOC_CAMERA_OV9640=m
|
||||||
|
CONFIG_SOC_CAMERA_IMX074=m
|
||||||
|
CONFIG_SOC_CAMERA_OV6650=m
|
||||||
|
CONFIG_SOC_CAMERA_OV2640=m
|
||||||
|
|
||||||
#
|
#
|
||||||
# USB Network adaptors
|
# USB Network adaptors
|
||||||
|
@ -3321,7 +3351,8 @@ CONFIG_QUOTACTL=y
|
||||||
CONFIG_DNOTIFY=y
|
CONFIG_DNOTIFY=y
|
||||||
# Autofsv3 is obsolete.
|
# Autofsv3 is obsolete.
|
||||||
# CONFIG_AUTOFS_FS is not set
|
# CONFIG_AUTOFS_FS is not set
|
||||||
CONFIG_AUTOFS4_FS=m
|
# systemd is dependant upon AUTOFS, so build it in.
|
||||||
|
CONFIG_AUTOFS4_FS=y
|
||||||
CONFIG_EXOFS_FS=m
|
CONFIG_EXOFS_FS=m
|
||||||
# CONFIG_EXOFS_DEBUG is not set
|
# CONFIG_EXOFS_DEBUG is not set
|
||||||
CONFIG_NILFS2_FS=m
|
CONFIG_NILFS2_FS=m
|
||||||
|
@ -3601,6 +3632,7 @@ CONFIG_CRYPTO_FIPS=y
|
||||||
CONFIG_CRYPTO_HW=y
|
CONFIG_CRYPTO_HW=y
|
||||||
CONFIG_CRYPTO_BLKCIPHER=y
|
CONFIG_CRYPTO_BLKCIPHER=y
|
||||||
CONFIG_CRYPTO_MANAGER=m
|
CONFIG_CRYPTO_MANAGER=m
|
||||||
|
CONFIG_CRYPTO_MANAGER_TESTS=y
|
||||||
# CONFIG_CRYPTO_CRYPTD is not set
|
# CONFIG_CRYPTO_CRYPTD is not set
|
||||||
CONFIG_CRYPTO_AES=m
|
CONFIG_CRYPTO_AES=m
|
||||||
CONFIG_CRYPTO_ARC4=m
|
CONFIG_CRYPTO_ARC4=m
|
||||||
|
@ -3722,7 +3754,7 @@ CONFIG_BLK_CGROUP=y
|
||||||
# CONFIG_SYSFS_DEPRECATED_V2 is not set
|
# CONFIG_SYSFS_DEPRECATED_V2 is not set
|
||||||
|
|
||||||
CONFIG_RELAY=y
|
CONFIG_RELAY=y
|
||||||
# CONFIG_PRINTK_TIME is not set
|
CONFIG_PRINTK_TIME=y
|
||||||
|
|
||||||
CONFIG_ENABLE_MUST_CHECK=y
|
CONFIG_ENABLE_MUST_CHECK=y
|
||||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||||
|
@ -3742,7 +3774,7 @@ CONFIG_IBMASR=m
|
||||||
CONFIG_PM_DEBUG=y
|
CONFIG_PM_DEBUG=y
|
||||||
CONFIG_PM_TRACE=y
|
CONFIG_PM_TRACE=y
|
||||||
# CONFIG_PM_VERBOSE is not set
|
# CONFIG_PM_VERBOSE is not set
|
||||||
CONFIG_PM_TEST_SUSPEND=y
|
# CONFIG_PM_TEST_SUSPEND is not set
|
||||||
CONFIG_PM_RUNTIME=y
|
CONFIG_PM_RUNTIME=y
|
||||||
|
|
||||||
## BEGIN ISA Junk.
|
## BEGIN ISA Junk.
|
||||||
|
@ -3851,6 +3883,7 @@ CONFIG_RADIO_ADAPTERS=y
|
||||||
# CONFIG_RADIO_TYPHOON is not set
|
# CONFIG_RADIO_TYPHOON is not set
|
||||||
# CONFIG_RADIO_ZOLTRIX is not set
|
# CONFIG_RADIO_ZOLTRIX is not set
|
||||||
# CONFIG_RADIO_SAA7706H is not set
|
# CONFIG_RADIO_SAA7706H is not set
|
||||||
|
# CONFIG_RADIO_WL1273 is not set
|
||||||
|
|
||||||
# CONFIG_SND_OPL4_LIB is not set
|
# CONFIG_SND_OPL4_LIB is not set
|
||||||
# CONFIG_SND_AD1816A is not set
|
# CONFIG_SND_AD1816A is not set
|
||||||
|
@ -3987,8 +4020,8 @@ CONFIG_AUXDISPLAY=y
|
||||||
CONFIG_UIO=m
|
CONFIG_UIO=m
|
||||||
CONFIG_UIO_CIF=m
|
CONFIG_UIO_CIF=m
|
||||||
CONFIG_UIO_SMX=m
|
CONFIG_UIO_SMX=m
|
||||||
CONFIG_UIO_PDRV=m
|
# CONFIG_UIO_PDRV is not set
|
||||||
CONFIG_UIO_PDRV_GENIRQ=m
|
# CONFIG_UIO_PDRV_GENIRQ is not set
|
||||||
CONFIG_UIO_AEC=m
|
CONFIG_UIO_AEC=m
|
||||||
CONFIG_UIO_SERCOS3=m
|
CONFIG_UIO_SERCOS3=m
|
||||||
CONFIG_UIO_PCI_GENERIC=m
|
CONFIG_UIO_PCI_GENERIC=m
|
||||||
|
@ -4000,20 +4033,16 @@ CONFIG_UIO_PCI_GENERIC=m
|
||||||
# LIRC
|
# LIRC
|
||||||
CONFIG_LIRC_STAGING=y
|
CONFIG_LIRC_STAGING=y
|
||||||
CONFIG_LIRC_BT829=m
|
CONFIG_LIRC_BT829=m
|
||||||
CONFIG_LIRC_ENE0100=m
|
|
||||||
CONFIG_LIRC_I2C=m
|
CONFIG_LIRC_I2C=m
|
||||||
CONFIG_LIRC_IGORPLUGUSB=m
|
CONFIG_LIRC_IGORPLUGUSB=m
|
||||||
CONFIG_LIRC_IMON=m
|
CONFIG_LIRC_IMON=m
|
||||||
CONFIG_LIRC_IT87=m
|
|
||||||
CONFIG_LIRC_ITE8709=m
|
|
||||||
CONFIG_LIRC_MCEUSB=m
|
|
||||||
CONFIG_LIRC_ZILOG=m
|
CONFIG_LIRC_ZILOG=m
|
||||||
CONFIG_LIRC_PARALLEL=m
|
CONFIG_LIRC_PARALLEL=m
|
||||||
CONFIG_LIRC_SERIAL=m
|
CONFIG_LIRC_SERIAL=m
|
||||||
CONFIG_LIRC_SERIAL_TRANSMITTER=y
|
CONFIG_LIRC_SERIAL_TRANSMITTER=y
|
||||||
CONFIG_LIRC_SASEM=m
|
CONFIG_LIRC_SASEM=m
|
||||||
CONFIG_LIRC_SIR=m
|
CONFIG_LIRC_SIR=m
|
||||||
CONFIG_LIRC_STREAMZAP=m
|
# CONFIG_LIRC_STREAMZAP is not set
|
||||||
CONFIG_LIRC_TTUSBIR=m
|
CONFIG_LIRC_TTUSBIR=m
|
||||||
|
|
||||||
# CONFIG_SAMPLES is not set
|
# CONFIG_SAMPLES is not set
|
||||||
|
@ -4175,7 +4204,7 @@ CONFIG_USB_ATMEL=m
|
||||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||||
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
|
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
|
||||||
# CONFIG_FUNCTION_GRAPH_TRACER is not set
|
# CONFIG_FUNCTION_GRAPH_TRACER is not set
|
||||||
CONFIG_BOOT_TRACER=y
|
# CONFIG_BOOT_TRACER is not set
|
||||||
CONFIG_EARLY_PRINTK_DBGP=y
|
CONFIG_EARLY_PRINTK_DBGP=y
|
||||||
|
|
||||||
CONFIG_SECURITYFS=y
|
CONFIG_SECURITYFS=y
|
||||||
|
@ -4253,7 +4282,7 @@ CONFIG_DEBUG_NX_TEST=m
|
||||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||||
CONFIG_DETECT_SOFTLOCKUP=y
|
CONFIG_DETECT_SOFTLOCKUP=y
|
||||||
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
|
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
|
||||||
CONFIG_DETECT_HUNG_TASK=y
|
# CONFIG_DETECT_HUNG_TASK is not set
|
||||||
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
|
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
|
||||||
CONFIG_ATOMIC64_SELFTEST=y
|
CONFIG_ATOMIC64_SELFTEST=y
|
||||||
|
|
||||||
|
@ -4269,7 +4298,7 @@ CONFIG_BLK_DEV_DRBD=m
|
||||||
# CONFIG_DEBUG_GPIO is not set
|
# CONFIG_DEBUG_GPIO is not set
|
||||||
# CONFIG_W1_MASTER_GPIO is not set
|
# CONFIG_W1_MASTER_GPIO is not set
|
||||||
# CONFIG_LEDS_GPIO is not set
|
# CONFIG_LEDS_GPIO is not set
|
||||||
# CONFIG_GPIO_SYSFS is not set
|
CONFIG_GPIO_SYSFS=y
|
||||||
# CONFIG_GPIO_MAX732X is not set
|
# CONFIG_GPIO_MAX732X is not set
|
||||||
# CONFIG_GPIO_PCA953X is not set
|
# CONFIG_GPIO_PCA953X is not set
|
||||||
# CONFIG_GPIO_PCF857X is not set
|
# CONFIG_GPIO_PCF857X is not set
|
||||||
|
|
|
@ -3,3 +3,6 @@ CONFIG_HIGHMEM64G=y
|
||||||
|
|
||||||
CONFIG_XEN_DEV_EVTCHN=m
|
CONFIG_XEN_DEV_EVTCHN=m
|
||||||
CONFIG_XEN_SYS_HYPERVISOR=y
|
CONFIG_XEN_SYS_HYPERVISOR=y
|
||||||
|
|
||||||
|
# I2O only works on non-PAE 32-bit x86
|
||||||
|
# CONFIG_I2O is not set
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file is intentionally left empty in the stock kernel. Its a nicety
|
||||||
|
# added for those wanting to do custom rebuilds with altered config opts.
|
|
@ -2,90 +2,92 @@ CONFIG_SND_VERBOSE_PRINTK=y
|
||||||
CONFIG_SND_DEBUG=y
|
CONFIG_SND_DEBUG=y
|
||||||
CONFIG_SND_PCM_XRUN_DEBUG=y
|
CONFIG_SND_PCM_XRUN_DEBUG=y
|
||||||
|
|
||||||
CONFIG_DEBUG_MUTEXES=y
|
# CONFIG_DEBUG_MUTEXES is not set
|
||||||
CONFIG_DEBUG_RT_MUTEXES=y
|
# CONFIG_DEBUG_RT_MUTEXES is not set
|
||||||
CONFIG_DEBUG_LOCK_ALLOC=y
|
# CONFIG_DEBUG_LOCK_ALLOC is not set
|
||||||
CONFIG_PROVE_LOCKING=y
|
# CONFIG_PROVE_LOCKING is not set
|
||||||
CONFIG_DEBUG_VM=y
|
# CONFIG_DEBUG_VM is not set
|
||||||
CONFIG_DEBUG_SPINLOCK=y
|
# CONFIG_DEBUG_SPINLOCK is not set
|
||||||
CONFIG_PROVE_RCU=y
|
# CONFIG_PROVE_RCU is not set
|
||||||
# CONFIG_PROVE_RCU_REPEATEDLY is not set
|
# CONFIG_PROVE_RCU_REPEATEDLY is not set
|
||||||
CONFIG_DEBUG_PER_CPU_MAPS=y
|
# CONFIG_DEBUG_PER_CPU_MAPS is not set
|
||||||
CONFIG_CPUMASK_OFFSTACK=y
|
CONFIG_CPUMASK_OFFSTACK=y
|
||||||
|
|
||||||
CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
|
# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
|
||||||
|
|
||||||
CONFIG_FAULT_INJECTION=y
|
# CONFIG_FAULT_INJECTION is not set
|
||||||
CONFIG_FAILSLAB=y
|
# CONFIG_FAILSLAB is not set
|
||||||
CONFIG_FAIL_PAGE_ALLOC=y
|
# CONFIG_FAIL_PAGE_ALLOC is not set
|
||||||
CONFIG_FAIL_MAKE_REQUEST=y
|
# CONFIG_FAIL_MAKE_REQUEST is not set
|
||||||
CONFIG_FAULT_INJECTION_DEBUG_FS=y
|
# CONFIG_FAULT_INJECTION_DEBUG_FS is not set
|
||||||
CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
|
# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set
|
||||||
CONFIG_FAIL_IO_TIMEOUT=y
|
# CONFIG_FAIL_IO_TIMEOUT is not set
|
||||||
|
|
||||||
CONFIG_SLUB_DEBUG_ON=y
|
# CONFIG_SLUB_DEBUG_ON is not set
|
||||||
|
|
||||||
CONFIG_LOCK_STAT=y
|
# CONFIG_LOCK_STAT is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_STACK_USAGE=y
|
# CONFIG_DEBUG_STACK_USAGE is not set
|
||||||
|
|
||||||
CONFIG_ACPI_DEBUG=y
|
# CONFIG_ACPI_DEBUG is not set
|
||||||
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
|
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_SG=y
|
# CONFIG_DEBUG_SG is not set
|
||||||
|
|
||||||
# CONFIG_DEBUG_PAGEALLOC is not set
|
# CONFIG_DEBUG_PAGEALLOC is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_WRITECOUNT=y
|
# CONFIG_DEBUG_WRITECOUNT is not set
|
||||||
CONFIG_DEBUG_OBJECTS=y
|
# CONFIG_DEBUG_OBJECTS is not set
|
||||||
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
|
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
|
||||||
CONFIG_DEBUG_OBJECTS_FREE=y
|
# CONFIG_DEBUG_OBJECTS_FREE is not set
|
||||||
CONFIG_DEBUG_OBJECTS_TIMERS=y
|
# CONFIG_DEBUG_OBJECTS_TIMERS is not set
|
||||||
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
|
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
|
||||||
|
|
||||||
CONFIG_X86_PTDUMP=y
|
# CONFIG_X86_PTDUMP is not set
|
||||||
|
|
||||||
CONFIG_CAN_DEBUG_DEVICES=y
|
# CONFIG_CAN_DEBUG_DEVICES is not set
|
||||||
|
|
||||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||||
|
|
||||||
CONFIG_SYSCTL_SYSCALL_CHECK=y
|
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_NOTIFIERS=y
|
# CONFIG_DEBUG_NOTIFIERS is not set
|
||||||
|
|
||||||
CONFIG_DMA_API_DEBUG=y
|
# CONFIG_DMA_API_DEBUG is not set
|
||||||
|
|
||||||
CONFIG_MMIOTRACE=y
|
# CONFIG_MMIOTRACE is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_CREDENTIALS=y
|
# CONFIG_DEBUG_CREDENTIALS is not set
|
||||||
|
|
||||||
# off in both production debug and nodebug builds,
|
# off in both production debug and nodebug builds,
|
||||||
# on in rawhide nodebug builds
|
# on in rawhide nodebug builds
|
||||||
CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
|
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
|
||||||
|
|
||||||
CONFIG_EXT4_DEBUG=y
|
# CONFIG_EXT4_DEBUG is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_PERF_USE_VMALLOC=y
|
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
|
||||||
|
|
||||||
CONFIG_JBD2_DEBUG=y
|
# CONFIG_JBD2_DEBUG is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_CFQ_IOSCHED=y
|
# CONFIG_DEBUG_CFQ_IOSCHED is not set
|
||||||
|
|
||||||
CONFIG_DRBD_FAULT_INJECTION=y
|
# CONFIG_DRBD_FAULT_INJECTION is not set
|
||||||
|
|
||||||
CONFIG_ATH_DEBUG=y
|
# CONFIG_ATH_DEBUG is not set
|
||||||
CONFIG_IWLWIFI_DEVICE_TRACING=y
|
# CONFIG_IWLWIFI_DEVICE_TRACING is not set
|
||||||
|
|
||||||
CONFIG_DEBUG_OBJECTS_WORK=y
|
# CONFIG_DEBUG_OBJECTS_WORK is not set
|
||||||
CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
|
# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
|
||||||
|
|
||||||
CONFIG_DMADEVICES_DEBUG=y
|
# CONFIG_DMADEVICES_DEBUG is not set
|
||||||
CONFIG_DMADEVICES_VDEBUG=y
|
# CONFIG_DMADEVICES_VDEBUG is not set
|
||||||
|
|
||||||
CONFIG_PM_ADVANCED_DEBUG=y
|
CONFIG_PM_ADVANCED_DEBUG=y
|
||||||
|
|
||||||
CONFIG_CEPH_FS_PRETTYDEBUG=y
|
# CONFIG_CEPH_FS_PRETTYDEBUG is not set
|
||||||
CONFIG_QUOTA_DEBUG=y
|
# CONFIG_QUOTA_DEBUG is not set
|
||||||
|
|
||||||
|
# CONFIG_PCI_DEFAULT_USE_CRS is not set
|
||||||
|
|
||||||
CONFIG_KGDB_KDB=y
|
CONFIG_KGDB_KDB=y
|
||||||
CONFIG_KDB_KEYBOARD=y
|
CONFIG_KDB_KEYBOARD=y
|
||||||
|
|
|
@ -200,4 +200,9 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m
|
||||||
CONFIG_GRETH=m
|
CONFIG_GRETH=m
|
||||||
CONFIG_FB_XVR1000=y
|
CONFIG_FB_XVR1000=y
|
||||||
|
|
||||||
CONFIG_CRYPTO_DEV_NIAGARA2=y
|
CONFIG_CRYPTO_DEV_NIAGARA2=m
|
||||||
|
|
||||||
|
# Bellow is changes made to get the kernel building on sparc again, they need to have upstream fixes
|
||||||
|
# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
|
||||||
|
# CONFIG_ATA_OVER_ETH is not set
|
||||||
|
# CONFIG_INFINIBAND is not set
|
||||||
|
|
|
@ -37,7 +37,7 @@ CONFIG_M686=y
|
||||||
# CONFIG_MCYRIXIII is not set
|
# CONFIG_MCYRIXIII is not set
|
||||||
# CONFIG_MVIAC3_2 is not set
|
# CONFIG_MVIAC3_2 is not set
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
CONFIG_NR_CPUS=32
|
CONFIG_NR_CPUS=64
|
||||||
CONFIG_X86_GENERIC=y
|
CONFIG_X86_GENERIC=y
|
||||||
# CONFIG_X86_PPRO_FENCE is not set
|
# CONFIG_X86_PPRO_FENCE is not set
|
||||||
CONFIG_HPET=y
|
CONFIG_HPET=y
|
||||||
|
@ -100,6 +100,16 @@ CONFIG_SECCOMP=y
|
||||||
|
|
||||||
CONFIG_CAPI_EICON=y
|
CONFIG_CAPI_EICON=y
|
||||||
|
|
||||||
|
# I2O enabled only for 32-bit x86, disabled for PAE kernel
|
||||||
|
CONFIG_I2O=m
|
||||||
|
CONFIG_I2O_BLOCK=m
|
||||||
|
CONFIG_I2O_SCSI=m
|
||||||
|
CONFIG_I2O_PROC=m
|
||||||
|
CONFIG_I2O_CONFIG=y
|
||||||
|
CONFIG_I2O_EXT_ADAPTEC=y
|
||||||
|
CONFIG_I2O_CONFIG_OLD_IOCTL=y
|
||||||
|
CONFIG_I2O_BUS=m
|
||||||
|
|
||||||
#
|
#
|
||||||
# APM (Advanced Power Management) BIOS Support
|
# APM (Advanced Power Management) BIOS Support
|
||||||
#
|
#
|
||||||
|
@ -479,6 +489,8 @@ CONFIG_TOSHIBA_BT_RFKILL=m
|
||||||
CONFIG_VGA_SWITCHEROO=y
|
CONFIG_VGA_SWITCHEROO=y
|
||||||
CONFIG_LPC_SCH=m
|
CONFIG_LPC_SCH=m
|
||||||
|
|
||||||
CONFIG_INTEL_IDLE=m
|
CONFIG_INTEL_IDLE=y
|
||||||
|
|
||||||
CONFIG_PCI_CNB20LE_QUIRK=y
|
CONFIG_PCI_CNB20LE_QUIRK=y
|
||||||
|
|
||||||
|
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||||
|
|
|
@ -15,7 +15,7 @@ CONFIG_NUMA=y
|
||||||
CONFIG_K8_NUMA=y
|
CONFIG_K8_NUMA=y
|
||||||
CONFIG_X86_64_ACPI_NUMA=y
|
CONFIG_X86_64_ACPI_NUMA=y
|
||||||
# CONFIG_NUMA_EMU is not set
|
# CONFIG_NUMA_EMU is not set
|
||||||
CONFIG_NR_CPUS=512
|
CONFIG_NR_CPUS=256
|
||||||
CONFIG_X86_POWERNOW_K8=m
|
CONFIG_X86_POWERNOW_K8=m
|
||||||
CONFIG_X86_P4_CLOCKMOD=m
|
CONFIG_X86_P4_CLOCKMOD=m
|
||||||
CONFIG_IA32_EMULATION=y
|
CONFIG_IA32_EMULATION=y
|
||||||
|
@ -403,7 +403,11 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
|
||||||
CONFIG_VGA_SWITCHEROO=y
|
CONFIG_VGA_SWITCHEROO=y
|
||||||
CONFIG_LPC_SCH=m
|
CONFIG_LPC_SCH=m
|
||||||
|
|
||||||
CONFIG_INTEL_IDLE=m
|
CONFIG_INTEL_IDLE=y
|
||||||
CONFIG_I7300_IDLE=m
|
CONFIG_I7300_IDLE=m
|
||||||
|
|
||||||
CONFIG_PCI_CNB20LE_QUIRK=y
|
CONFIG_PCI_CNB20LE_QUIRK=y
|
||||||
|
|
||||||
|
CONFIG_HP_ILO=m
|
||||||
|
|
||||||
|
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
From: Greg KH <gregkh@suse.de>
|
||||||
|
Date: Thu, 5 Aug 2010 20:53:35 +0000 (-0700)
|
||||||
|
Subject: cgroupfs: create /sys/fs/cgroup to mount cgroupfs on
|
||||||
|
X-Git-Tag: v2.6.36-rc1~521^2~7
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=676db4af043014e852f67ba0349dae0071bd11f3
|
||||||
|
|
||||||
|
cgroupfs: create /sys/fs/cgroup to mount cgroupfs on
|
||||||
|
|
||||||
|
We really shouldn't be asking userspace to create new root filesystems.
|
||||||
|
So follow along with all of the other in-kernel filesystems, and provide
|
||||||
|
a mount point in sysfs.
|
||||||
|
|
||||||
|
For cgroupfs, this should be in /sys/fs/cgroup/ This change provides
|
||||||
|
that mount point when the cgroup filesystem is registered in the kernel.
|
||||||
|
|
||||||
|
Acked-by: Paul Menage <menage@google.com>
|
||||||
|
Acked-by: Dhaval Giani <dhaval.giani@gmail.com>
|
||||||
|
Cc: Li Zefan <lizf@cn.fujitsu.com>
|
||||||
|
Cc: Lennart Poettering <lennart@poettering.net>
|
||||||
|
Cc: Kay Sievers <kay.sievers@vrfy.org>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
|
||||||
|
index a8ce099..d83cab0 100644
|
||||||
|
--- a/kernel/cgroup.c
|
||||||
|
+++ b/kernel/cgroup.c
|
||||||
|
@@ -1623,6 +1623,8 @@ static struct file_system_type cgroup_fs_type = {
|
||||||
|
.kill_sb = cgroup_kill_sb,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static struct kobject *cgroup_kobj;
|
||||||
|
+
|
||||||
|
static inline struct cgroup *__d_cgrp(struct dentry *dentry)
|
||||||
|
{
|
||||||
|
return dentry->d_fsdata;
|
||||||
|
@@ -3894,9 +3896,18 @@ int __init cgroup_init(void)
|
||||||
|
hhead = css_set_hash(init_css_set.subsys);
|
||||||
|
hlist_add_head(&init_css_set.hlist, hhead);
|
||||||
|
BUG_ON(!init_root_id(&rootnode));
|
||||||
|
+
|
||||||
|
+ cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
|
||||||
|
+ if (!cgroup_kobj) {
|
||||||
|
+ err = -ENOMEM;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
err = register_filesystem(&cgroup_fs_type);
|
||||||
|
- if (err < 0)
|
||||||
|
+ if (err < 0) {
|
||||||
|
+ kobject_put(cgroup_kobj);
|
||||||
|
goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
From 44c943562c2e204cddf46db131c53c326b47bd47 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "David S. Miller" <davem@davemloft.net>
|
||||||
|
Date: Fri, 16 Sep 2011 17:10:29 -0400
|
||||||
|
Subject: [PATCH 1/2] crypto: Move md5_transform to lib/md5.c
|
||||||
|
|
||||||
|
We are going to use this for TCP/IP sequence number and fragment ID
|
||||||
|
generation.
|
||||||
|
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
|
Backported to 2.6.25.14 by Josh Boyer <jwboyer@redhat.com>
|
||||||
|
---
|
||||||
|
crypto/md5.c | 92 +------------------------------------------
|
||||||
|
include/linux/cryptohash.h | 5 ++
|
||||||
|
lib/Makefile | 2 +-
|
||||||
|
lib/md5.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
4 files changed, 102 insertions(+), 92 deletions(-)
|
||||||
|
create mode 100644 lib/md5.c
|
||||||
|
|
||||||
|
diff --git a/crypto/md5.c b/crypto/md5.c
|
||||||
|
index 30efc7d..7febeaa 100644
|
||||||
|
--- a/crypto/md5.c
|
||||||
|
+++ b/crypto/md5.c
|
||||||
|
@@ -21,99 +21,9 @@
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
+#include <linux/cryptohash.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||||
|
-#define F2(x, y, z) F1(z, x, y)
|
||||||
|
-#define F3(x, y, z) (x ^ y ^ z)
|
||||||
|
-#define F4(x, y, z) (y ^ (x | ~z))
|
||||||
|
-
|
||||||
|
-#define MD5STEP(f, w, x, y, z, in, s) \
|
||||||
|
- (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||||
|
-
|
||||||
|
-static void md5_transform(u32 *hash, u32 const *in)
|
||||||
|
-{
|
||||||
|
- u32 a, b, c, d;
|
||||||
|
-
|
||||||
|
- a = hash[0];
|
||||||
|
- b = hash[1];
|
||||||
|
- c = hash[2];
|
||||||
|
- d = hash[3];
|
||||||
|
-
|
||||||
|
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||||
|
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||||
|
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||||
|
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||||
|
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||||
|
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||||
|
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||||
|
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||||
|
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||||
|
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||||
|
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||||
|
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||||
|
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||||
|
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||||
|
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||||
|
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||||
|
-
|
||||||
|
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||||
|
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||||
|
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||||
|
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||||
|
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||||
|
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||||
|
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||||
|
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||||
|
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||||
|
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||||
|
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||||
|
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||||
|
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||||
|
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||||
|
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||||
|
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||||
|
-
|
||||||
|
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||||
|
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||||
|
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||||
|
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||||
|
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||||
|
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||||
|
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||||
|
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||||
|
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||||
|
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||||
|
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||||
|
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||||
|
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||||
|
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||||
|
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||||
|
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||||
|
-
|
||||||
|
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||||
|
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||||
|
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||||
|
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||||
|
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||||
|
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||||
|
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||||
|
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||||
|
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||||
|
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||||
|
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||||
|
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||||
|
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||||
|
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||||
|
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||||
|
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||||
|
-
|
||||||
|
- hash[0] += a;
|
||||||
|
- hash[1] += b;
|
||||||
|
- hash[2] += c;
|
||||||
|
- hash[3] += d;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* XXX: this stuff can be optimized */
|
||||||
|
static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
|
||||||
|
{
|
||||||
|
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
|
||||||
|
index ec78a4b..d2984fb 100644
|
||||||
|
--- a/include/linux/cryptohash.h
|
||||||
|
+++ b/include/linux/cryptohash.h
|
||||||
|
@@ -8,6 +8,11 @@
|
||||||
|
void sha_init(__u32 *buf);
|
||||||
|
void sha_transform(__u32 *digest, const char *data, __u32 *W);
|
||||||
|
|
||||||
|
+#define MD5_DIGEST_WORDS 4
|
||||||
|
+#define MD5_MESSAGE_BYTES 64
|
||||||
|
+
|
||||||
|
+void md5_transform(__u32 *hash, __u32 const *in);
|
||||||
|
+
|
||||||
|
__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/lib/Makefile b/lib/Makefile
|
||||||
|
index 0bfabba..d07eef3 100644
|
||||||
|
--- a/lib/Makefile
|
||||||
|
+++ b/lib/Makefile
|
||||||
|
@@ -10,7 +10,7 @@ endif
|
||||||
|
lib-y := ctype.o string.o vsprintf.o cmdline.o \
|
||||||
|
rbtree.o radix-tree.o dump_stack.o \
|
||||||
|
idr.o int_sqrt.o extable.o prio_tree.o \
|
||||||
|
- sha1.o irq_regs.o reciprocal_div.o argv_split.o \
|
||||||
|
+ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
|
||||||
|
proportions.o prio_heap.o ratelimit.o show_mem.o \
|
||||||
|
is_single_threaded.o plist.o decompress.o flex_array.o
|
||||||
|
|
||||||
|
diff --git a/lib/md5.c b/lib/md5.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c777180
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/md5.c
|
||||||
|
@@ -0,0 +1,95 @@
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/cryptohash.h>
|
||||||
|
+
|
||||||
|
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||||
|
+#define F2(x, y, z) F1(z, x, y)
|
||||||
|
+#define F3(x, y, z) (x ^ y ^ z)
|
||||||
|
+#define F4(x, y, z) (y ^ (x | ~z))
|
||||||
|
+
|
||||||
|
+#define MD5STEP(f, w, x, y, z, in, s) \
|
||||||
|
+ (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||||
|
+
|
||||||
|
+void md5_transform(__u32 *hash, __u32 const *in)
|
||||||
|
+{
|
||||||
|
+ u32 a, b, c, d;
|
||||||
|
+
|
||||||
|
+ a = hash[0];
|
||||||
|
+ b = hash[1];
|
||||||
|
+ c = hash[2];
|
||||||
|
+ d = hash[3];
|
||||||
|
+
|
||||||
|
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||||
|
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||||
|
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||||
|
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||||
|
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||||
|
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||||
|
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||||
|
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||||
|
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||||
|
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||||
|
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||||
|
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||||
|
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||||
|
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||||
|
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||||
|
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||||
|
+
|
||||||
|
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||||
|
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||||
|
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||||
|
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||||
|
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||||
|
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||||
|
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||||
|
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||||
|
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||||
|
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||||
|
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||||
|
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||||
|
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||||
|
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||||
|
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||||
|
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||||
|
+
|
||||||
|
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||||
|
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||||
|
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||||
|
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||||
|
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||||
|
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||||
|
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||||
|
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||||
|
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||||
|
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||||
|
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||||
|
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||||
|
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||||
|
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||||
|
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||||
|
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||||
|
+
|
||||||
|
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||||
|
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||||
|
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||||
|
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||||
|
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||||
|
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||||
|
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||||
|
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||||
|
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||||
|
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||||
|
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||||
|
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||||
|
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||||
|
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||||
|
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||||
|
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||||
|
+
|
||||||
|
+ hash[0] += a;
|
||||||
|
+ hash[1] += b;
|
||||||
|
+ hash[2] += c;
|
||||||
|
+ hash[3] += d;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(md5_transform);
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
From 3e65dd9e26cf5ba791f44c5e15e29d07b84824aa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nick Bowler <nbowler@elliptictech.com>
|
||||||
|
Date: Thu, 20 Oct 2011 14:16:55 +0200
|
||||||
|
Subject: [PATCH] crypto: ghash - Avoid null pointer dereference if no key is
|
||||||
|
set
|
||||||
|
|
||||||
|
commit 7ed47b7d142ec99ad6880bbbec51e9f12b3af74c upstream.
|
||||||
|
|
||||||
|
The ghash_update function passes a pointer to gf128mul_4k_lle which will
|
||||||
|
be NULL if ghash_setkey is not called or if the most recent call to
|
||||||
|
ghash_setkey failed to allocate memory. This causes an oops. Fix this
|
||||||
|
up by returning an error code in the null case.
|
||||||
|
|
||||||
|
This is trivially triggered from unprivileged userspace through the
|
||||||
|
AF_ALG interface by simply writing to the socket without setting a key.
|
||||||
|
|
||||||
|
The ghash_final function has a similar issue, but triggering it requires
|
||||||
|
a memory allocation failure in ghash_setkey _after_ at least one
|
||||||
|
successful call to ghash_update.
|
||||||
|
|
||||||
|
BUG: unable to handle kernel NULL pointer dereference at 00000670
|
||||||
|
IP: [<d88c92d4>] gf128mul_4k_lle+0x23/0x60 [gf128mul]
|
||||||
|
*pde = 00000000
|
||||||
|
Oops: 0000 [#1] PREEMPT SMP
|
||||||
|
Modules linked in: ghash_generic gf128mul algif_hash af_alg nfs lockd nfs_acl sunrpc bridge ipv6 stp llc
|
||||||
|
|
||||||
|
Pid: 1502, comm: hashatron Tainted: G W 3.1.0-rc9-00085-ge9308cf #32 Bochs Bochs
|
||||||
|
EIP: 0060:[<d88c92d4>] EFLAGS: 00000202 CPU: 0
|
||||||
|
EIP is at gf128mul_4k_lle+0x23/0x60 [gf128mul]
|
||||||
|
EAX: d69db1f0 EBX: d6b8ddac ECX: 00000004 EDX: 00000000
|
||||||
|
ESI: 00000670 EDI: d6b8ddac EBP: d6b8ddc8 ESP: d6b8dda4
|
||||||
|
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
|
||||||
|
Process hashatron (pid: 1502, ti=d6b8c000 task=d6810000 task.ti=d6b8c000)
|
||||||
|
Stack:
|
||||||
|
00000000 d69db1f0 00000163 00000000 d6b8ddc8 c101a520 d69db1f0 d52aa000
|
||||||
|
00000ff0 d6b8dde8 d88d310f d6b8a3f8 d52aa000 00001000 d88d502c d6b8ddfc
|
||||||
|
00001000 d6b8ddf4 c11676ed d69db1e8 d6b8de24 c11679ad d52aa000 00000000
|
||||||
|
Call Trace:
|
||||||
|
[<c101a520>] ? kmap_atomic_prot+0x37/0xa6
|
||||||
|
[<d88d310f>] ghash_update+0x85/0xbe [ghash_generic]
|
||||||
|
[<c11676ed>] crypto_shash_update+0x18/0x1b
|
||||||
|
[<c11679ad>] shash_ahash_update+0x22/0x36
|
||||||
|
[<c11679cc>] shash_async_update+0xb/0xd
|
||||||
|
[<d88ce0ba>] hash_sendpage+0xba/0xf2 [algif_hash]
|
||||||
|
[<c121b24c>] kernel_sendpage+0x39/0x4e
|
||||||
|
[<d88ce000>] ? 0xd88cdfff
|
||||||
|
[<c121b298>] sock_sendpage+0x37/0x3e
|
||||||
|
[<c121b261>] ? kernel_sendpage+0x4e/0x4e
|
||||||
|
[<c10b4dbc>] pipe_to_sendpage+0x56/0x61
|
||||||
|
[<c10b4e1f>] splice_from_pipe_feed+0x58/0xcd
|
||||||
|
[<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
|
||||||
|
[<c10b51f5>] __splice_from_pipe+0x36/0x55
|
||||||
|
[<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
|
||||||
|
[<c10b6383>] splice_from_pipe+0x51/0x64
|
||||||
|
[<c10b63c2>] ? default_file_splice_write+0x2c/0x2c
|
||||||
|
[<c10b63d5>] generic_splice_sendpage+0x13/0x15
|
||||||
|
[<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
|
||||||
|
[<c10b527f>] do_splice_from+0x5d/0x67
|
||||||
|
[<c10b6865>] sys_splice+0x2bf/0x363
|
||||||
|
[<c129373b>] ? sysenter_exit+0xf/0x16
|
||||||
|
[<c104dc1e>] ? trace_hardirqs_on_caller+0x10e/0x13f
|
||||||
|
[<c129370c>] sysenter_do_call+0x12/0x32
|
||||||
|
Code: 83 c4 0c 5b 5e 5f c9 c3 55 b9 04 00 00 00 89 e5 57 8d 7d e4 56 53 8d 5d e4 83 ec 18 89 45 e0 89 55 dc 0f b6 70 0f c1 e6 04 01 d6 <f3> a5 be 0f 00 00 00 4e 89 d8 e8 48 ff ff ff 8b 45 e0 89 da 0f
|
||||||
|
EIP: [<d88c92d4>] gf128mul_4k_lle+0x23/0x60 [gf128mul] SS:ESP 0068:d6b8dda4
|
||||||
|
CR2: 0000000000000670
|
||||||
|
---[ end trace 4eaa2a86a8e2da24 ]---
|
||||||
|
note: hashatron[1502] exited with preempt_count 1
|
||||||
|
BUG: scheduling while atomic: hashatron/1502/0x10000002
|
||||||
|
INFO: lockdep is turned off.
|
||||||
|
[...]
|
||||||
|
|
||||||
|
Signed-off-by: Nick Bowler <nbowler@elliptictech.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
crypto/ghash-generic.c | 6 ++++++
|
||||||
|
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
|
||||||
|
index be44256..7835b8f 100644
|
||||||
|
--- a/crypto/ghash-generic.c
|
||||||
|
+++ b/crypto/ghash-generic.c
|
||||||
|
@@ -67,6 +67,9 @@ static int ghash_update(struct shash_desc *desc,
|
||||||
|
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
|
||||||
|
u8 *dst = dctx->buffer;
|
||||||
|
|
||||||
|
+ if (!ctx->gf128)
|
||||||
|
+ return -ENOKEY;
|
||||||
|
+
|
||||||
|
if (dctx->bytes) {
|
||||||
|
int n = min(srclen, dctx->bytes);
|
||||||
|
u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
|
||||||
|
@@ -119,6 +122,9 @@ static int ghash_final(struct shash_desc *desc, u8 *dst)
|
||||||
|
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
|
||||||
|
u8 *buf = dctx->buffer;
|
||||||
|
|
||||||
|
+ if (!ctx->gf128)
|
||||||
|
+ return -ENOKEY;
|
||||||
|
+
|
||||||
|
ghash_flush(ctx, dctx);
|
||||||
|
memcpy(dst, buf, GHASH_BLOCK_SIZE);
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.6.4
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
From 799c10559d60f159ab2232203f222f18fa3c4a5f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
Date: Fri, 15 Oct 2010 11:09:28 -0700
|
||||||
|
Subject: [PATCH] De-pessimize rds_page_copy_user
|
||||||
|
|
||||||
|
Don't try to "optimize" rds_page_copy_user() by using kmap_atomic() and
|
||||||
|
the unsafe atomic user mode accessor functions. It's actually slower
|
||||||
|
than the straightforward code on any reasonable modern CPU.
|
||||||
|
|
||||||
|
Back when the code was written (although probably not by the time it was
|
||||||
|
actually merged, though), 32-bit x86 may have been the dominant
|
||||||
|
architecture. And there kmap_atomic() can be a lot faster than kmap()
|
||||||
|
(unless you have very good locality, in which case the virtual address
|
||||||
|
caching by kmap() can overcome all the downsides).
|
||||||
|
|
||||||
|
But these days, x86-64 may not be more populous, but it's getting there
|
||||||
|
(and if you care about performance, it's definitely already there -
|
||||||
|
you'd have upgraded your CPU's already in the last few years). And on
|
||||||
|
x86-64, the non-kmap_atomic() version is faster, simply because the code
|
||||||
|
is simpler and doesn't have the "re-try page fault" case.
|
||||||
|
|
||||||
|
People with old hardware are not likely to care about RDS anyway, and
|
||||||
|
the optimization for the 32-bit case is simply buggy, since it doesn't
|
||||||
|
verify the user addresses properly.
|
||||||
|
|
||||||
|
Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
|
||||||
|
Acked-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
---
|
||||||
|
net/rds/page.c | 27 +++++++--------------------
|
||||||
|
1 files changed, 7 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/net/rds/page.c b/net/rds/page.c
|
||||||
|
index 595a952..1dfbfea 100644
|
||||||
|
--- a/net/rds/page.c
|
||||||
|
+++ b/net/rds/page.c
|
||||||
|
@@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset,
|
||||||
|
unsigned long ret;
|
||||||
|
void *addr;
|
||||||
|
|
||||||
|
- if (to_user)
|
||||||
|
+ addr = kmap(page);
|
||||||
|
+ if (to_user) {
|
||||||
|
rds_stats_add(s_copy_to_user, bytes);
|
||||||
|
- else
|
||||||
|
+ ret = copy_to_user(ptr, addr + offset, bytes);
|
||||||
|
+ } else {
|
||||||
|
rds_stats_add(s_copy_from_user, bytes);
|
||||||
|
-
|
||||||
|
- addr = kmap_atomic(page, KM_USER0);
|
||||||
|
- if (to_user)
|
||||||
|
- ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
|
||||||
|
- else
|
||||||
|
- ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
|
||||||
|
- kunmap_atomic(addr, KM_USER0);
|
||||||
|
-
|
||||||
|
- if (ret) {
|
||||||
|
- addr = kmap(page);
|
||||||
|
- if (to_user)
|
||||||
|
- ret = copy_to_user(ptr, addr + offset, bytes);
|
||||||
|
- else
|
||||||
|
- ret = copy_from_user(addr + offset, ptr, bytes);
|
||||||
|
- kunmap(page);
|
||||||
|
- if (ret)
|
||||||
|
- return -EFAULT;
|
||||||
|
+ ret = copy_from_user(addr + offset, ptr, bytes);
|
||||||
|
}
|
||||||
|
+ kunmap(page);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return ret ? -EFAULT : 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rds_page_copy_user);
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
|
||||||
|
index 11482b6..b05ff9c 100644
|
||||||
|
--- a/drivers/usb/host/xhci-pci.c
|
||||||
|
+++ b/drivers/usb/host/xhci-pci.c
|
||||||
|
@@ -179,9 +179,25 @@ static struct pci_driver xhci_pci_driver = {
|
||||||
|
.shutdown = usb_hcd_pci_shutdown,
|
||||||
|
};
|
||||||
|
|
||||||
|
+
|
||||||
|
+static int enable;
|
||||||
|
+module_param(enable, int, S_IRUGO);
|
||||||
|
+MODULE_PARM_DESC(enable, "Enable XHCI host controller");
|
||||||
|
+
|
||||||
|
int xhci_register_pci(void)
|
||||||
|
{
|
||||||
|
- return pci_register_driver(&xhci_pci_driver);
|
||||||
|
+ /* xhci will prevent suspend/resume if it's loaded.
|
||||||
|
+ * force user to pass xhci.enable=1 to the kernel in order
|
||||||
|
+ * to get usb3.0 support for the time being.
|
||||||
|
+ *
|
||||||
|
+ * ugly yes, but there's few enough users out there using
|
||||||
|
+ * usb3.0, and a lot who just have the hardware breaking
|
||||||
|
+ * their suspend.
|
||||||
|
+ */
|
||||||
|
+ if (enable)
|
||||||
|
+ return pci_register_driver(&xhci_pci_driver);
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xhci_unregister_pci(void)
|
|
@ -0,0 +1,205 @@
|
||||||
|
From ce5fa9851090cc5f3de4139bf0f343eb78d1c568 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Mon, 11 Oct 2010 15:49:28 -0400
|
||||||
|
Subject: [PATCH] device-mapper: Allow setting of UUID via rename if not already set
|
||||||
|
|
||||||
|
This makes it possible to use DM_DEV_RENAME to add a uuid to a device so
|
||||||
|
long as one has not been previously set either with DM_DEV_CREATE or
|
||||||
|
with DM_DEV_RENAME. This is needed because sometimes in it's necessary
|
||||||
|
to create the device before the uuid is known, and in such cases the
|
||||||
|
uuid must be filled in after the creation.
|
||||||
|
|
||||||
|
Also bump the minor number to 19.
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/md/dm-ioctl.c | 95 ++++++++++++++++++++++++++++++++--------------
|
||||||
|
include/linux/dm-ioctl.h | 11 ++++-
|
||||||
|
2 files changed, 74 insertions(+), 32 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
|
||||||
|
index bb6bdc8..d102269 100644
|
||||||
|
--- a/drivers/md/dm-ioctl.c
|
||||||
|
+++ b/drivers/md/dm-ioctl.c
|
||||||
|
@@ -298,15 +298,15 @@ retry:
|
||||||
|
static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
|
||||||
|
const char *new)
|
||||||
|
{
|
||||||
|
- char *new_name, *old_name;
|
||||||
|
+ char *new_data, *old_data;
|
||||||
|
struct hash_cell *hc;
|
||||||
|
struct dm_table *table;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* duplicate new.
|
||||||
|
*/
|
||||||
|
- new_name = kstrdup(new, GFP_KERNEL);
|
||||||
|
- if (!new_name)
|
||||||
|
+ new_data = kstrdup(new, GFP_KERNEL);
|
||||||
|
+ if (!new_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
down_write(&_hash_lock);
|
||||||
|
@@ -314,13 +314,18 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
|
||||||
|
/*
|
||||||
|
* Is new free ?
|
||||||
|
*/
|
||||||
|
- hc = __get_name_cell(new);
|
||||||
|
+ if (*flags & DM_NEW_UUID_FLAG)
|
||||||
|
+ hc = __get_uuid_cell(new);
|
||||||
|
+ else
|
||||||
|
+ hc = __get_name_cell(new);
|
||||||
|
if (hc) {
|
||||||
|
- DMWARN("asked to rename to an already existing name %s -> %s",
|
||||||
|
+ DMWARN("Unable to change %s on device, %s to one that "
|
||||||
|
+ "already exists: %s",
|
||||||
|
+ (*flags & DM_NEW_UUID_FLAG) ? "uuid" : "name",
|
||||||
|
old, new);
|
||||||
|
dm_put(hc->md);
|
||||||
|
up_write(&_hash_lock);
|
||||||
|
- kfree(new_name);
|
||||||
|
+ kfree(new_data);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -329,22 +334,46 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
|
||||||
|
*/
|
||||||
|
hc = __get_name_cell(old);
|
||||||
|
if (!hc) {
|
||||||
|
- DMWARN("asked to rename a non existent device %s -> %s",
|
||||||
|
+ DMWARN("Unable to rename non-existent device, %s to %s",
|
||||||
|
old, new);
|
||||||
|
up_write(&_hash_lock);
|
||||||
|
- kfree(new_name);
|
||||||
|
+ kfree(new_data);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * rename and move the name cell.
|
||||||
|
- */
|
||||||
|
- list_del(&hc->name_list);
|
||||||
|
- old_name = hc->name;
|
||||||
|
- mutex_lock(&dm_hash_cells_mutex);
|
||||||
|
- hc->name = new_name;
|
||||||
|
- mutex_unlock(&dm_hash_cells_mutex);
|
||||||
|
- list_add(&hc->name_list, _name_buckets + hash_str(new_name));
|
||||||
|
+ if (*flags & DM_NEW_UUID_FLAG) {
|
||||||
|
+ /*
|
||||||
|
+ * Does this device already have a uuid?
|
||||||
|
+ */
|
||||||
|
+ if (hc->uuid) {
|
||||||
|
+ DMWARN("Unable to change uuid of device, %s because "
|
||||||
|
+ "uuid is already set to %s",
|
||||||
|
+ old, hc->uuid);
|
||||||
|
+ dm_put(hc->md);
|
||||||
|
+ up_write(&_hash_lock);
|
||||||
|
+ kfree(new_data);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ /*
|
||||||
|
+ * change uuid and move the uuid cell.
|
||||||
|
+ */
|
||||||
|
+ list_del(&hc->uuid_list);
|
||||||
|
+ old_data = hc->uuid;
|
||||||
|
+ mutex_lock(&dm_hash_cells_mutex);
|
||||||
|
+ hc->uuid = new_data;
|
||||||
|
+ mutex_unlock(&dm_hash_cells_mutex);
|
||||||
|
+ list_add(&hc->uuid_list, _uuid_buckets + hash_str(new_data));
|
||||||
|
+ } else {
|
||||||
|
+ /*
|
||||||
|
+ * rename and move the name cell.
|
||||||
|
+ */
|
||||||
|
+ list_del(&hc->name_list);
|
||||||
|
+ old_data = hc->name;
|
||||||
|
+ mutex_lock(&dm_hash_cells_mutex);
|
||||||
|
+ hc->name = new_data;
|
||||||
|
+ mutex_unlock(&dm_hash_cells_mutex);
|
||||||
|
+ list_add(&hc->name_list, _name_buckets + hash_str(new_data));
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wake up any dm event waiters.
|
||||||
|
@@ -360,7 +388,7 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
|
||||||
|
|
||||||
|
dm_put(hc->md);
|
||||||
|
up_write(&_hash_lock);
|
||||||
|
- kfree(old_name);
|
||||||
|
+ kfree(old_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -773,23 +801,32 @@ static int invalid_str(char *str, void *end)
|
||||||
|
static int dev_rename(struct dm_ioctl *param, size_t param_size)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
- char *new_name = (char *) param + param->data_start;
|
||||||
|
+ char *new_data = (char *) param + param->data_start;
|
||||||
|
|
||||||
|
- if (new_name < param->data ||
|
||||||
|
- invalid_str(new_name, (void *) param + param_size) ||
|
||||||
|
- strlen(new_name) > DM_NAME_LEN - 1) {
|
||||||
|
- DMWARN("Invalid new logical volume name supplied.");
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
+ if (param->flags & DM_NEW_UUID_FLAG) {
|
||||||
|
+ if (new_data < param->data ||
|
||||||
|
+ invalid_str(new_data, (void *) param + param_size) ||
|
||||||
|
+ strlen(new_data) > DM_UUID_LEN - 1) {
|
||||||
|
+ DMWARN("Invalid new device uuid supplied.");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (new_data < param->data ||
|
||||||
|
+ invalid_str(new_data, (void *) param + param_size) ||
|
||||||
|
+ strlen(new_data) > DM_NAME_LEN - 1) {
|
||||||
|
+ DMWARN("Invalid new device name supplied.");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- r = check_name(new_name);
|
||||||
|
- if (r)
|
||||||
|
- return r;
|
||||||
|
+ r = check_name(new_data);
|
||||||
|
+ if (r)
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
param->data_size = 0;
|
||||||
|
|
||||||
|
return dm_hash_rename(param->event_nr, ¶m->flags, param->name,
|
||||||
|
- new_name);
|
||||||
|
+ new_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
|
||||||
|
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
|
||||||
|
index 2c445e1..3bbcb3a 100644
|
||||||
|
--- a/include/linux/dm-ioctl.h
|
||||||
|
+++ b/include/linux/dm-ioctl.h
|
||||||
|
@@ -266,9 +266,9 @@ enum {
|
||||||
|
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
|
||||||
|
|
||||||
|
#define DM_VERSION_MAJOR 4
|
||||||
|
-#define DM_VERSION_MINOR 17
|
||||||
|
-#define DM_VERSION_PATCHLEVEL 0
|
||||||
|
-#define DM_VERSION_EXTRA "-ioctl (2010-03-05)"
|
||||||
|
+#define DM_VERSION_MINOR 19
|
||||||
|
+#define DM_VERSION_PATCHLEVEL 1
|
||||||
|
+#define DM_VERSION_EXTRA "-ioctl (2010-10-12)"
|
||||||
|
|
||||||
|
/* Status bits */
|
||||||
|
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
|
||||||
|
@@ -321,4 +321,9 @@ enum {
|
||||||
|
*/
|
||||||
|
#define DM_UEVENT_GENERATED_FLAG (1 << 13) /* Out */
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * If set, rename operates on uuid, not name.
|
||||||
|
+ */
|
||||||
|
+#define DM_NEW_UUID_FLAG (1 << 14) /* In */
|
||||||
|
+
|
||||||
|
#endif /* _LINUX_DM_IOCTL_H */
|
||||||
|
--
|
||||||
|
1.7.2.3
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
From 8d2f6746f7f82e1aee2dc40a937b5954cfc73414 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kyle McMartin <kyle@mcmartin.ca>
|
||||||
|
Date: Sun, 17 Oct 2010 15:55:32 -0400
|
||||||
|
Subject: [PATCH] dmar: disable if ricoh multifunction detected
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/pci/intel-iommu.c | 10 ++++++++++
|
||||||
|
1 files changed, 10 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
|
||||||
|
index 8e499e8..076c5de 100644
|
||||||
|
--- a/drivers/pci/intel-iommu.c
|
||||||
|
+++ b/drivers/pci/intel-iommu.c
|
||||||
|
@@ -3755,6 +3755,18 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
|
||||||
|
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
|
||||||
|
|
||||||
|
+/* https://bugzilla.redhat.com/show_bug.cgi?id=605888 */
|
||||||
|
+static void __devinit quirk_ricoh_multifunction(struct pci_dev *dev)
|
||||||
|
+{
|
||||||
|
+ printk(KERN_INFO "intel_iommu: broken Ricoh device %04X detected, disabling...\n",
|
||||||
|
+ dev->device);
|
||||||
|
+ dmar_disabled = 1;
|
||||||
|
+}
|
||||||
|
+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe822, quirk_ricoh_multifunction);
|
||||||
|
+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe230, quirk_ricoh_multifunction);
|
||||||
|
+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe832, quirk_ricoh_multifunction);
|
||||||
|
+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe476, quirk_ricoh_multifunction);
|
||||||
|
+
|
||||||
|
/* On Tylersburg chipsets, some BIOSes have been known to enable the
|
||||||
|
ISOCH DMAR unit for the Azalia sound device, but not give it any
|
||||||
|
TLB entries, which causes it to deadlock. Check for that. We do
|
||||||
|
--
|
||||||
|
1.7.3.1
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
diff -up linux-2.6.35.x86_64/drivers/gpu/drm/drm_edid.c.da linux-2.6.35.x86_64/drivers/gpu/drm/drm_edid.c
|
||||||
|
--- linux-2.6.35.x86_64/drivers/gpu/drm/drm_edid.c.da 2010-08-01 18:11:14.000000000 -0400
|
||||||
|
+++ linux-2.6.35.x86_64/drivers/gpu/drm/drm_edid.c 2010-11-11 20:46:10.000000000 -0500
|
||||||
|
@@ -229,7 +229,7 @@ drm_do_probe_ddc_edid(struct i2c_adapter
|
||||||
|
.addr = DDC_ADDR,
|
||||||
|
.flags = I2C_M_RD,
|
||||||
|
.len = len,
|
||||||
|
- .buf = buf + start,
|
||||||
|
+ .buf = buf,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -242,7 +242,7 @@ drm_do_probe_ddc_edid(struct i2c_adapter
|
||||||
|
static u8 *
|
||||||
|
drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
- int i, j = 0;
|
||||||
|
+ int i, j = 0, valid_extensions = 0;
|
||||||
|
u8 *block, *new;
|
||||||
|
|
||||||
|
if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
|
||||||
|
@@ -269,14 +269,28 @@ drm_do_get_edid(struct drm_connector *co
|
||||||
|
|
||||||
|
for (j = 1; j <= block[0x7e]; j++) {
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
- if (drm_do_probe_ddc_edid(adapter, block, j,
|
||||||
|
- EDID_LENGTH))
|
||||||
|
+ if (drm_do_probe_ddc_edid(adapter,
|
||||||
|
+ block + (valid_extensions + 1) * EDID_LENGTH,
|
||||||
|
+ j, EDID_LENGTH))
|
||||||
|
goto out;
|
||||||
|
- if (drm_edid_block_valid(block + j * EDID_LENGTH))
|
||||||
|
+ if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) {
|
||||||
|
+ valid_extensions++;
|
||||||
|
break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (i == 4)
|
||||||
|
- goto carp;
|
||||||
|
+ printk(KERN_WARNING
|
||||||
|
+ "%s: Ignoring invalid EDID block %d.\n",
|
||||||
|
+ drm_get_connector_name(connector), j);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (valid_extensions != block[0x7e]) {
|
||||||
|
+ block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
|
||||||
|
+ block[0x7e] = valid_extensions;
|
||||||
|
+ new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
|
||||||
|
+ if (!new)
|
||||||
|
+ goto out;
|
||||||
|
+ block = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
|
@ -0,0 +1,57 @@
|
||||||
|
From 9fa9e790eb301bade8fe4ea0fd9ecb72617f0928 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Date: Thu, 5 Aug 2010 22:57:08 +0200
|
||||||
|
Subject: [PATCH 3/5] drm-i2c-ch7006-fix
|
||||||
|
|
||||||
|
drm/i2c/ch7006: Don't use POWER_LEVEL_FULL_POWER_OFF on early chip versions.
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/i2c/ch7006_drv.c | 1 +
|
||||||
|
drivers/gpu/drm/i2c/ch7006_mode.c | 5 ++++-
|
||||||
|
drivers/gpu/drm/i2c/ch7006_priv.h | 1 +
|
||||||
|
3 files changed, 6 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
|
||||||
|
index 81681a0..8c760c7 100644
|
||||||
|
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
|
||||||
|
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
|
||||||
|
@@ -454,6 +454,7 @@ static int ch7006_encoder_init(struct i2c_client *client,
|
||||||
|
priv->hmargin = 50;
|
||||||
|
priv->vmargin = 50;
|
||||||
|
priv->last_dpms = -1;
|
||||||
|
+ priv->chip_version = ch7006_read(client, CH7006_VERSION_ID);
|
||||||
|
|
||||||
|
if (ch7006_tv_norm) {
|
||||||
|
for (i = 0; i < NUM_TV_NORMS; i++) {
|
||||||
|
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c
|
||||||
|
index e447dfb..c860f24 100644
|
||||||
|
--- a/drivers/gpu/drm/i2c/ch7006_mode.c
|
||||||
|
+++ b/drivers/gpu/drm/i2c/ch7006_mode.c
|
||||||
|
@@ -316,7 +316,10 @@ void ch7006_setup_power_state(struct drm_encoder *encoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
- *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
|
||||||
|
+ if (priv->chip_version >= 0x20)
|
||||||
|
+ *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
|
||||||
|
+ else
|
||||||
|
+ *power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h
|
||||||
|
index b06d3d9..9487123 100644
|
||||||
|
--- a/drivers/gpu/drm/i2c/ch7006_priv.h
|
||||||
|
+++ b/drivers/gpu/drm/i2c/ch7006_priv.h
|
||||||
|
@@ -95,6 +95,7 @@ struct ch7006_priv {
|
||||||
|
int flicker;
|
||||||
|
int scale;
|
||||||
|
|
||||||
|
+ int chip_version;
|
||||||
|
int last_dpms;
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.2
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=639146
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
index ce8ff0e..3bbd2c4 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
@@ -1353,6 +1353,27 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
|
||||||
|
return can_switch;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* check the VBT to see whether the eDP is on DP-D port */
|
||||||
|
+static bool intel_dpd_is_edp(struct drm_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
+ struct child_device_config *p_child;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ if (!dev_priv->child_dev_num)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < dev_priv->child_dev_num; i++) {
|
||||||
|
+ p_child = dev_priv->child_dev + i;
|
||||||
|
+
|
||||||
|
+ if (p_child->dvo_port == PORT_IDPD &&
|
||||||
|
+ p_child->device_type == DEVICE_TYPE_eDP)
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int i915_load_modeset_init(struct drm_device *dev,
|
||||||
|
unsigned long prealloc_start,
|
||||||
|
unsigned long prealloc_size,
|
||||||
|
@@ -1409,6 +1430,15 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
||||||
|
if (ret)
|
||||||
|
DRM_INFO("failed to find VBIOS tables\n");
|
||||||
|
|
||||||
|
+ /* XXX: eDP doesn't even work in git HEAD,
|
||||||
|
+ * bail out and pray that text mode still works...
|
||||||
|
+ */
|
||||||
|
+ if (intel_dpd_is_edp(dev)) {
|
||||||
|
+ DRM_ERROR("eDP support is currently non-functional, please boot with \"nomodeset xdriver=vesa\"\n");
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto cleanup_ringbuffer;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
|
||||||
|
ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
|
||||||
|
if (ret)
|
|
@ -0,0 +1,70 @@
|
||||||
|
From ab7959dd389be36c0bc63e3e883b7891d2c1bfc4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Date: Wed, 8 Sep 2010 09:45:11 +0100
|
||||||
|
Subject: [PATCH] drm/i915: Disable output polling across suspend & resume
|
||||||
|
|
||||||
|
Suspending (especially hibernating) may take a finite amount of time,
|
||||||
|
during which a hotplug event may trigger and we will attempt to handle
|
||||||
|
it with inconsistent state. Disable hotplug polling around suspend and
|
||||||
|
resume.
|
||||||
|
|
||||||
|
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30070
|
||||||
|
Reported-by: Rui Tiago Matos <tiagomatos@gmail.com>
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/i915/i915_dma.c | 2 --
|
||||||
|
drivers/gpu/drm/i915/i915_drv.c | 11 ++++++++++-
|
||||||
|
2 files changed, 10 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
index ce8ff0e..c569617 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/i915_dma.c
|
||||||
|
@@ -1334,10 +1334,8 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
|
||||||
|
/* i915 resume handler doesn't set to D0 */
|
||||||
|
pci_set_power_state(dev->pdev, PCI_D0);
|
||||||
|
i915_resume(dev);
|
||||||
|
- drm_kms_helper_poll_enable(dev);
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR "i915: switched off\n");
|
||||||
|
- drm_kms_helper_poll_disable(dev);
|
||||||
|
i915_suspend(dev, pmm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
|
||||||
|
index 194e0c4..3ad3ebe 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/i915_drv.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/i915_drv.c
|
||||||
|
@@ -263,6 +263,8 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
|
||||||
|
if (state.event == PM_EVENT_PRETHAW)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+ drm_kms_helper_poll_disable(dev);
|
||||||
|
+
|
||||||
|
error = i915_drm_freeze(dev);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
@@ -306,12 +308,19 @@ static int i915_drm_thaw(struct drm_device *dev)
|
||||||
|
|
||||||
|
int i915_resume(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
if (pci_enable_device(dev->pdev))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
pci_set_master(dev->pdev);
|
||||||
|
|
||||||
|
- return i915_drm_thaw(dev);
|
||||||
|
+ ret = i915_drm_thaw(dev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ drm_kms_helper_poll_enable(dev);
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
--
|
||||||
|
1.7.2.3
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
From ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Date: Sun, 26 Sep 2010 20:50:05 +0100
|
||||||
|
Subject: drm/i915: Sanity check pread/pwrite
|
||||||
|
|
||||||
|
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
|
||||||
|
commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream.
|
||||||
|
|
||||||
|
Move the access control up from the fast paths, which are no longer
|
||||||
|
universally taken first, up into the caller. This then duplicates some
|
||||||
|
sanity checking along the slow paths, but is much simpler.
|
||||||
|
Tracked as CVE-2010-2962.
|
||||||
|
|
||||||
|
Reported-by: Kees Cook <kees@ubuntu.com>
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/i915/i915_gem.c | 28 ++++++++++++++++++++--------
|
||||||
|
1 file changed, 20 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/i915/i915_gem.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
||||||
|
@@ -465,8 +465,15 @@ i915_gem_pread_ioctl(struct drm_device *
|
||||||
|
*/
|
||||||
|
if (args->offset > obj->size || args->size > obj->size ||
|
||||||
|
args->offset + args->size > obj->size) {
|
||||||
|
- drm_gem_object_unreference_unlocked(obj);
|
||||||
|
- return -EINVAL;
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!access_ok(VERIFY_WRITE,
|
||||||
|
+ (char __user *)(uintptr_t)args->data_ptr,
|
||||||
|
+ args->size)) {
|
||||||
|
+ ret = -EFAULT;
|
||||||
|
+ goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i915_gem_object_needs_bit17_swizzle(obj)) {
|
||||||
|
@@ -478,8 +485,8 @@ i915_gem_pread_ioctl(struct drm_device *
|
||||||
|
file_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
+err:
|
||||||
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
|
-
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -568,8 +575,6 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
|
||||||
|
|
||||||
|
user_data = (char __user *) (uintptr_t) args->data_ptr;
|
||||||
|
remain = args->size;
|
||||||
|
- if (!access_ok(VERIFY_READ, user_data, remain))
|
||||||
|
- return -EFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
@@ -928,8 +933,15 @@ i915_gem_pwrite_ioctl(struct drm_device
|
||||||
|
*/
|
||||||
|
if (args->offset > obj->size || args->size > obj->size ||
|
||||||
|
args->offset + args->size > obj->size) {
|
||||||
|
- drm_gem_object_unreference_unlocked(obj);
|
||||||
|
- return -EINVAL;
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!access_ok(VERIFY_READ,
|
||||||
|
+ (char __user *)(uintptr_t)args->data_ptr,
|
||||||
|
+ args->size)) {
|
||||||
|
+ ret = -EFAULT;
|
||||||
|
+ goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can only do the GTT pwrite on untiled buffers, as otherwise
|
||||||
|
@@ -963,8 +975,8 @@ i915_gem_pwrite_ioctl(struct drm_device
|
||||||
|
DRM_INFO("pwrite failed %d\n", ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+err:
|
||||||
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
|
-
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
--- linux-2.6.35.noarch/drivers/gpu/drm/radeon/radeon_fence.c~ 2011-10-21 14:08:15.229351796 -0400
|
||||||
|
+++ linux-2.6.35.noarch/drivers/gpu/drm/radeon/radeon_fence.c 2011-10-21 14:08:35.140287089 -0400
|
||||||
|
@@ -232,7 +232,7 @@ retry:
|
||||||
|
*/
|
||||||
|
if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) {
|
||||||
|
/* good news we believe it's a lockup */
|
||||||
|
- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", fence->seq, seq);
|
||||||
|
+ printk(KERN_WARNING, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", fence->seq, seq);
|
||||||
|
/* FIXME: what should we do ? marking everyone
|
||||||
|
* as signaled for now
|
||||||
|
*/
|
|
@ -0,0 +1,21 @@
|
||||||
|
diff -up linux-2.6.35.x86_64/drivers/gpu/drm/nouveau/nouveau_connector.c.da linux-2.6.35.x86_64/drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
--- linux-2.6.35.x86_64/drivers/gpu/drm/nouveau/nouveau_connector.c.da 2010-11-08 19:55:42.000000000 -0500
|
||||||
|
+++ linux-2.6.35.x86_64/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-08 19:55:49.000000000 -0500
|
||||||
|
@@ -298,7 +298,7 @@ detect_analog:
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
-nouveau_connector_detect_lvds(struct drm_connector *connector)
|
||||||
|
+nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
|
@@ -319,7 +319,7 @@ nouveau_connector_detect_lvds(struct drm
|
||||||
|
|
||||||
|
/* Try retrieving EDID via DDC */
|
||||||
|
if (!dev_priv->vbios.fp_no_ddc) {
|
||||||
|
- status = nouveau_connector_detect(connector);
|
||||||
|
+ status = nouveau_connector_detect(connector, force);
|
||||||
|
if (status == connector_status_connected)
|
||||||
|
goto out;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
From d0301ece9e093c484f880893dc86d97848360892 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Fri, 19 Nov 2010 18:50:57 +1000
|
||||||
|
Subject: [PATCH 2/2] drm-nouveau-evo-hang
|
||||||
|
|
||||||
|
On some GF8+ boards, the display engine will stop processing its push
|
||||||
|
buffer if a wrap-around occurs at a certain point. The exact cause
|
||||||
|
is not known.
|
||||||
|
|
||||||
|
This patch by David Dillow (rhbz#537065) is a safe enough work-around
|
||||||
|
until it can be solved properly.
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nv50_display.c | 1 +
|
||||||
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
|
||||||
|
index 11d366a..4e5402c 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_display.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
|
||||||
|
@@ -364,6 +364,7 @@ nv50_display_init(struct drm_device *dev)
|
||||||
|
nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1);
|
||||||
|
|
||||||
|
evo->dma.max = (4096/4) - 2;
|
||||||
|
+ evo->dma.max &= ~7;
|
||||||
|
evo->dma.put = 0;
|
||||||
|
evo->dma.cur = evo->dma.put;
|
||||||
|
evo->dma.free = evo->dma.max - evo->dma.cur;
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
From b4166db6d1f951a460e5e7f52bb4b4d96f27f55a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Date: Fri, 19 Nov 2010 18:08:47 +1000
|
||||||
|
Subject: [PATCH 1/2] drm-nouveau-imac-g4
|
||||||
|
|
||||||
|
drm/nouveau: fabricate DCB encoder table for iMac G4
|
||||||
|
|
||||||
|
In typical Apple fashion there's no standard information about what
|
||||||
|
encoders are present on this machine, this patch adds a quirk to
|
||||||
|
provide it.
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_bios.c | 102 ++++++++++++--------------------
|
||||||
|
1 files changed, 38 insertions(+), 64 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
index 72905c9..8c287f8 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
@@ -5985,52 +5985,17 @@ static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
|
||||||
|
+static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c,
|
||||||
|
+ int heads, int or)
|
||||||
|
{
|
||||||
|
struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||||
|
|
||||||
|
- entry->type = 0;
|
||||||
|
+ entry->type = type;
|
||||||
|
entry->i2c_index = i2c;
|
||||||
|
entry->heads = heads;
|
||||||
|
- entry->location = DCB_LOC_ON_CHIP;
|
||||||
|
- entry->or = 1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
|
||||||
|
-{
|
||||||
|
- struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||||
|
-
|
||||||
|
- entry->type = 2;
|
||||||
|
- entry->i2c_index = LEGACY_I2C_PANEL;
|
||||||
|
- entry->heads = twoHeads ? 3 : 1;
|
||||||
|
- entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
|
||||||
|
- entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */
|
||||||
|
- entry->duallink_possible = false; /* SiI164 and co. are single link */
|
||||||
|
-
|
||||||
|
-#if 0
|
||||||
|
- /*
|
||||||
|
- * For dvi-a either crtc probably works, but my card appears to only
|
||||||
|
- * support dvi-d. "nvidia" still attempts to program it for dvi-a,
|
||||||
|
- * doing the full fp output setup (program 0x6808.. fp dimension regs,
|
||||||
|
- * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
|
||||||
|
- * the monitor picks up the mode res ok and lights up, but no pixel
|
||||||
|
- * data appears, so the board manufacturer probably connected up the
|
||||||
|
- * sync lines, but missed the video traces / components
|
||||||
|
- *
|
||||||
|
- * with this introduction, dvi-a left as an exercise for the reader.
|
||||||
|
- */
|
||||||
|
- fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
|
||||||
|
-#endif
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
|
||||||
|
-{
|
||||||
|
- struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||||
|
-
|
||||||
|
- entry->type = 1;
|
||||||
|
- entry->i2c_index = LEGACY_I2C_TV;
|
||||||
|
- entry->heads = twoHeads ? 3 : 1;
|
||||||
|
- entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
|
||||||
|
+ if (type != OUTPUT_ANALOG)
|
||||||
|
+ entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
|
||||||
|
+ entry->or = or;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
@@ -6297,8 +6262,36 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
|
||||||
|
+{
|
||||||
|
+ struct dcb_table *dcb = &bios->dcb;
|
||||||
|
+ int all_heads = (nv_two_heads(dev) ? 3 : 1);
|
||||||
|
+
|
||||||
|
+#ifdef __powerpc__
|
||||||
|
+ /* Apple iMac G4 NV17 */
|
||||||
|
+ if (of_machine_is_compatible("PowerMac4,5")) {
|
||||||
|
+ fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1);
|
||||||
|
+ fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* Make up some sane defaults */
|
||||||
|
+ fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1);
|
||||||
|
+
|
||||||
|
+ if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||||
|
+ fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV,
|
||||||
|
+ all_heads, 0);
|
||||||
|
+
|
||||||
|
+ else if (bios->tmds.output0_script_ptr ||
|
||||||
|
+ bios->tmds.output1_script_ptr)
|
||||||
|
+ fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL,
|
||||||
|
+ all_heads, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
-parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||||
|
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
|
||||||
|
{
|
||||||
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
|
struct dcb_table *dcb = &bios->dcb;
|
||||||
|
@@ -6318,12 +6311,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||||
|
|
||||||
|
/* this situation likely means a really old card, pre DCB */
|
||||||
|
if (dcbptr == 0x0) {
|
||||||
|
- NV_INFO(dev, "Assuming a CRT output exists\n");
|
||||||
|
- fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
|
||||||
|
-
|
||||||
|
- if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||||
|
- fabricate_tv_output(dcb, twoHeads);
|
||||||
|
-
|
||||||
|
+ fabricate_dcb_encoder_table(dev, bios);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -6383,21 +6371,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||||
|
*/
|
||||||
|
NV_TRACEWARN(dev, "No useful information in BIOS output table; "
|
||||||
|
"adding all possible outputs\n");
|
||||||
|
- fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Attempt to detect TV before DVI because the test
|
||||||
|
- * for the former is more accurate and it rules the
|
||||||
|
- * latter out.
|
||||||
|
- */
|
||||||
|
- if (nv04_tv_identify(dev,
|
||||||
|
- bios->legacy.i2c_indices.tv) >= 0)
|
||||||
|
- fabricate_tv_output(dcb, twoHeads);
|
||||||
|
-
|
||||||
|
- else if (bios->tmds.output0_script_ptr ||
|
||||||
|
- bios->tmds.output1_script_ptr)
|
||||||
|
- fabricate_dvi_i_output(dcb, twoHeads);
|
||||||
|
-
|
||||||
|
+ fabricate_dcb_encoder_table(dev, bios);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -6787,7 +6761,7 @@ nouveau_bios_init(struct drm_device *dev)
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- ret = parse_dcb_table(dev, bios, nv_two_heads(dev));
|
||||||
|
+ ret = parse_dcb_table(dev, bios);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
From 2120b3b32d96d523b18c82beb99a2d1c6135eb49 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Mon, 21 Mar 2011 21:31:21 +1000
|
||||||
|
Subject: [PATCH] drm/nouveau: implement init table opcode 0x5c
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_bios.c | 27 ++++++++++++++++++++++++---
|
||||||
|
1 files changed, 24 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
index 8314a49..eca191a 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||||
|
@@ -269,7 +269,7 @@ struct init_tbl_entry {
|
||||||
|
int (*handler)(struct nvbios *, uint16_t, struct init_exec *);
|
||||||
|
};
|
||||||
|
|
||||||
|
-static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *);
|
||||||
|
+static int parse_init_table(struct nvbios *, uint16_t, struct init_exec *);
|
||||||
|
|
||||||
|
#define MACRO_INDEX_SIZE 2
|
||||||
|
#define MACRO_SIZE 8
|
||||||
|
@@ -2011,6 +2011,27 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
+init_jump(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * INIT_JUMP opcode: 0x5C ('\')
|
||||||
|
+ *
|
||||||
|
+ * offset (8 bit): opcode
|
||||||
|
+ * offset + 1 (16 bit): offset (in bios)
|
||||||
|
+ *
|
||||||
|
+ * Continue execution of init table from 'offset'
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ uint16_t jmp_offset = ROM16(bios->data[offset + 1]);
|
||||||
|
+
|
||||||
|
+ if (!iexec->execute)
|
||||||
|
+ return 3;
|
||||||
|
+
|
||||||
|
+ BIOSLOG(bios, "0x%04X: Jump to 0x%04X\n", offset, jmp_offset);
|
||||||
|
+ return jmp_offset - offset;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
@@ -3659,6 +3680,7 @@ static struct init_tbl_entry itbl_entry[] = {
|
||||||
|
{ "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence },
|
||||||
|
/* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
|
||||||
|
{ "INIT_SUB_DIRECT" , 0x5B, init_sub_direct },
|
||||||
|
+ { "INIT_JUMP" , 0x5C, init_jump },
|
||||||
|
{ "INIT_I2C_IF" , 0x5E, init_i2c_if },
|
||||||
|
{ "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg },
|
||||||
|
{ "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io },
|
||||||
|
@@ -3700,8 +3722,7 @@ static struct init_tbl_entry itbl_entry[] = {
|
||||||
|
#define MAX_TABLE_OPS 1000
|
||||||
|
|
||||||
|
static int
|
||||||
|
-parse_init_table(struct nvbios *bios, unsigned int offset,
|
||||||
|
- struct init_exec *iexec)
|
||||||
|
+parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Parses all commands in an init table.
|
||||||
|
--
|
||||||
|
1.7.4.1
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
From 8f51b07995c55369bfd27921ef10b76c2b203fe8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Tue, 17 Aug 2010 14:20:29 +1000
|
||||||
|
Subject: [PATCH] drm-nouveau-nv50-crtc-update-delay
|
||||||
|
|
||||||
|
rhbz#614552
|
||||||
|
|
||||||
|
Adds a short delay before doing framebuffer-only CRTC updates. Fixes
|
||||||
|
an issue that effects some cards (Quadro NVS295/FX580) where two of
|
||||||
|
these updates in quick succession hangs the display engine.
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nv50_crtc.c | 3 +++
|
||||||
|
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
|
||||||
|
index 2423c92..5c2aa1e 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
|
||||||
|
@@ -540,6 +540,9 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||||
|
nouveau_bo_unpin(ofb->nvbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (update)
|
||||||
|
+ mdelay(1);
|
||||||
|
+
|
||||||
|
nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base;
|
||||||
|
nv_crtc->fb.tile_flags = fb->nvbo->tile_flags;
|
||||||
|
nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
|
||||||
|
--
|
||||||
|
1.7.3.1
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
From e7e3837f6395e44b5b5fb7cdbcccaba5baf76803 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Fri, 22 Oct 2010 10:26:24 +1000
|
||||||
|
Subject: [PATCH] drm-nouveau-nv86-bug
|
||||||
|
|
||||||
|
drm/nv50: implement possible workaround for NV86 PGRAPH TLB flush hang
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_drv.h | 5 +++
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_mem.c | 14 +++-----
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_sgdma.c | 8 ++--
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_state.c | 10 ++++++
|
||||||
|
drivers/gpu/drm/nouveau/nv50_fifo.c | 5 +++
|
||||||
|
drivers/gpu/drm/nouveau/nv50_graph.c | 52 +++++++++++++++++++++++++++++++
|
||||||
|
drivers/gpu/drm/nouveau/nv50_instmem.c | 1 -
|
||||||
|
7 files changed, 82 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
index be53e92..4273390 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
@@ -304,6 +304,7 @@ struct nouveau_fifo_engine {
|
||||||
|
void (*destroy_context)(struct nouveau_channel *);
|
||||||
|
int (*load_context)(struct nouveau_channel *);
|
||||||
|
int (*unload_context)(struct drm_device *);
|
||||||
|
+ void (*tlb_flush)(struct drm_device *dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nouveau_pgraph_object_method {
|
||||||
|
@@ -336,6 +337,7 @@ struct nouveau_pgraph_engine {
|
||||||
|
void (*destroy_context)(struct nouveau_channel *);
|
||||||
|
int (*load_context)(struct nouveau_channel *);
|
||||||
|
int (*unload_context)(struct drm_device *);
|
||||||
|
+ void (*tlb_flush)(struct drm_device *dev);
|
||||||
|
|
||||||
|
void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
|
||||||
|
uint32_t size, uint32_t pitch);
|
||||||
|
@@ -944,6 +946,7 @@ extern int nv50_fifo_create_context(struct nouveau_channel *);
|
||||||
|
extern void nv50_fifo_destroy_context(struct nouveau_channel *);
|
||||||
|
extern int nv50_fifo_load_context(struct nouveau_channel *);
|
||||||
|
extern int nv50_fifo_unload_context(struct drm_device *);
|
||||||
|
+extern void nv50_fifo_tlb_flush(struct drm_device *dev);
|
||||||
|
|
||||||
|
/* nvc0_fifo.c */
|
||||||
|
extern int nvc0_fifo_init(struct drm_device *);
|
||||||
|
@@ -1021,6 +1024,8 @@ extern int nv50_graph_load_context(struct nouveau_channel *);
|
||||||
|
extern int nv50_graph_unload_context(struct drm_device *);
|
||||||
|
extern void nv50_graph_context_switch(struct drm_device *);
|
||||||
|
extern int nv50_grctx_init(struct nouveau_grctx *);
|
||||||
|
+extern void nv50_graph_tlb_flush(struct drm_device *dev);
|
||||||
|
+extern void nv86_graph_tlb_flush(struct drm_device *dev);
|
||||||
|
|
||||||
|
/* nvc0_graph.c */
|
||||||
|
extern int nvc0_graph_init(struct drm_device *);
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||||
|
index 4f0ae39..514ad9f 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||||
|
@@ -173,11 +173,10 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- dev_priv->engine.instmem.flush(dev);
|
||||||
|
|
||||||
|
- nv50_vm_flush(dev, 5);
|
||||||
|
- nv50_vm_flush(dev, 0);
|
||||||
|
- nv50_vm_flush(dev, 4);
|
||||||
|
+ dev_priv->engine.instmem.flush(dev);
|
||||||
|
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||||
|
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||||
|
nv50_vm_flush(dev, 6);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -207,11 +206,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
|
||||||
|
pte++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- dev_priv->engine.instmem.flush(dev);
|
||||||
|
|
||||||
|
- nv50_vm_flush(dev, 5);
|
||||||
|
- nv50_vm_flush(dev, 0);
|
||||||
|
- nv50_vm_flush(dev, 4);
|
||||||
|
+ dev_priv->engine.instmem.flush(dev);
|
||||||
|
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||||
|
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||||
|
nv50_vm_flush(dev, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||||
|
index 7f028fe..d55a583 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||||
|
@@ -120,8 +120,8 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
|
||||||
|
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||||
|
|
||||||
|
if (dev_priv->card_type == NV_50) {
|
||||||
|
- nv50_vm_flush(dev, 5); /* PGRAPH */
|
||||||
|
- nv50_vm_flush(dev, 0); /* PFIFO */
|
||||||
|
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||||
|
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
nvbe->bound = true;
|
||||||
|
@@ -162,8 +162,8 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
|
||||||
|
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||||
|
|
||||||
|
if (dev_priv->card_type == NV_50) {
|
||||||
|
- nv50_vm_flush(dev, 5);
|
||||||
|
- nv50_vm_flush(dev, 0);
|
||||||
|
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||||
|
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
nvbe->bound = false;
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
index be85960..47c353c 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
@@ -333,6 +333,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||||
|
engine->graph.destroy_context = nv50_graph_destroy_context;
|
||||||
|
engine->graph.load_context = nv50_graph_load_context;
|
||||||
|
engine->graph.unload_context = nv50_graph_unload_context;
|
||||||
|
+ if (dev_priv->chipset != 0x86)
|
||||||
|
+ engine->graph.tlb_flush = nv50_graph_tlb_flush;
|
||||||
|
+ else {
|
||||||
|
+ /* from what i can see nvidia do this on every
|
||||||
|
+ * pre-NVA3 board except NVAC, but, we've only
|
||||||
|
+ * ever seen problems on NV86
|
||||||
|
+ */
|
||||||
|
+ engine->graph.tlb_flush = nv86_graph_tlb_flush;
|
||||||
|
+ }
|
||||||
|
engine->fifo.channels = 128;
|
||||||
|
engine->fifo.init = nv50_fifo_init;
|
||||||
|
engine->fifo.takedown = nv50_fifo_takedown;
|
||||||
|
@@ -344,6 +353,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||||
|
engine->fifo.destroy_context = nv50_fifo_destroy_context;
|
||||||
|
engine->fifo.load_context = nv50_fifo_load_context;
|
||||||
|
engine->fifo.unload_context = nv50_fifo_unload_context;
|
||||||
|
+ engine->fifo.tlb_flush = nv50_fifo_tlb_flush;
|
||||||
|
engine->display.early_init = nv50_display_early_init;
|
||||||
|
engine->display.late_takedown = nv50_display_late_takedown;
|
||||||
|
engine->display.create = nv50_display_create;
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||||
|
index a46a961..1da65bd 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||||
|
@@ -464,3 +464,8 @@ nv50_fifo_unload_context(struct drm_device *dev)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+nv50_fifo_tlb_flush(struct drm_device *dev)
|
||||||
|
+{
|
||||||
|
+ nv50_vm_flush(dev, 5);
|
||||||
|
+}
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
index cbf5ae2..8b669d0 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
@@ -402,3 +402,55 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
|
||||||
|
{ 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+nv50_graph_tlb_flush(struct drm_device *dev)
|
||||||
|
+{
|
||||||
|
+ nv50_vm_flush(dev, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+nv86_graph_tlb_flush(struct drm_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
|
+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
|
||||||
|
+ bool idle, timeout = false;
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ u64 start;
|
||||||
|
+ u32 tmp;
|
||||||
|
+
|
||||||
|
+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||||
|
+ nv_mask(dev, 0x400500, 0x00000001, 0x00000000);
|
||||||
|
+
|
||||||
|
+ start = ptimer->read(dev);
|
||||||
|
+ do {
|
||||||
|
+ idle = true;
|
||||||
|
+
|
||||||
|
+ for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) {
|
||||||
|
+ if ((tmp & 7) == 1)
|
||||||
|
+ idle = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) {
|
||||||
|
+ if ((tmp & 7) == 1)
|
||||||
|
+ idle = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) {
|
||||||
|
+ if ((tmp & 7) == 1)
|
||||||
|
+ idle = false;
|
||||||
|
+ }
|
||||||
|
+ } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000));
|
||||||
|
+
|
||||||
|
+ if (timeout) {
|
||||||
|
+ NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: "
|
||||||
|
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||||
|
+ nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380),
|
||||||
|
+ nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ nv50_vm_flush(dev, 0);
|
||||||
|
+
|
||||||
|
+ nv_mask(dev, 0x400500, 0x00000001, 0x00000001);
|
||||||
|
+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||||
|
+}
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||||
|
index ac3de05..c836ddc 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||||
|
@@ -402,7 +402,6 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
||||||
|
}
|
||||||
|
dev_priv->engine.instmem.flush(dev);
|
||||||
|
|
||||||
|
- nv50_vm_flush(dev, 4);
|
||||||
|
nv50_vm_flush(dev, 6);
|
||||||
|
|
||||||
|
gpuobj->im_bound = 1;
|
||||||
|
--
|
||||||
|
1.7.3.1
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
From 07a51882863d9e45b0715dcffbb66491adf2fb4e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Wed, 30 Jun 2010 13:34:05 +1000
|
||||||
|
Subject: [PATCH] drm/nouveau: disable acceleration on NVA3/NVA5/NVA8 by default
|
||||||
|
|
||||||
|
There's an GPU lockup problem for which the cause is currently unknown
|
||||||
|
on these chipsets.
|
||||||
|
|
||||||
|
Until it's resolved, it's better to leave the user with a working system
|
||||||
|
without acceleration than to have random lockups.
|
||||||
|
|
||||||
|
With this patch, acceleration will be off by default if a known problem
|
||||||
|
chipset is detected, but can be re-enabled with nouveau.noaccel=0 on
|
||||||
|
the kernel commandline.
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +-
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_drv.h | 1 +
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_state.c | 23 +++++++++++++++++++----
|
||||||
|
3 files changed, 21 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||||
|
index 946748a..9b69328 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||||
|
@@ -72,7 +72,7 @@ int nouveau_ignorelid = 0;
|
||||||
|
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
|
||||||
|
|
||||||
|
MODULE_PARM_DESC(noaccel, "Disable all acceleration");
|
||||||
|
-int nouveau_noaccel = 0;
|
||||||
|
+int nouveau_noaccel = -1;
|
||||||
|
module_param_named(noaccel, nouveau_noaccel, int, 0400);
|
||||||
|
|
||||||
|
MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
index 24b3d03..0cf1bee 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
@@ -504,6 +504,7 @@ enum nouveau_card_type {
|
||||||
|
|
||||||
|
struct drm_nouveau_private {
|
||||||
|
struct drm_device *dev;
|
||||||
|
+ bool noaccel;
|
||||||
|
|
||||||
|
/* the card type, takes NV_* as values */
|
||||||
|
enum nouveau_card_type card_type;
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
index be85960..896f6ae 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||||
|
@@ -563,7 +563,7 @@ nouveau_card_init(struct drm_device *dev)
|
||||||
|
if (ret)
|
||||||
|
goto out_timer;
|
||||||
|
|
||||||
|
- if (nouveau_noaccel)
|
||||||
|
+ if (dev_priv->noaccel)
|
||||||
|
engine->graph.accel_blocked = true;
|
||||||
|
else {
|
||||||
|
/* PGRAPH */
|
||||||
|
@@ -613,10 +613,10 @@ out_irq:
|
||||||
|
out_display:
|
||||||
|
engine->display.destroy(dev);
|
||||||
|
out_fifo:
|
||||||
|
- if (!nouveau_noaccel)
|
||||||
|
+ if (!dev_priv->noaccel)
|
||||||
|
engine->fifo.takedown(dev);
|
||||||
|
out_graph:
|
||||||
|
- if (!nouveau_noaccel)
|
||||||
|
+ if (!dev_priv->noaccel)
|
||||||
|
engine->graph.takedown(dev);
|
||||||
|
out_fb:
|
||||||
|
engine->fb.takedown(dev);
|
||||||
|
@@ -655,7 +655,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
||||||
|
dev_priv->channel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!nouveau_noaccel) {
|
||||||
|
+ if (!dev_priv->noaccel) {
|
||||||
|
engine->fifo.takedown(dev);
|
||||||
|
engine->graph.takedown(dev);
|
||||||
|
}
|
||||||
|
@@ -861,6 +861,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
||||||
|
if (ret)
|
||||||
|
goto err_mmio;
|
||||||
|
|
||||||
|
+ if (nouveau_noaccel == -1) {
|
||||||
|
+ switch (dev_priv->chipset) {
|
||||||
|
+ case 0xa3:
|
||||||
|
+ case 0xa5:
|
||||||
|
+ case 0xa8:
|
||||||
|
+ dev_priv->noaccel = true;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ dev_priv->noaccel = false;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ dev_priv->noaccel = (nouveau_noaccel != 0);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
|
||||||
|
if (dev_priv->card_type >= NV_40) {
|
||||||
|
int ramin_bar = 2;
|
||||||
|
--
|
||||||
|
1.7.2.2
|
|
@ -0,0 +1,25 @@
|
||||||
|
From 7abba51e3fc9e3fdd43c63eeb1a680a2e258a833 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Fri, 19 Nov 2010 18:59:15 +1000
|
||||||
|
Subject: [PATCH] drm-nouveau-nvaf-grclass
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nv50_graph.c | 1 +
|
||||||
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
index 8b669d0..235be5f 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||||
|
@@ -400,6 +400,7 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
|
||||||
|
{ 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */
|
||||||
|
{ 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */
|
||||||
|
{ 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */
|
||||||
|
+ { 0x8697, false, NULL }, /* tesla (nvaf) */
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
From 4733f633c4bfb0672d5bd88a8d19a03e27a3c1d0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Date: Fri, 23 Jul 2010 09:06:52 +1000
|
||||||
|
Subject: [PATCH 2/2] drm-nouveau-race-fix
|
||||||
|
|
||||||
|
drm/nouveau: fix race condition when under memory pressure
|
||||||
|
|
||||||
|
rhbz#602663
|
||||||
|
|
||||||
|
When VRAM is running out it's possible that the client's push buffers get
|
||||||
|
evicted to main memory. When they're validated back in, the GPU may
|
||||||
|
be used for the copy back to VRAM, but the existing synchronisation code
|
||||||
|
only deals with inter-channel sync, not sync between PFIFO and PGRAPH on
|
||||||
|
the same channel. This leads to PFIFO fetching from command buffers that
|
||||||
|
haven't quite been copied by PGRAPH yet.
|
||||||
|
|
||||||
|
This patch marks push buffers as so, and forces any GPU-assisted buffer
|
||||||
|
moves to be done on a different channel, which triggers the correct
|
||||||
|
synchronisation to happen before we submit them.
|
||||||
|
|
||||||
|
After discussion with another nouveau developer, it was agreed that while
|
||||||
|
this patch is fine in itself, that we'd prefer to work out a nicer, but
|
||||||
|
likely much more invasive, fix upstream.
|
||||||
|
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_bo.c | 15 +++++++++++++
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_drv.h | 1 +
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++++++++++++++---------
|
||||||
|
3 files changed, 42 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
|
||||||
|
index 553a01d..5e62d1b 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
|
||||||
|
@@ -36,6 +36,21 @@
|
||||||
|
#include <linux/log2.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
+int
|
||||||
|
+nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan)
|
||||||
|
+{
|
||||||
|
+ struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (!prev_fence || nouveau_fence_channel(prev_fence) == chan)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ spin_lock(&nvbo->bo.lock);
|
||||||
|
+ ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||||
|
+ spin_unlock(&nvbo->bo.lock);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
|
||||||
|
{
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
index 2eb622b..70a16f3 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||||
|
@@ -1167,6 +1167,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
|
||||||
|
extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
|
||||||
|
extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
|
||||||
|
extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
|
||||||
|
+extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *);
|
||||||
|
|
||||||
|
/* nouveau_fence.c */
|
||||||
|
struct nouveau_fence;
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
|
||||||
|
index 62ac673..613f878 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
|
||||||
|
@@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
||||||
|
|
||||||
|
list_for_each_entry(nvbo, list, entry) {
|
||||||
|
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
|
||||||
|
- struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
|
||||||
|
|
||||||
|
- if (prev_fence && nouveau_fence_channel(prev_fence) != chan) {
|
||||||
|
- spin_lock(&nvbo->bo.lock);
|
||||||
|
- ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||||
|
- spin_unlock(&nvbo->bo.lock);
|
||||||
|
- if (unlikely(ret)) {
|
||||||
|
- NV_ERROR(dev, "fail wait other chan\n");
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
+ ret = nouveau_bo_sync_gpu(nvbo, chan);
|
||||||
|
+ if (unlikely(ret)) {
|
||||||
|
+ NV_ERROR(dev, "fail pre-validate sync\n");
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
|
||||||
|
@@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- nvbo->channel = chan;
|
||||||
|
+ nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
|
||||||
|
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
|
||||||
|
false, false, false);
|
||||||
|
nvbo->channel = NULL;
|
||||||
|
@@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ret = nouveau_bo_sync_gpu(nvbo, chan);
|
||||||
|
+ if (unlikely(ret)) {
|
||||||
|
+ NV_ERROR(dev, "fail post-validate sync\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (nvbo->bo.offset == b->presumed.offset &&
|
||||||
|
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
|
||||||
|
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
||||||
|
@@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
+ /* Mark push buffers as being used on PFIFO, the validation code
|
||||||
|
+ * will then make sure that if the pushbuf bo moves, that they
|
||||||
|
+ * happen on the kernel channel, which will in turn cause a sync
|
||||||
|
+ * to happen before we try and submit the push buffer.
|
||||||
|
+ */
|
||||||
|
+ for (i = 0; i < req->nr_push; i++) {
|
||||||
|
+ if (push[i].bo_index >= req->nr_buffers) {
|
||||||
|
+ NV_ERROR(dev, "push %d buffer not in list\n", i);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bo[push[i].bo_index].read_domains |= (1 << 31);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Validate buffer list */
|
||||||
|
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
|
||||||
|
req->nr_buffers, &op, &do_reloc);
|
||||||
|
--
|
||||||
|
1.7.2.2
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,601 @@
|
||||||
|
commit 879d56da9b89b52de2109cadf1369967522428e8
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Tue Oct 26 12:55:52 2010 +1000
|
||||||
|
|
||||||
|
drm/radeon/kms: don't poll dac load detect.
|
||||||
|
|
||||||
|
This is slightly destructive, cpu intensive and can cause lockups.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 2563a90cdda1fe490947dc032ce17bf1118afc39
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Tue Nov 9 10:26:00 2010 +1000
|
||||||
|
|
||||||
|
drm: Use a nondestructive mode for output detect when polling (v2)
|
||||||
|
|
||||||
|
v2: Julien Cristau pointed out that @nondestructive results in
|
||||||
|
double-negatives and confusion when trying to interpret the parameter,
|
||||||
|
so use @force instead. Much easier to type as well. ;-)
|
||||||
|
|
||||||
|
And fix the miscompilation of vmgfx reported by Sedat Dilek.
|
||||||
|
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
drivers/gpu/drm/i915/intel_tv.c
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
|
||||||
|
commit deb557bbbcaa7fa8281d51490c73b51f579bc84d
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Tue Nov 9 10:24:06 2010 +1000
|
||||||
|
|
||||||
|
drm: Use a nondestructive mode for output detect when polling
|
||||||
|
|
||||||
|
Destructive load-detection is very expensive and due to failings
|
||||||
|
elsewhere can trigger system wide stalls of up to 600ms. A simple
|
||||||
|
first step to correcting this is not to invoke such an expensive
|
||||||
|
and destructive load-detection operation automatically.
|
||||||
|
|
||||||
|
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29536
|
||||||
|
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16265
|
||||||
|
Reported-by: Bruno Prémont <bonbons@linux-vserver.org>
|
||||||
|
Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com>
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
drivers/gpu/drm/i915/intel_tv.c
|
||||||
|
drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
|
||||||
|
commit 8d5d3cd3612618a3c2214048788f0b2cc463ce0f
|
||||||
|
Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Date: Mon Sep 6 23:53:47 2010 +0100
|
||||||
|
|
||||||
|
drm: Fix regression in disable polling e58f637
|
||||||
|
|
||||||
|
I broke out my trusty i845 and found a new boot failure, which upon
|
||||||
|
inspection turned out to be a recursion within:
|
||||||
|
|
||||||
|
drm_helper_probe_single_connector_modes() -> drm_helper_hpd_irq_event()
|
||||||
|
-> intel_crt_detect() -> drm_helper_probe_single_connector_modes()
|
||||||
|
|
||||||
|
Calling drm_kms_helper_poll_enable() instead performs the desired
|
||||||
|
re-initialisation of the polling should the user have toggled the
|
||||||
|
parameter, without the recursive side-effect.
|
||||||
|
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Cc: Dave Airlie <airlied@redhat.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit ec0becade1eae9b0f40b12ea4fcc3ea36e993ba3
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Tue Nov 9 09:48:34 2010 +1000
|
||||||
|
|
||||||
|
drm/kms: Add a module parameter to disable polling
|
||||||
|
|
||||||
|
Polling for a VGA device on an old system can be quite expensive,
|
||||||
|
causing latencies on the order of 600ms. As we hold the mode mutex for
|
||||||
|
this time and also need the same mutex to move the cursor, we trigger a
|
||||||
|
user-visible stall.
|
||||||
|
|
||||||
|
The real solution would involve improving the granulatity of the
|
||||||
|
locking and so perhaps performing some of the probing not under the lock
|
||||||
|
or some other updates can be done under different locks. Also reducing the
|
||||||
|
cost of probing for a non-existent monitor would be worthwhile. However,
|
||||||
|
exposing a parameter to disable polling is a simple workaround in the
|
||||||
|
meantime.
|
||||||
|
|
||||||
|
In order to accommodate users turning polling on and off at runtime, the
|
||||||
|
polling is potentially re-enabled on every probe. This is coupled to
|
||||||
|
the user calling xrandr, which seems to be a vaild time to reset the
|
||||||
|
polling timeout since the information on the connection has just been
|
||||||
|
updated. (The presumption being that all connections are probed in a
|
||||||
|
single xrandr pass, which is currently valid.)
|
||||||
|
|
||||||
|
References:
|
||||||
|
|
||||||
|
Bug 29536 - 2.6.35 causes ~600ms latency every 10s
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=29536
|
||||||
|
|
||||||
|
Bug 16265 - Why is kslowd accumulating so much CPU time?
|
||||||
|
https://bugzilla.kernel.org/show_bug.cgi?id=16265
|
||||||
|
|
||||||
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||||
|
Reported-and-tested-by: Bruno Prémont <bonbons@linux-vserver.org>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
drivers/gpu/drm/drm_crtc_helper.c
|
||||||
|
|
||||||
|
commit 77e90256db2f7e6424717f7cc984b22d2832243f
|
||||||
|
Author: Dan Carpenter <error27@gmail.com>
|
||||||
|
Date: Thu Aug 19 11:46:29 2010 +0200
|
||||||
|
|
||||||
|
drm: move dereference below check
|
||||||
|
|
||||||
|
"fb_helper_conn" is dereferenced before the check for NULL. It's never
|
||||||
|
actually NULL here, so this is mostly to keep the static checkers happy.
|
||||||
|
|
||||||
|
Signed-off-by: Dan Carpenter <error27@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 86e25290d9df7a84d185dfc037851d72d270a6c0
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Tue Jul 20 03:24:11 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: make sure HPD is set to NONE on analog-only connectors
|
||||||
|
|
||||||
|
HPD is digital only.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
|
||||||
|
index 25d70d6..d537039 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_crtc_helper.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_crtc_helper.c
|
||||||
|
@@ -34,6 +34,9 @@
|
||||||
|
#include "drm_crtc_helper.h"
|
||||||
|
#include "drm_fb_helper.h"
|
||||||
|
|
||||||
|
+static bool drm_kms_helper_poll = true;
|
||||||
|
+module_param_named(poll, drm_kms_helper_poll, bool, 0600);
|
||||||
|
+
|
||||||
|
static void drm_mode_validate_flag(struct drm_connector *connector,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
@@ -98,8 +101,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
||||||
|
connector->status = connector_status_disconnected;
|
||||||
|
if (connector->funcs->force)
|
||||||
|
connector->funcs->force(connector);
|
||||||
|
- } else
|
||||||
|
- connector->status = connector->funcs->detect(connector);
|
||||||
|
+ } else {
|
||||||
|
+ connector->status = connector->funcs->detect(connector, true);
|
||||||
|
+ drm_kms_helper_poll_enable(dev);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (connector->status == connector_status_disconnected) {
|
||||||
|
DRM_DEBUG_KMS("%s is disconnected\n",
|
||||||
|
@@ -820,6 +825,9 @@ static void output_poll_execute(struct slow_work *work)
|
||||||
|
bool repoll = false, changed = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ if (!drm_kms_helper_poll)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
|
|
||||||
|
@@ -839,7 +847,7 @@ static void output_poll_execute(struct slow_work *work)
|
||||||
|
!(connector->polled & DRM_CONNECTOR_POLL_HPD))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
- status = connector->funcs->detect(connector);
|
||||||
|
+ status = connector->funcs->detect(connector, false);
|
||||||
|
if (old_status != status)
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
@@ -874,6 +882,9 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
|
||||||
|
struct drm_connector *connector;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
|
if (connector->polled)
|
||||||
|
poll = true;
|
||||||
|
@@ -909,9 +920,12 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
if (!dev->mode_config.poll_enabled)
|
||||||
|
return;
|
||||||
|
+
|
||||||
|
delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
|
||||||
|
/* schedule a slow work asap */
|
||||||
|
- delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, 0);
|
||||||
|
+ if (drm_kms_helper_poll)
|
||||||
|
+ delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, 0);
|
||||||
|
+
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_helper_hpd_irq_event);
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||||
|
index 7196620..cef8d8d 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||||
|
@@ -94,10 +94,11 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn
|
||||||
|
int i;
|
||||||
|
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
||||||
|
struct drm_fb_helper_cmdline_mode *cmdline_mode;
|
||||||
|
- struct drm_connector *connector = fb_helper_conn->connector;
|
||||||
|
+ struct drm_connector *connector;
|
||||||
|
|
||||||
|
if (!fb_helper_conn)
|
||||||
|
return false;
|
||||||
|
+ connector = fb_helper_conn->connector;
|
||||||
|
|
||||||
|
cmdline_mode = &fb_helper_conn->cmdline_mode;
|
||||||
|
if (!mode_option)
|
||||||
|
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
|
||||||
|
index 101d381..9500af1 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_sysfs.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_sysfs.c
|
||||||
|
@@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device,
|
||||||
|
struct drm_connector *connector = to_drm_connector(device);
|
||||||
|
enum drm_connector_status status;
|
||||||
|
|
||||||
|
- status = connector->funcs->detect(connector);
|
||||||
|
+ status = connector->funcs->detect(connector, true);
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||||
|
drm_get_connector_status_name(status));
|
||||||
|
}
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
|
||||||
|
index ee0732b..3886b47 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_crt.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_crt.c
|
||||||
|
@@ -402,7 +402,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+intel_crt_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||||
|
@@ -421,6 +422,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
|
||||||
|
if (intel_crt_detect_ddc(encoder))
|
||||||
|
return connector_status_connected;
|
||||||
|
|
||||||
|
+ if (!force)
|
||||||
|
+ return connector->status;
|
||||||
|
+
|
||||||
|
/* for pre-945g platforms use load detect */
|
||||||
|
if (encoder->crtc && encoder->crtc->enabled) {
|
||||||
|
status = intel_crt_load_detect(encoder->crtc, intel_encoder);
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
|
||||||
|
index d9de8f1..b58249d 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_dp.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_dp.c
|
||||||
|
@@ -1287,7 +1287,7 @@ ironlake_dp_detect(struct drm_connector *connector)
|
||||||
|
* \return false if DP port is disconnected.
|
||||||
|
*/
|
||||||
|
static enum drm_connector_status
|
||||||
|
-intel_dp_detect(struct drm_connector *connector)
|
||||||
|
+intel_dp_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||||
|
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
|
||||||
|
index 227feca..48a1889 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_dvo.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_dvo.c
|
||||||
|
@@ -211,7 +211,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
|
||||||
|
*
|
||||||
|
* Unimplemented.
|
||||||
|
*/
|
||||||
|
-static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+intel_dvo_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||||
|
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
|
||||||
|
index 83bd764..d1decfc 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_hdmi.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
|
||||||
|
@@ -134,7 +134,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
-intel_hdmi_detect(struct drm_connector *connector)
|
||||||
|
+intel_hdmi_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||||
|
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
|
||||||
|
index 7d42ff1..9ad3425 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_lvds.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_lvds.c
|
||||||
|
@@ -546,7 +546,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
||||||
|
* connected and closed means disconnected. We also send hotplug events as
|
||||||
|
* needed, using lid status notification from the input layer.
|
||||||
|
*/
|
||||||
|
-static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+intel_lvds_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
enum drm_connector_status status = connector_status_connected;
|
||||||
|
@@ -641,7 +642,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
|
||||||
|
* the LID nofication event.
|
||||||
|
*/
|
||||||
|
if (connector)
|
||||||
|
- connector->status = connector->funcs->detect(connector);
|
||||||
|
+ connector->status = connector->funcs->detect(connector,
|
||||||
|
+ false);
|
||||||
|
+
|
||||||
|
/* Don't force modeset on machines where it causes a GPU lockup */
|
||||||
|
if (dmi_check_system(intel_no_modeset_on_lid))
|
||||||
|
return NOTIFY_OK;
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
|
||||||
|
index 76993ac..76c9b3d 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_sdvo.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
|
||||||
|
@@ -1496,7 +1496,7 @@ intel_analog_is_connected(struct drm_device *dev)
|
||||||
|
if (!analog_connector)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
- if (analog_connector->funcs->detect(analog_connector) ==
|
||||||
|
+ if (analog_connector->funcs->detect(analog_connector, false) ==
|
||||||
|
connector_status_disconnected)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
@@ -1567,7 +1567,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+intel_sdvo_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
uint16_t response;
|
||||||
|
u8 status;
|
||||||
|
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
|
||||||
|
index 6d553c2..ad40f1b 100644
|
||||||
|
--- a/drivers/gpu/drm/i915/intel_tv.c
|
||||||
|
+++ b/drivers/gpu/drm/i915/intel_tv.c
|
||||||
|
@@ -1336,7 +1336,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
|
||||||
|
* we have a pipe programmed in order to probe the TV.
|
||||||
|
*/
|
||||||
|
static enum drm_connector_status
|
||||||
|
-intel_tv_detect(struct drm_connector *connector)
|
||||||
|
+intel_tv_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_crtc *crtc;
|
||||||
|
struct drm_display_mode mode;
|
||||||
|
@@ -1351,7 +1351,7 @@ intel_tv_detect(struct drm_connector *connector)
|
||||||
|
|
||||||
|
if (encoder->crtc && encoder->crtc->enabled) {
|
||||||
|
type = intel_tv_detect_type(encoder->crtc, intel_encoder);
|
||||||
|
- } else {
|
||||||
|
+ } else if (force) {
|
||||||
|
crtc = intel_get_load_detect_pipe(intel_encoder, connector,
|
||||||
|
&mode, &dpms_mode);
|
||||||
|
if (crtc) {
|
||||||
|
@@ -1359,8 +1359,9 @@ intel_tv_detect(struct drm_connector *connector)
|
||||||
|
intel_release_load_detect_pipe(intel_encoder, connector,
|
||||||
|
dpms_mode);
|
||||||
|
} else
|
||||||
|
- type = -1;
|
||||||
|
- }
|
||||||
|
+ return connector_status_unknown;
|
||||||
|
+ } else
|
||||||
|
+ return connector->status;
|
||||||
|
|
||||||
|
tv_priv->type = type;
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
index 149ed22..1085376 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
||||||
|
@@ -228,7 +228,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
-nouveau_connector_detect(struct drm_connector *connector)
|
||||||
|
+nouveau_connector_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||||
|
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
||||||
|
index adccbc2..1680600 100644
|
||||||
|
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
||||||
|
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
||||||
|
@@ -467,7 +467,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
|
||||||
|
return MODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+radeon_lvds_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||||
|
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||||
|
@@ -582,7 +583,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector,
|
||||||
|
return MODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+radeon_vga_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
@@ -621,6 +623,11 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
|
||||||
|
ret = connector_status_connected;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
+
|
||||||
|
+ /* if we aren't forcing don't do destructive polling */
|
||||||
|
+ if (!force)
|
||||||
|
+ return connector->status;
|
||||||
|
+
|
||||||
|
if (radeon_connector->dac_load_detect && encoder) {
|
||||||
|
encoder_funcs = encoder->helper_private;
|
||||||
|
ret = encoder_funcs->detect(encoder, connector);
|
||||||
|
@@ -679,7 +686,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector,
|
||||||
|
return MODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+radeon_tv_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||||
|
@@ -736,7 +744,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
|
||||||
|
* we have to check if this analog encoder is shared with anyone else (TV)
|
||||||
|
* if its shared we have to set the other connector to disconnected.
|
||||||
|
*/
|
||||||
|
-static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||||
|
struct drm_encoder *encoder = NULL;
|
||||||
|
@@ -806,6 +815,11 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
|
||||||
|
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
+ if (!force) {
|
||||||
|
+ ret = connector->status;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* find analog encoder */
|
||||||
|
if (radeon_connector->dac_load_detect) {
|
||||||
|
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||||
|
@@ -962,7 +976,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector)
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||||
|
{
|
||||||
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||||
|
enum drm_connector_status ret = connector_status_disconnected;
|
||||||
|
@@ -1082,6 +1097,8 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.load_detect_property,
|
||||||
|
1);
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||||
|
connector->interlace_allowed = true;
|
||||||
|
connector->doublescan_allowed = true;
|
||||||
|
@@ -1096,6 +1113,8 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.load_detect_property,
|
||||||
|
1);
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
connector->interlace_allowed = true;
|
||||||
|
connector->doublescan_allowed = true;
|
||||||
|
break;
|
||||||
|
@@ -1186,6 +1205,8 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.tv_std_property,
|
||||||
|
radeon_atombios_get_tv_info(rdev));
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
}
|
||||||
|
connector->interlace_allowed = false;
|
||||||
|
connector->doublescan_allowed = false;
|
||||||
|
@@ -1209,7 +1230,7 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (hpd->hpd == RADEON_HPD_NONE) {
|
||||||
|
+ if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
|
||||||
|
if (i2c_bus->valid)
|
||||||
|
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||||
|
} else
|
||||||
|
@@ -1276,6 +1297,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.load_detect_property,
|
||||||
|
1);
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||||
|
connector->interlace_allowed = true;
|
||||||
|
connector->doublescan_allowed = true;
|
||||||
|
@@ -1290,6 +1313,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.load_detect_property,
|
||||||
|
1);
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
connector->interlace_allowed = true;
|
||||||
|
connector->doublescan_allowed = true;
|
||||||
|
break;
|
||||||
|
@@ -1328,6 +1353,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||||
|
drm_connector_attach_property(&radeon_connector->base,
|
||||||
|
rdev->mode_info.tv_std_property,
|
||||||
|
radeon_combios_get_tv_info(rdev));
|
||||||
|
+ /* no HPD on analog connectors */
|
||||||
|
+ radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||||
|
}
|
||||||
|
connector->interlace_allowed = false;
|
||||||
|
connector->doublescan_allowed = false;
|
||||||
|
@@ -1345,7 +1372,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (hpd->hpd == RADEON_HPD_NONE) {
|
||||||
|
+ if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
|
||||||
|
if (i2c_bus->valid)
|
||||||
|
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||||
|
} else
|
||||||
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||||
|
index cfaf690..5b638cb 100644
|
||||||
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||||
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||||
|
@@ -335,7 +335,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
- vmw_ldu_connector_detect(struct drm_connector *connector)
|
||||||
|
+ vmw_ldu_connector_detect(struct drm_connector *connector,
|
||||||
|
+ bool force)
|
||||||
|
{
|
||||||
|
if (vmw_connector_to_ldu(connector)->pref_active)
|
||||||
|
return connector_status_connected;
|
||||||
|
@@ -516,7 +517,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
|
||||||
|
|
||||||
|
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
|
||||||
|
DRM_MODE_CONNECTOR_LVDS);
|
||||||
|
- connector->status = vmw_ldu_connector_detect(connector);
|
||||||
|
+ connector->status = vmw_ldu_connector_detect(connector, true);
|
||||||
|
|
||||||
|
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
|
||||||
|
DRM_MODE_ENCODER_LVDS);
|
||||||
|
@@ -610,7 +611,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
|
||||||
|
ldu->pref_height = 600;
|
||||||
|
ldu->pref_active = false;
|
||||||
|
}
|
||||||
|
- con->status = vmw_ldu_connector_detect(con);
|
||||||
|
+ con->status = vmw_ldu_connector_detect(con, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
|
||||||
|
index 93a1a31..afbb578 100644
|
||||||
|
--- a/include/drm/drm_crtc.h
|
||||||
|
+++ b/include/drm/drm_crtc.h
|
||||||
|
@@ -420,7 +420,15 @@ struct drm_connector_funcs {
|
||||||
|
void (*dpms)(struct drm_connector *connector, int mode);
|
||||||
|
void (*save)(struct drm_connector *connector);
|
||||||
|
void (*restore)(struct drm_connector *connector);
|
||||||
|
- enum drm_connector_status (*detect)(struct drm_connector *connector);
|
||||||
|
+
|
||||||
|
+ /* Check to see if anything is attached to the connector.
|
||||||
|
+ * @force is set to false whilst polling, true when checking the
|
||||||
|
+ * connector due to user request. @force can be used by the driver
|
||||||
|
+ * to avoid expensive, destructive operations during automated
|
||||||
|
+ * probing.
|
||||||
|
+ */
|
||||||
|
+ enum drm_connector_status (*detect)(struct drm_connector *connector,
|
||||||
|
+ bool force);
|
||||||
|
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
|
||||||
|
int (*set_property)(struct drm_connector *connector, struct drm_property *property,
|
||||||
|
uint64_t val);
|
|
@ -0,0 +1,854 @@
|
||||||
|
commit 4adf332cc24ee2d46064aaafd8216169d29566d5
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Sun Nov 14 20:24:35 2010 -0500
|
||||||
|
|
||||||
|
drm/radeon/kms: fix and unify tiled buffer alignment checking for r6xx/7xx
|
||||||
|
|
||||||
|
Tiled buffers have the same alignment requirements regardless of
|
||||||
|
whether the surface is for db, cb, or textures. Previously, the
|
||||||
|
calculations where inconsistent for each buffer type.
|
||||||
|
|
||||||
|
- Unify the alignment calculations in a common function
|
||||||
|
- Standardize the alignment units (pixels for pitch/height/depth,
|
||||||
|
bytes for base)
|
||||||
|
- properly check the buffer base alignments
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit c37cb9e61dce7437f63280d9347a9ffdf4ec34e7
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Wed Oct 27 01:44:35 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: fix tiled db height calculation on 6xx/7xx
|
||||||
|
|
||||||
|
Calculate height based on the slice bitfield rather than the size.
|
||||||
|
Same as Dave's CB fix.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit b80c8fdc2fadd8182b958e91a10f2fa287f993e4
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Tue Oct 26 20:22:42 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: fix r6xx/7xx 1D tiling CS checker v2
|
||||||
|
|
||||||
|
broken by:
|
||||||
|
drm/radeon/r600: fix tiling issues in CS checker.
|
||||||
|
|
||||||
|
v2: only apply it to 1D tiling case.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 4336ac5c0a4e5dfbb51631ad680d6a5d0b295cd3
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Mon Oct 18 23:45:39 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: fix 2D tile height alignment in the r600 CS checker
|
||||||
|
|
||||||
|
macro tile heights are aligned to num channels, not num banks.
|
||||||
|
|
||||||
|
Noticed by Dave Airlie.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Cc: stable@kernel.org
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 5c76976a1419a633f9f33c6547bae00348b855d2
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Thu Oct 21 13:55:40 2010 +1000
|
||||||
|
|
||||||
|
drm/radeon/r600: fix tiling issues in CS checker.
|
||||||
|
|
||||||
|
The CS checker had some incorrect alignment requirements for 2D surfaces,
|
||||||
|
this made rendering to mipmap levels that were 2D broken.
|
||||||
|
|
||||||
|
Also the CB height was being worked out from the BO size, this doesn't work
|
||||||
|
at all when rendering mipmap levels, instead we work out what height userspace
|
||||||
|
wanted from slice max and use that to check it fits inside the BO, however
|
||||||
|
the DDX send the wrong slice max for an unaligned buffer so we have to workaround
|
||||||
|
for that even though its a userspace bug.
|
||||||
|
|
||||||
|
Reviewed-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit fa479e9df4558af6f091c45be37f713e64b836a1
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Tue Sep 14 10:10:47 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: only warn on mipmap size checks in r600 cs checker (v2)
|
||||||
|
|
||||||
|
The texture base address registers are in units of 256 bytes.
|
||||||
|
The original CS checker treated these offsets as bytes, so the
|
||||||
|
original check was wrong. I fixed the units in a patch during
|
||||||
|
the 2.6.36 cycle, but this ended up breaking some existing
|
||||||
|
userspace (probably due to a bug in either userspace texture allocation
|
||||||
|
or the drm texture mipmap checker). So for now, until we come
|
||||||
|
up with a better fix, just warn if the mipmap size it too large.
|
||||||
|
This will keep existing userspace working and it should be just
|
||||||
|
as safe as before when we were checking the wrong units. These
|
||||||
|
are GPU MC addresses, so if they fall outside of the VRAM or
|
||||||
|
GART apertures, they end up at the GPU default page, so this should
|
||||||
|
be safe from a security perspective.
|
||||||
|
|
||||||
|
v2: Just disable the warning. It just spams the log and there's
|
||||||
|
nothing the user can do about it.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Cc: Jerome Glisse <glisse@freedesktop.org>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 6e8df81d43d5c95fe37db7f0ef55332de1a4b698
|
||||||
|
Author: Dave Airlie <airlied@redhat.com>
|
||||||
|
Date: Thu Aug 12 09:40:05 2010 +1000
|
||||||
|
|
||||||
|
drm/radeon: drop old and broken mesa warning
|
||||||
|
|
||||||
|
This never really got fixed in mesa, and the kernel deals with the problem
|
||||||
|
just fine, so don't got reporting things that confuse people.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 23f012fb9a0633f2f8901440e314d6276255b1c0
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Wed Aug 11 11:54:25 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: another r6xx/r7xx CS checker fix
|
||||||
|
|
||||||
|
add default case for buffer formats
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Cc: Andre Maasikas <amaasikas@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 2c7e76decda2d437f0ca064fef1a2d5d8892288e
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Fri Aug 6 02:54:05 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: r600 CS parser fixes
|
||||||
|
|
||||||
|
- buffer offsets in the base regs are 256b aligned so
|
||||||
|
shift properly when comparing, fixed by Andre Maasikas
|
||||||
|
- mipmap size was calculated wrong when nlevel=0
|
||||||
|
- texture bo offsets were used after the bo base address was added
|
||||||
|
- vertex resource size register is size - 1, not size
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Cc: Andre Maasikas <amaasikas@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit 85d1363c9f15b5d4303b635142cee0ba9d1473fc
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Fri Jun 4 18:41:42 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: fix CS alignment checking for tiling (v2)
|
||||||
|
|
||||||
|
Covers depth, cb, and textures. Hopefully I got this right.
|
||||||
|
|
||||||
|
v2: - fix bugs:
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=28327
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=28381
|
||||||
|
- use ALIGNED(), IS_ALIGNED() macros
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
commit b956b6e7c7fb207daf32520c0a72c8c06ef1d5f5
|
||||||
|
Author: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Date: Thu May 20 12:43:52 2010 -0400
|
||||||
|
|
||||||
|
drm/radeon/kms: add tiling support to the cs checker for r6xx/r7xx
|
||||||
|
|
||||||
|
Check for relocs for DB_DEPTH_INFO, CB_COLOR*_INFO, and texture
|
||||||
|
resources.
|
||||||
|
|
||||||
|
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
|
||||||
|
drivers/gpu/drm/radeon/r600_cs.c | 391 ++++++++++++++++++++++++++++++--------
|
||||||
|
drivers/gpu/drm/radeon/r600d.h | 12 ++
|
||||||
|
2 files changed, 324 insertions(+), 79 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
|
||||||
|
index 144c32d..0f90fc3 100644
|
||||||
|
--- a/drivers/gpu/drm/radeon/r600_cs.c
|
||||||
|
+++ b/drivers/gpu/drm/radeon/r600_cs.c
|
||||||
|
@@ -25,6 +25,7 @@
|
||||||
|
* Alex Deucher
|
||||||
|
* Jerome Glisse
|
||||||
|
*/
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
#include "drmP.h"
|
||||||
|
#include "radeon.h"
|
||||||
|
#include "r600d.h"
|
||||||
|
@@ -49,6 +50,7 @@ struct r600_cs_track {
|
||||||
|
u32 nsamples;
|
||||||
|
u32 cb_color_base_last[8];
|
||||||
|
struct radeon_bo *cb_color_bo[8];
|
||||||
|
+ u64 cb_color_bo_mc[8];
|
||||||
|
u32 cb_color_bo_offset[8];
|
||||||
|
struct radeon_bo *cb_color_frag_bo[8];
|
||||||
|
struct radeon_bo *cb_color_tile_bo[8];
|
||||||
|
@@ -66,6 +68,7 @@ struct r600_cs_track {
|
||||||
|
u32 db_depth_size;
|
||||||
|
u32 db_offset;
|
||||||
|
struct radeon_bo *db_bo;
|
||||||
|
+ u64 db_bo_mc;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int r600_bpe_from_format(u32 *bpe, u32 format)
|
||||||
|
@@ -132,12 +135,75 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format)
|
||||||
|
case V_038004_FMT_GB_GR:
|
||||||
|
case V_038004_FMT_BG_RG:
|
||||||
|
case V_038004_COLOR_INVALID:
|
||||||
|
+ default:
|
||||||
|
*bpe = 16;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct array_mode_checker {
|
||||||
|
+ int array_mode;
|
||||||
|
+ u32 group_size;
|
||||||
|
+ u32 nbanks;
|
||||||
|
+ u32 npipes;
|
||||||
|
+ u32 nsamples;
|
||||||
|
+ u32 bpe;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* returns alignment in pixels for pitch/height/depth and bytes for base */
|
||||||
|
+static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
|
||||||
|
+ u32 *pitch_align,
|
||||||
|
+ u32 *height_align,
|
||||||
|
+ u32 *depth_align,
|
||||||
|
+ u64 *base_align)
|
||||||
|
+{
|
||||||
|
+ u32 tile_width = 8;
|
||||||
|
+ u32 tile_height = 8;
|
||||||
|
+ u32 macro_tile_width = values->nbanks;
|
||||||
|
+ u32 macro_tile_height = values->npipes;
|
||||||
|
+ u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples;
|
||||||
|
+ u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
|
||||||
|
+
|
||||||
|
+ switch (values->array_mode) {
|
||||||
|
+ case ARRAY_LINEAR_GENERAL:
|
||||||
|
+ /* technically tile_width/_height for pitch/height */
|
||||||
|
+ *pitch_align = 1; /* tile_width */
|
||||||
|
+ *height_align = 1; /* tile_height */
|
||||||
|
+ *depth_align = 1;
|
||||||
|
+ *base_align = 1;
|
||||||
|
+ break;
|
||||||
|
+ case ARRAY_LINEAR_ALIGNED:
|
||||||
|
+ *pitch_align = max((u32)64, (u32)(values->group_size / values->bpe));
|
||||||
|
+ *height_align = tile_height;
|
||||||
|
+ *depth_align = 1;
|
||||||
|
+ *base_align = values->group_size;
|
||||||
|
+ break;
|
||||||
|
+ case ARRAY_1D_TILED_THIN1:
|
||||||
|
+ *pitch_align = max((u32)tile_width,
|
||||||
|
+ (u32)(values->group_size /
|
||||||
|
+ (tile_height * values->bpe * values->nsamples)));
|
||||||
|
+ *height_align = tile_height;
|
||||||
|
+ *depth_align = 1;
|
||||||
|
+ *base_align = values->group_size;
|
||||||
|
+ break;
|
||||||
|
+ case ARRAY_2D_TILED_THIN1:
|
||||||
|
+ *pitch_align = max((u32)macro_tile_width,
|
||||||
|
+ (u32)(((values->group_size / tile_height) /
|
||||||
|
+ (values->bpe * values->nsamples)) *
|
||||||
|
+ values->nbanks)) * tile_width;
|
||||||
|
+ *height_align = macro_tile_height * tile_height;
|
||||||
|
+ *depth_align = 1;
|
||||||
|
+ *base_align = max(macro_tile_bytes,
|
||||||
|
+ (*pitch_align) * values->bpe * (*height_align) * values->nsamples);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void r600_cs_track_init(struct r600_cs_track *track)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
@@ -151,10 +217,12 @@ static void r600_cs_track_init(struct r600_cs_track *track)
|
||||||
|
track->cb_color_info[i] = 0;
|
||||||
|
track->cb_color_bo[i] = NULL;
|
||||||
|
track->cb_color_bo_offset[i] = 0xFFFFFFFF;
|
||||||
|
+ track->cb_color_bo_mc[i] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
track->cb_target_mask = 0xFFFFFFFF;
|
||||||
|
track->cb_shader_mask = 0xFFFFFFFF;
|
||||||
|
track->db_bo = NULL;
|
||||||
|
+ track->db_bo_mc = 0xFFFFFFFF;
|
||||||
|
/* assume the biggest format and that htile is enabled */
|
||||||
|
track->db_depth_info = 7 | (1 << 25);
|
||||||
|
track->db_depth_view = 0xFFFFC000;
|
||||||
|
@@ -166,70 +234,58 @@ static void r600_cs_track_init(struct r600_cs_track *track)
|
||||||
|
static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
|
||||||
|
{
|
||||||
|
struct r600_cs_track *track = p->track;
|
||||||
|
- u32 bpe = 0, pitch, slice_tile_max, size, tmp, height;
|
||||||
|
+ u32 bpe = 0, slice_tile_max, size, tmp;
|
||||||
|
+ u32 height, height_align, pitch, pitch_align, depth_align;
|
||||||
|
+ u64 base_offset, base_align;
|
||||||
|
+ struct array_mode_checker array_check;
|
||||||
|
volatile u32 *ib = p->ib->ptr;
|
||||||
|
+ unsigned array_mode;
|
||||||
|
|
||||||
|
if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
|
||||||
|
dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- size = radeon_bo_size(track->cb_color_bo[i]);
|
||||||
|
+ size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
|
||||||
|
if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
|
||||||
|
dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
|
||||||
|
__func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
|
||||||
|
i, track->cb_color_info[i]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) << 3;
|
||||||
|
+ /* pitch in pixels */
|
||||||
|
+ pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
|
||||||
|
slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
|
||||||
|
- if (!pitch) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d) for %d invalid (0x%08X)\n",
|
||||||
|
- __func__, __LINE__, pitch, i, track->cb_color_size[i]);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
- height = size / (pitch * bpe);
|
||||||
|
+ slice_tile_max *= 64;
|
||||||
|
+ height = slice_tile_max / pitch;
|
||||||
|
if (height > 8192)
|
||||||
|
height = 8192;
|
||||||
|
- switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
|
||||||
|
+ array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
|
||||||
|
+
|
||||||
|
+ base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
|
||||||
|
+ array_check.array_mode = array_mode;
|
||||||
|
+ array_check.group_size = track->group_size;
|
||||||
|
+ array_check.nbanks = track->nbanks;
|
||||||
|
+ array_check.npipes = track->npipes;
|
||||||
|
+ array_check.nsamples = track->nsamples;
|
||||||
|
+ array_check.bpe = bpe;
|
||||||
|
+ if (r600_get_array_mode_alignment(&array_check,
|
||||||
|
+ &pitch_align, &height_align, &depth_align, &base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
|
||||||
|
+ G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
|
||||||
|
+ track->cb_color_info[i]);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ switch (array_mode) {
|
||||||
|
case V_0280A0_ARRAY_LINEAR_GENERAL:
|
||||||
|
+ break;
|
||||||
|
case V_0280A0_ARRAY_LINEAR_ALIGNED:
|
||||||
|
- if (pitch & 0x3f) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d x %d = %d) invalid\n",
|
||||||
|
- __func__, __LINE__, pitch, bpe, pitch * bpe);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
- if ((pitch * bpe) & (track->group_size - 1)) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||||
|
- __func__, __LINE__, pitch);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
break;
|
||||||
|
case V_0280A0_ARRAY_1D_TILED_THIN1:
|
||||||
|
- if ((pitch * 8 * bpe * track->nsamples) & (track->group_size - 1)) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||||
|
- __func__, __LINE__, pitch);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
- height &= ~0x7;
|
||||||
|
- if (!height)
|
||||||
|
- height = 8;
|
||||||
|
+ /* avoid breaking userspace */
|
||||||
|
+ if (height > 7)
|
||||||
|
+ height &= ~0x7;
|
||||||
|
break;
|
||||||
|
case V_0280A0_ARRAY_2D_TILED_THIN1:
|
||||||
|
- if (pitch & ((8 * track->nbanks) - 1)) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||||
|
- __func__, __LINE__, pitch);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
- tmp = pitch * 8 * bpe * track->nsamples;
|
||||||
|
- tmp = tmp / track->nbanks;
|
||||||
|
- if (tmp & (track->group_size - 1)) {
|
||||||
|
- dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||||
|
- __func__, __LINE__, pitch);
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
- height &= ~((16 * track->npipes) - 1);
|
||||||
|
- if (!height)
|
||||||
|
- height = 16 * track->npipes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
|
||||||
|
@@ -237,17 +293,43 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
|
||||||
|
track->cb_color_info[i]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (!IS_ALIGNED(pitch, pitch_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, pitch);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(height, height_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, height);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(base_offset, base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* check offset */
|
||||||
|
- tmp = height * pitch;
|
||||||
|
+ tmp = height * pitch * bpe;
|
||||||
|
if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
|
||||||
|
- dev_warn(p->dev, "%s offset[%d] %d to big\n", __func__, i, track->cb_color_bo_offset[i]);
|
||||||
|
- return -EINVAL;
|
||||||
|
+ if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
|
||||||
|
+ /* the initial DDX does bad things with the CB size occasionally */
|
||||||
|
+ /* it rounds up height too far for slice tile max but the BO is smaller */
|
||||||
|
+ tmp = (height - 7) * 8 * bpe;
|
||||||
|
+ if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
|
||||||
|
+ dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
/* limit max tile */
|
||||||
|
tmp = (height * pitch) >> 6;
|
||||||
|
if (tmp < slice_tile_max)
|
||||||
|
slice_tile_max = tmp;
|
||||||
|
- tmp = S_028060_PITCH_TILE_MAX((pitch >> 3) - 1) |
|
||||||
|
+ tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
|
||||||
|
S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
|
||||||
|
ib[track->cb_color_size_idx[i]] = tmp;
|
||||||
|
return 0;
|
||||||
|
@@ -289,7 +371,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
|
||||||
|
/* Check depth buffer */
|
||||||
|
if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
|
||||||
|
G_028800_Z_ENABLE(track->db_depth_control)) {
|
||||||
|
- u32 nviews, bpe, ntiles;
|
||||||
|
+ u32 nviews, bpe, ntiles, size, slice_tile_max;
|
||||||
|
+ u32 height, height_align, pitch, pitch_align, depth_align;
|
||||||
|
+ u64 base_offset, base_align;
|
||||||
|
+ struct array_mode_checker array_check;
|
||||||
|
+ int array_mode;
|
||||||
|
+
|
||||||
|
if (track->db_bo == NULL) {
|
||||||
|
dev_warn(p->dev, "z/stencil with no depth buffer\n");
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -321,7 +408,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
|
||||||
|
dev_warn(p->dev, "z/stencil buffer size not set\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n");
|
||||||
|
tmp = radeon_bo_size(track->db_bo) - track->db_offset;
|
||||||
|
tmp = (tmp / bpe) >> 6;
|
||||||
|
if (!tmp) {
|
||||||
|
@@ -332,11 +418,63 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
|
||||||
|
}
|
||||||
|
ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
|
||||||
|
} else {
|
||||||
|
+ size = radeon_bo_size(track->db_bo);
|
||||||
|
+ /* pitch in pixels */
|
||||||
|
+ pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
|
||||||
|
+ slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
|
||||||
|
+ slice_tile_max *= 64;
|
||||||
|
+ height = slice_tile_max / pitch;
|
||||||
|
+ if (height > 8192)
|
||||||
|
+ height = 8192;
|
||||||
|
+ base_offset = track->db_bo_mc + track->db_offset;
|
||||||
|
+ array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
|
||||||
|
+ array_check.array_mode = array_mode;
|
||||||
|
+ array_check.group_size = track->group_size;
|
||||||
|
+ array_check.nbanks = track->nbanks;
|
||||||
|
+ array_check.npipes = track->npipes;
|
||||||
|
+ array_check.nsamples = track->nsamples;
|
||||||
|
+ array_check.bpe = bpe;
|
||||||
|
+ if (r600_get_array_mode_alignment(&array_check,
|
||||||
|
+ &pitch_align, &height_align, &depth_align, &base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
|
||||||
|
+ G_028010_ARRAY_MODE(track->db_depth_info),
|
||||||
|
+ track->db_depth_info);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ switch (array_mode) {
|
||||||
|
+ case V_028010_ARRAY_1D_TILED_THIN1:
|
||||||
|
+ /* don't break userspace */
|
||||||
|
+ height &= ~0x7;
|
||||||
|
+ break;
|
||||||
|
+ case V_028010_ARRAY_2D_TILED_THIN1:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
|
||||||
|
+ G_028010_ARRAY_MODE(track->db_depth_info),
|
||||||
|
+ track->db_depth_info);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!IS_ALIGNED(pitch, pitch_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, pitch);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(height, height_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, height);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(base_offset, base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
|
||||||
|
nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
|
||||||
|
tmp = ntiles * bpe * 64 * nviews;
|
||||||
|
if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
|
||||||
|
- dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n",
|
||||||
|
+ dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %u have %lu)\n",
|
||||||
|
track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
|
||||||
|
radeon_bo_size(track->db_bo));
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -724,7 +862,25 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
track->db_depth_control = radeon_get_ib_value(p, idx);
|
||||||
|
break;
|
||||||
|
case R_028010_DB_DEPTH_INFO:
|
||||||
|
- track->db_depth_info = radeon_get_ib_value(p, idx);
|
||||||
|
+ if (r600_cs_packet_next_is_pkt3_nop(p)) {
|
||||||
|
+ r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
+ if (r) {
|
||||||
|
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
|
||||||
|
+ "0x%04X\n", reg);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ track->db_depth_info = radeon_get_ib_value(p, idx);
|
||||||
|
+ ib[idx] &= C_028010_ARRAY_MODE;
|
||||||
|
+ track->db_depth_info &= C_028010_ARRAY_MODE;
|
||||||
|
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
|
||||||
|
+ ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ } else {
|
||||||
|
+ ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
|
||||||
|
+ track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
|
||||||
|
+ }
|
||||||
|
+ } else
|
||||||
|
+ track->db_depth_info = radeon_get_ib_value(p, idx);
|
||||||
|
break;
|
||||||
|
case R_028004_DB_DEPTH_VIEW:
|
||||||
|
track->db_depth_view = radeon_get_ib_value(p, idx);
|
||||||
|
@@ -757,8 +913,25 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
case R_0280B4_CB_COLOR5_INFO:
|
||||||
|
case R_0280B8_CB_COLOR6_INFO:
|
||||||
|
case R_0280BC_CB_COLOR7_INFO:
|
||||||
|
- tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
|
||||||
|
- track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
|
||||||
|
+ if (r600_cs_packet_next_is_pkt3_nop(p)) {
|
||||||
|
+ r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
+ if (r) {
|
||||||
|
+ dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
|
||||||
|
+ track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
|
||||||
|
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
|
||||||
|
+ ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
|
||||||
|
+ ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
|
||||||
|
+ track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
|
||||||
|
+ track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
case R_028060_CB_COLOR0_SIZE:
|
||||||
|
case R_028064_CB_COLOR1_SIZE:
|
||||||
|
@@ -796,8 +969,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ib[idx] = track->cb_color_base_last[tmp];
|
||||||
|
- printk_once(KERN_WARNING "You have old & broken userspace "
|
||||||
|
- "please consider updating mesa & xf86-video-ati\n");
|
||||||
|
track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
|
||||||
|
} else {
|
||||||
|
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
@@ -824,8 +995,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ib[idx] = track->cb_color_base_last[tmp];
|
||||||
|
- printk_once(KERN_WARNING "You have old & broken userspace "
|
||||||
|
- "please consider updating mesa & xf86-video-ati\n");
|
||||||
|
track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
|
||||||
|
} else {
|
||||||
|
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
@@ -852,10 +1021,11 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
tmp = (reg - CB_COLOR0_BASE) / 4;
|
||||||
|
- track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
|
||||||
|
+ track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
|
||||||
|
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
track->cb_color_base_last[tmp] = ib[idx];
|
||||||
|
track->cb_color_bo[tmp] = reloc->robj;
|
||||||
|
+ track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset;
|
||||||
|
break;
|
||||||
|
case DB_DEPTH_BASE:
|
||||||
|
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
@@ -864,9 +1034,10 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
|
||||||
|
"0x%04X\n", reg);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- track->db_offset = radeon_get_ib_value(p, idx);
|
||||||
|
+ track->db_offset = radeon_get_ib_value(p, idx) << 8;
|
||||||
|
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
track->db_bo = reloc->robj;
|
||||||
|
+ track->db_bo_mc = reloc->lobj.gpu_offset;
|
||||||
|
break;
|
||||||
|
case DB_HTILE_DATA_BASE:
|
||||||
|
case SQ_PGM_START_FS:
|
||||||
|
@@ -946,8 +1117,9 @@ static inline unsigned minify(unsigned size, unsigned levels)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
|
||||||
|
- unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
|
||||||
|
- unsigned *l0_size, unsigned *mipmap_size)
|
||||||
|
+ unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
|
||||||
|
+ unsigned pitch_align,
|
||||||
|
+ unsigned *l0_size, unsigned *mipmap_size)
|
||||||
|
{
|
||||||
|
unsigned offset, i, level, face;
|
||||||
|
unsigned width, height, depth, rowstride, size;
|
||||||
|
@@ -960,18 +1132,18 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels
|
||||||
|
height = minify(h0, i);
|
||||||
|
depth = minify(d0, i);
|
||||||
|
for(face = 0; face < nfaces; face++) {
|
||||||
|
- rowstride = ((width * bpe) + 255) & ~255;
|
||||||
|
+ rowstride = ALIGN((width * bpe), pitch_align);
|
||||||
|
size = height * rowstride * depth;
|
||||||
|
offset += size;
|
||||||
|
offset = (offset + 0x1f) & ~0x1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- *l0_size = (((w0 * bpe) + 255) & ~255) * h0 * d0;
|
||||||
|
+ *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0;
|
||||||
|
*mipmap_size = offset;
|
||||||
|
- if (!blevel)
|
||||||
|
- *mipmap_size -= *l0_size;
|
||||||
|
if (!nlevels)
|
||||||
|
*mipmap_size = *l0_size;
|
||||||
|
+ if (!blevel)
|
||||||
|
+ *mipmap_size -= *l0_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -985,16 +1157,32 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels
|
||||||
|
* the texture and mipmap bo object are big enough to cover this resource.
|
||||||
|
*/
|
||||||
|
static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
|
||||||
|
- struct radeon_bo *texture,
|
||||||
|
- struct radeon_bo *mipmap)
|
||||||
|
+ struct radeon_bo *texture,
|
||||||
|
+ struct radeon_bo *mipmap,
|
||||||
|
+ u64 base_offset,
|
||||||
|
+ u64 mip_offset,
|
||||||
|
+ u32 tiling_flags)
|
||||||
|
{
|
||||||
|
+ struct r600_cs_track *track = p->track;
|
||||||
|
u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
|
||||||
|
u32 word0, word1, l0_size, mipmap_size;
|
||||||
|
+ u32 height_align, pitch, pitch_align, depth_align;
|
||||||
|
+ u64 base_align;
|
||||||
|
+ struct array_mode_checker array_check;
|
||||||
|
|
||||||
|
/* on legacy kernel we don't perform advanced check */
|
||||||
|
if (p->rdev == NULL)
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+ /* convert to bytes */
|
||||||
|
+ base_offset <<= 8;
|
||||||
|
+ mip_offset <<= 8;
|
||||||
|
+
|
||||||
|
word0 = radeon_get_ib_value(p, idx + 0);
|
||||||
|
+ if (tiling_flags & RADEON_TILING_MACRO)
|
||||||
|
+ word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ else if (tiling_flags & RADEON_TILING_MICRO)
|
||||||
|
+ word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
|
||||||
|
word1 = radeon_get_ib_value(p, idx + 1);
|
||||||
|
w0 = G_038000_TEX_WIDTH(word0) + 1;
|
||||||
|
h0 = G_038004_TEX_HEIGHT(word1) + 1;
|
||||||
|
@@ -1021,24 +1209,59 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i
|
||||||
|
__func__, __LINE__, G_038004_DATA_FORMAT(word1));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* pitch in texels */
|
||||||
|
+ pitch = (G_038000_PITCH(word0) + 1) * 8;
|
||||||
|
+ array_check.array_mode = G_038000_TILE_MODE(word0);
|
||||||
|
+ array_check.group_size = track->group_size;
|
||||||
|
+ array_check.nbanks = track->nbanks;
|
||||||
|
+ array_check.npipes = track->npipes;
|
||||||
|
+ array_check.nsamples = 1;
|
||||||
|
+ array_check.bpe = bpe;
|
||||||
|
+ if (r600_get_array_mode_alignment(&array_check,
|
||||||
|
+ &pitch_align, &height_align, &depth_align, &base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, G_038000_TILE_MODE(word0));
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* XXX check height as well... */
|
||||||
|
+
|
||||||
|
+ if (!IS_ALIGNED(pitch, pitch_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
|
||||||
|
+ __func__, __LINE__, pitch);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(base_offset, base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d tex base offset (0x%llx) invalid\n",
|
||||||
|
+ __func__, __LINE__, base_offset);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+ if (!IS_ALIGNED(mip_offset, base_align)) {
|
||||||
|
+ dev_warn(p->dev, "%s:%d tex mip offset (0x%llx) invalid\n",
|
||||||
|
+ __func__, __LINE__, mip_offset);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
word0 = radeon_get_ib_value(p, idx + 4);
|
||||||
|
word1 = radeon_get_ib_value(p, idx + 5);
|
||||||
|
blevel = G_038010_BASE_LEVEL(word0);
|
||||||
|
nlevels = G_038014_LAST_LEVEL(word1);
|
||||||
|
- r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, &l0_size, &mipmap_size);
|
||||||
|
+ r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe,
|
||||||
|
+ (pitch_align * bpe),
|
||||||
|
+ &l0_size, &mipmap_size);
|
||||||
|
/* using get ib will give us the offset into the texture bo */
|
||||||
|
- word0 = radeon_get_ib_value(p, idx + 2);
|
||||||
|
+ word0 = radeon_get_ib_value(p, idx + 2) << 8;
|
||||||
|
if ((l0_size + word0) > radeon_bo_size(texture)) {
|
||||||
|
dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
|
||||||
|
w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* using get ib will give us the offset into the mipmap bo */
|
||||||
|
- word0 = radeon_get_ib_value(p, idx + 3);
|
||||||
|
+ word0 = radeon_get_ib_value(p, idx + 3) << 8;
|
||||||
|
if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
|
||||||
|
- dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
|
||||||
|
- w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
|
||||||
|
- return -EINVAL;
|
||||||
|
+ /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
|
||||||
|
+ w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -1228,7 +1451,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||||
|
}
|
||||||
|
for (i = 0; i < (pkt->count / 7); i++) {
|
||||||
|
struct radeon_bo *texture, *mipmap;
|
||||||
|
- u32 size, offset;
|
||||||
|
+ u32 size, offset, base_offset, mip_offset;
|
||||||
|
|
||||||
|
switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
|
||||||
|
case SQ_TEX_VTX_VALID_TEXTURE:
|
||||||
|
@@ -1238,7 +1461,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||||
|
DRM_ERROR("bad SET_RESOURCE\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
+ base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
|
||||||
|
+ ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
|
||||||
|
+ else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
|
||||||
|
+ ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
|
||||||
|
texture = reloc->robj;
|
||||||
|
/* tex mip base */
|
||||||
|
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||||
|
@@ -1246,12 +1473,17 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||||
|
DRM_ERROR("bad SET_RESOURCE\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
- ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
+ mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||||
|
mipmap = reloc->robj;
|
||||||
|
r = r600_check_texture_resource(p, idx+(i*7)+1,
|
||||||
|
- texture, mipmap);
|
||||||
|
+ texture, mipmap,
|
||||||
|
+ base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
|
||||||
|
+ mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
|
||||||
|
+ reloc->lobj.tiling_flags);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
+ ib[idx+1+(i*7)+2] += base_offset;
|
||||||
|
+ ib[idx+1+(i*7)+3] += mip_offset;
|
||||||
|
break;
|
||||||
|
case SQ_TEX_VTX_VALID_BUFFER:
|
||||||
|
/* vtx base */
|
||||||
|
@@ -1261,10 +1493,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
|
||||||
|
- size = radeon_get_ib_value(p, idx+1+(i*7)+1);
|
||||||
|
+ size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1;
|
||||||
|
if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
|
||||||
|
/* force size to size of the buffer */
|
||||||
|
- dev_warn(p->dev, "vbo resource seems too big for the bo\n");
|
||||||
|
+ dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n",
|
||||||
|
+ size + offset, radeon_bo_size(reloc->robj));
|
||||||
|
ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
|
||||||
|
}
|
||||||
|
ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
|
||||||
|
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
|
||||||
|
index 84bc28e..9577945 100644
|
||||||
|
--- a/drivers/gpu/drm/radeon/r600d.h
|
||||||
|
+++ b/drivers/gpu/drm/radeon/r600d.h
|
||||||
|
@@ -51,6 +51,12 @@
|
||||||
|
#define PTE_READABLE (1 << 5)
|
||||||
|
#define PTE_WRITEABLE (1 << 6)
|
||||||
|
|
||||||
|
+/* tiling bits */
|
||||||
|
+#define ARRAY_LINEAR_GENERAL 0x00000000
|
||||||
|
+#define ARRAY_LINEAR_ALIGNED 0x00000001
|
||||||
|
+#define ARRAY_1D_TILED_THIN1 0x00000002
|
||||||
|
+#define ARRAY_2D_TILED_THIN1 0x00000004
|
||||||
|
+
|
||||||
|
/* Registers */
|
||||||
|
#define ARB_POP 0x2418
|
||||||
|
#define ENABLE_TC128 (1 << 30)
|
||||||
|
@@ -1155,6 +1161,10 @@
|
||||||
|
#define S_038000_TILE_MODE(x) (((x) & 0xF) << 3)
|
||||||
|
#define G_038000_TILE_MODE(x) (((x) >> 3) & 0xF)
|
||||||
|
#define C_038000_TILE_MODE 0xFFFFFF87
|
||||||
|
+#define V_038000_ARRAY_LINEAR_GENERAL 0x00000000
|
||||||
|
+#define V_038000_ARRAY_LINEAR_ALIGNED 0x00000001
|
||||||
|
+#define V_038000_ARRAY_1D_TILED_THIN1 0x00000002
|
||||||
|
+#define V_038000_ARRAY_2D_TILED_THIN1 0x00000004
|
||||||
|
#define S_038000_TILE_TYPE(x) (((x) & 0x1) << 7)
|
||||||
|
#define G_038000_TILE_TYPE(x) (((x) >> 7) & 0x1)
|
||||||
|
#define C_038000_TILE_TYPE 0xFFFFFF7F
|
||||||
|
@@ -1358,6 +1368,8 @@
|
||||||
|
#define S_028010_ARRAY_MODE(x) (((x) & 0xF) << 15)
|
||||||
|
#define G_028010_ARRAY_MODE(x) (((x) >> 15) & 0xF)
|
||||||
|
#define C_028010_ARRAY_MODE 0xFFF87FFF
|
||||||
|
+#define V_028010_ARRAY_1D_TILED_THIN1 0x00000002
|
||||||
|
+#define V_028010_ARRAY_2D_TILED_THIN1 0x00000004
|
||||||
|
#define S_028010_TILE_SURFACE_ENABLE(x) (((x) & 0x1) << 25)
|
||||||
|
#define G_028010_TILE_SURFACE_ENABLE(x) (((x) >> 25) & 0x1)
|
||||||
|
#define C_028010_TILE_SURFACE_ENABLE 0xFDFFFFFF
|
|
@ -1,958 +0,0 @@
|
||||||
From 5b904034b0ab5195d971b139d0c0b67ab21b063c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
|
|
||||||
Date: Mon, 21 Jun 2010 20:33:16 +0100
|
|
||||||
Subject: Revert "drm/fbdev: rework output polling to be back in the core. (v4)"
|
|
||||||
|
|
||||||
This reverts commit eb1f8e4f3be898df808e2dfc131099f5831d491d.
|
|
||||||
|
|
||||||
Conflicts:
|
|
||||||
|
|
||||||
drivers/gpu/drm/drm_crtc_helper.c
|
|
||||||
drivers/gpu/drm/i915/i915_dma.c
|
|
||||||
drivers/gpu/drm/i915/intel_fb.c
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_fbcon.c
|
|
||||||
drivers/gpu/drm/radeon/radeon_fb.c
|
|
||||||
include/drm/drm_crtc_helper.h
|
|
||||||
---
|
|
||||||
drivers/gpu/drm/Kconfig | 2 +-
|
|
||||||
drivers/gpu/drm/drm_crtc_helper.c | 111 ------------------------
|
|
||||||
drivers/gpu/drm/drm_fb_helper.c | 123 +++++++++++++++++++++++----
|
|
||||||
drivers/gpu/drm/i915/i915_dma.c | 1 -
|
|
||||||
drivers/gpu/drm/i915/i915_irq.c | 3 +-
|
|
||||||
drivers/gpu/drm/i915/intel_crt.c | 5 -
|
|
||||||
drivers/gpu/drm/i915/intel_display.c | 2 -
|
|
||||||
drivers/gpu/drm/i915/intel_dp.c | 2 -
|
|
||||||
drivers/gpu/drm/i915/intel_drv.h | 2 +-
|
|
||||||
drivers/gpu/drm/i915/intel_fb.c | 14 ++--
|
|
||||||
drivers/gpu/drm/i915/intel_hdmi.c | 1 -
|
|
||||||
drivers/gpu/drm/i915/intel_sdvo.c | 2 -
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_connector.c | 12 ---
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_display.c | 1 -
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 ++-
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_fbcon.h | 2 +-
|
|
||||||
drivers/gpu/drm/nouveau/nouveau_state.c | 5 +-
|
|
||||||
drivers/gpu/drm/nouveau/nv50_display.c | 2 +-
|
|
||||||
drivers/gpu/drm/radeon/radeon_connectors.c | 13 ---
|
|
||||||
drivers/gpu/drm/radeon/radeon_display.c | 10 --
|
|
||||||
drivers/gpu/drm/radeon/radeon_fb.c | 15 +++-
|
|
||||||
drivers/gpu/drm/radeon/radeon_irq_kms.c | 5 +-
|
|
||||||
drivers/gpu/drm/radeon/radeon_mode.h | 3 +-
|
|
||||||
include/drm/drm_crtc.h | 17 ----
|
|
||||||
include/drm/drm_crtc_helper.h | 6 --
|
|
||||||
include/drm/drm_fb_helper.h | 13 +++-
|
|
||||||
26 files changed, 155 insertions(+), 230 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
|
|
||||||
index c2711c6..a51a1e4 100644
|
|
||||||
--- a/drivers/gpu/drm/Kconfig
|
|
||||||
+++ b/drivers/gpu/drm/Kconfig
|
|
||||||
@@ -9,7 +9,6 @@ menuconfig DRM
|
|
||||||
depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU
|
|
||||||
select I2C
|
|
||||||
select I2C_ALGOBIT
|
|
||||||
- select SLOW_WORK
|
|
||||||
help
|
|
||||||
Kernel-level support for the Direct Rendering Infrastructure (DRI)
|
|
||||||
introduced in XFree86 4.0. If you say Y here, you need to select
|
|
||||||
@@ -24,6 +23,7 @@ config DRM_KMS_HELPER
|
|
||||||
depends on DRM
|
|
||||||
select FB
|
|
||||||
select FRAMEBUFFER_CONSOLE if !EMBEDDED
|
|
||||||
+ select SLOW_WORK
|
|
||||||
help
|
|
||||||
FB and CRTC helpers for KMS drivers.
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
|
|
||||||
index 9b2a541..b142ac2 100644
|
|
||||||
--- a/drivers/gpu/drm/drm_crtc_helper.c
|
|
||||||
+++ b/drivers/gpu/drm/drm_crtc_helper.c
|
|
||||||
@@ -807,114 +807,3 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_helper_resume_force_mode);
|
|
||||||
-
|
|
||||||
-static struct slow_work_ops output_poll_ops;
|
|
||||||
-
|
|
||||||
-#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
|
||||||
-static void output_poll_execute(struct slow_work *work)
|
|
||||||
-{
|
|
||||||
- struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work);
|
|
||||||
- struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_slow_work);
|
|
||||||
- struct drm_connector *connector;
|
|
||||||
- enum drm_connector_status old_status, status;
|
|
||||||
- bool repoll = false, changed = false;
|
|
||||||
- int ret;
|
|
||||||
-
|
|
||||||
- mutex_lock(&dev->mode_config.mutex);
|
|
||||||
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
||||||
-
|
|
||||||
- /* if this is HPD or polled don't check it -
|
|
||||||
- TV out for instance */
|
|
||||||
- if (!connector->polled)
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
|
|
||||||
- repoll = true;
|
|
||||||
-
|
|
||||||
- old_status = connector->status;
|
|
||||||
- /* if we are connected and don't want to poll for disconnect
|
|
||||||
- skip it */
|
|
||||||
- if (old_status == connector_status_connected &&
|
|
||||||
- !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
|
|
||||||
- !(connector->polled & DRM_CONNECTOR_POLL_HPD))
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- status = connector->funcs->detect(connector);
|
|
||||||
- if (old_status != status)
|
|
||||||
- changed = true;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- mutex_unlock(&dev->mode_config.mutex);
|
|
||||||
-
|
|
||||||
- if (changed) {
|
|
||||||
- /* send a uevent + call fbdev */
|
|
||||||
- drm_sysfs_hotplug_event(dev);
|
|
||||||
- if (dev->mode_config.funcs->output_poll_changed)
|
|
||||||
- dev->mode_config.funcs->output_poll_changed(dev);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (repoll) {
|
|
||||||
- ret = delayed_slow_work_enqueue(delayed_work, DRM_OUTPUT_POLL_PERIOD);
|
|
||||||
- if (ret)
|
|
||||||
- DRM_ERROR("delayed enqueue failed %d\n", ret);
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void drm_kms_helper_poll_disable(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- if (!dev->mode_config.poll_enabled)
|
|
||||||
- return;
|
|
||||||
- delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(drm_kms_helper_poll_disable);
|
|
||||||
-
|
|
||||||
-void drm_kms_helper_poll_enable(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- bool poll = false;
|
|
||||||
- struct drm_connector *connector;
|
|
||||||
- int ret;
|
|
||||||
-
|
|
||||||
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
||||||
- if (connector->polled)
|
|
||||||
- poll = true;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (poll) {
|
|
||||||
- ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
|
|
||||||
- if (ret)
|
|
||||||
- DRM_ERROR("delayed enqueue failed %d\n", ret);
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(drm_kms_helper_poll_enable);
|
|
||||||
-
|
|
||||||
-void drm_kms_helper_poll_init(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- slow_work_register_user(THIS_MODULE);
|
|
||||||
- delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
|
|
||||||
- &output_poll_ops);
|
|
||||||
- dev->mode_config.poll_enabled = true;
|
|
||||||
-
|
|
||||||
- drm_kms_helper_poll_enable(dev);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(drm_kms_helper_poll_init);
|
|
||||||
-
|
|
||||||
-void drm_kms_helper_poll_fini(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- drm_kms_helper_poll_disable(dev);
|
|
||||||
- slow_work_unregister_user(THIS_MODULE);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(drm_kms_helper_poll_fini);
|
|
||||||
-
|
|
||||||
-void drm_helper_hpd_irq_event(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- if (!dev->mode_config.poll_enabled)
|
|
||||||
- return;
|
|
||||||
- delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
|
|
||||||
- /* schedule a slow work asap */
|
|
||||||
- delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, 0);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(drm_helper_hpd_irq_event);
|
|
||||||
-
|
|
||||||
-static struct slow_work_ops output_poll_ops = {
|
|
||||||
- .execute = output_poll_execute,
|
|
||||||
-};
|
|
||||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
|
||||||
index 08c4c92..dcc6601 100644
|
|
||||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
|
||||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
|
||||||
@@ -42,6 +42,8 @@ MODULE_LICENSE("GPL and additional rights");
|
|
||||||
|
|
||||||
static LIST_HEAD(kernel_fb_helper_list);
|
|
||||||
|
|
||||||
+static struct slow_work_ops output_status_change_ops;
|
|
||||||
+
|
|
||||||
/* simple single crtc case helper function */
|
|
||||||
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
|
|
||||||
{
|
|
||||||
@@ -423,13 +425,19 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
|
|
||||||
|
|
||||||
int drm_fb_helper_init(struct drm_device *dev,
|
|
||||||
struct drm_fb_helper *fb_helper,
|
|
||||||
- int crtc_count, int max_conn_count)
|
|
||||||
+ int crtc_count, int max_conn_count,
|
|
||||||
+ bool polled)
|
|
||||||
{
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
int ret = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fb_helper->dev = dev;
|
|
||||||
+ fb_helper->poll_enabled = polled;
|
|
||||||
+
|
|
||||||
+ slow_work_register_user(THIS_MODULE);
|
|
||||||
+ delayed_slow_work_init(&fb_helper->output_status_change_slow_work,
|
|
||||||
+ &output_status_change_ops);
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
|
|
||||||
|
|
||||||
@@ -486,6 +494,8 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
|
||||||
|
|
||||||
drm_fb_helper_crtc_free(fb_helper);
|
|
||||||
|
|
||||||
+ delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work);
|
|
||||||
+ slow_work_unregister_user(THIS_MODULE);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_fb_helper_fini);
|
|
||||||
|
|
||||||
@@ -703,7 +713,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
|
|
||||||
|
|
||||||
if (fb_helper->delayed_hotplug) {
|
|
||||||
fb_helper->delayed_hotplug = false;
|
|
||||||
- drm_fb_helper_hotplug_event(fb_helper);
|
|
||||||
+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -816,7 +826,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|
||||||
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
|
||||||
/* hmm everyone went away - assume VGA cable just fell out
|
|
||||||
and will come back later. */
|
|
||||||
- DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
|
|
||||||
+ DRM_ERROR("Cannot find any crtc or sizes - going 1024x768\n");
|
|
||||||
sizes.fb_width = sizes.surface_width = 1024;
|
|
||||||
sizes.fb_height = sizes.surface_height = 768;
|
|
||||||
}
|
|
||||||
@@ -1362,7 +1372,12 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
|
|
||||||
* we shouldn't end up with no modes here.
|
|
||||||
*/
|
|
||||||
if (count == 0) {
|
|
||||||
- printk(KERN_INFO "No connectors reported connected with modes\n");
|
|
||||||
+ if (fb_helper->poll_enabled) {
|
|
||||||
+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work,
|
|
||||||
+ 5*HZ);
|
|
||||||
+ printk(KERN_INFO "No connectors reported connected with modes - started polling\n");
|
|
||||||
+ } else
|
|
||||||
+ printk(KERN_INFO "No connectors reported connected with modes\n");
|
|
||||||
}
|
|
||||||
drm_setup_crtcs(fb_helper);
|
|
||||||
|
|
||||||
@@ -1370,16 +1385,71 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_fb_helper_initial_config);
|
|
||||||
|
|
||||||
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
|
|
||||||
+/* we got a hotplug irq - need to update fbcon */
|
|
||||||
+void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper)
|
|
||||||
+{
|
|
||||||
+ /* if we don't have the fbdev registered yet do nothing */
|
|
||||||
+ if (!fb_helper->fbdev)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* schedule a slow work asap */
|
|
||||||
+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0);
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(drm_helper_fb_hpd_irq_event);
|
|
||||||
+
|
|
||||||
+bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, bool polled)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
+ int ret;
|
|
||||||
u32 max_width, max_height, bpp_sel;
|
|
||||||
- bool bound = false, crtcs_bound = false;
|
|
||||||
- struct drm_crtc *crtc;
|
|
||||||
|
|
||||||
if (!fb_helper->fb)
|
|
||||||
return false;
|
|
||||||
+ DRM_DEBUG_KMS("\n");
|
|
||||||
+
|
|
||||||
+ max_width = fb_helper->fb->width;
|
|
||||||
+ max_height = fb_helper->fb->height;
|
|
||||||
+ bpp_sel = fb_helper->fb->bits_per_pixel;
|
|
||||||
+
|
|
||||||
+ count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
|
|
||||||
+ max_height);
|
|
||||||
+ if (fb_helper->poll_enabled && !polled) {
|
|
||||||
+ if (count) {
|
|
||||||
+ delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work);
|
|
||||||
+ } else {
|
|
||||||
+ ret = delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 5*HZ);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ drm_setup_crtcs(fb_helper);
|
|
||||||
+
|
|
||||||
+ return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(drm_helper_fb_hotplug_event);
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * delayed work queue execution function
|
|
||||||
+ * - check if fbdev is actually in use on the gpu
|
|
||||||
+ * - if not set delayed flag and repoll if necessary
|
|
||||||
+ * - check for connector status change
|
|
||||||
+ * - repoll if 0 modes found
|
|
||||||
+ *- call driver output status changed notifier
|
|
||||||
+ */
|
|
||||||
+static void output_status_change_execute(struct slow_work *work)
|
|
||||||
+{
|
|
||||||
+ struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work);
|
|
||||||
+ struct drm_fb_helper *fb_helper = container_of(delayed_work, struct drm_fb_helper, output_status_change_slow_work);
|
|
||||||
+ struct drm_connector *connector;
|
|
||||||
+ enum drm_connector_status old_status, status;
|
|
||||||
+ bool repoll, changed = false;
|
|
||||||
+ int ret;
|
|
||||||
+ int i;
|
|
||||||
+ bool bound = false, crtcs_bound = false;
|
|
||||||
+ struct drm_crtc *crtc;
|
|
||||||
|
|
||||||
+ repoll = fb_helper->poll_enabled;
|
|
||||||
+
|
|
||||||
+ /* first of all check the fbcon framebuffer is actually bound to any crtc */
|
|
||||||
+ /* take into account that no crtc at all maybe bound */
|
|
||||||
list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
|
|
||||||
if (crtc->fb)
|
|
||||||
crtcs_bound = true;
|
|
||||||
@@ -1387,21 +1457,38 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
|
|
||||||
bound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!bound && crtcs_bound) {
|
|
||||||
+ if (bound == false && crtcs_bound) {
|
|
||||||
fb_helper->delayed_hotplug = true;
|
|
||||||
- return false;
|
|
||||||
+ goto requeue;
|
|
||||||
}
|
|
||||||
- DRM_DEBUG_KMS("\n");
|
|
||||||
|
|
||||||
- max_width = fb_helper->fb->width;
|
|
||||||
- max_height = fb_helper->fb->height;
|
|
||||||
- bpp_sel = fb_helper->fb->bits_per_pixel;
|
|
||||||
+ for (i = 0; i < fb_helper->connector_count; i++) {
|
|
||||||
+ connector = fb_helper->connector_info[i]->connector;
|
|
||||||
+ old_status = connector->status;
|
|
||||||
+ status = connector->funcs->detect(connector);
|
|
||||||
+ if (old_status != status) {
|
|
||||||
+ changed = true;
|
|
||||||
+ }
|
|
||||||
+ if (status == connector_status_connected && repoll) {
|
|
||||||
+ DRM_DEBUG("%s is connected - stop polling\n", drm_get_connector_name(connector));
|
|
||||||
+ repoll = false;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
|
|
||||||
- max_height);
|
|
||||||
- drm_setup_crtcs(fb_helper);
|
|
||||||
+ if (changed) {
|
|
||||||
+ if (fb_helper->funcs->fb_output_status_changed)
|
|
||||||
+ fb_helper->funcs->fb_output_status_changed(fb_helper);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
|
|
||||||
+requeue:
|
|
||||||
+ if (repoll) {
|
|
||||||
+ ret = delayed_slow_work_enqueue(delayed_work, 5*HZ);
|
|
||||||
+ if (ret)
|
|
||||||
+ DRM_ERROR("delayed enqueue failed %d\n", ret);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
-EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
|
|
||||||
+
|
|
||||||
+static struct slow_work_ops output_status_change_ops = {
|
|
||||||
+ .execute = output_status_change_execute,
|
|
||||||
+};
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
|
|
||||||
index 59a2bf8..76ace2d 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/i915_dma.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/i915_dma.c
|
|
||||||
@@ -1430,7 +1430,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|
||||||
if (ret)
|
|
||||||
goto cleanup_irq;
|
|
||||||
|
|
||||||
- drm_kms_helper_poll_init(dev);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cleanup_irq:
|
|
||||||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
|
|
||||||
index 2479be0..6350bd3 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/i915_irq.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/i915_irq.c
|
|
||||||
@@ -271,7 +271,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Just fire off a uevent and let userspace tell us what to do */
|
|
||||||
- drm_helper_hpd_irq_event(dev);
|
|
||||||
+ intelfb_hotplug(dev, false);
|
|
||||||
+ drm_sysfs_hotplug_event(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i915_handle_rps_change(struct drm_device *dev)
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
|
|
||||||
index 22ff384..125eded 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_crt.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_crt.c
|
|
||||||
@@ -584,10 +584,5 @@ void intel_crt_init(struct drm_device *dev)
|
|
||||||
|
|
||||||
drm_sysfs_connector_add(connector);
|
|
||||||
|
|
||||||
- if (I915_HAS_HOTPLUG(dev))
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
- else
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
-
|
|
||||||
dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
|
|
||||||
}
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
|
||||||
index d753257..70537cf 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
|
||||||
@@ -5036,7 +5036,6 @@ intel_user_framebuffer_create(struct drm_device *dev,
|
|
||||||
|
|
||||||
static const struct drm_mode_config_funcs intel_mode_funcs = {
|
|
||||||
.fb_create = intel_user_framebuffer_create,
|
|
||||||
- .output_poll_changed = intel_fb_output_poll_changed,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct drm_gem_object *
|
|
||||||
@@ -5538,7 +5537,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
|
||||||
|
|
||||||
- drm_kms_helper_poll_fini(dev);
|
|
||||||
intel_fbdev_fini(dev);
|
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
|
|
||||||
index 49b54f0..1815df5 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_dp.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_dp.c
|
|
||||||
@@ -1393,8 +1393,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|
||||||
DRM_MODE_CONNECTOR_DisplayPort);
|
|
||||||
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
|
|
||||||
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
-
|
|
||||||
if (output_reg == DP_A)
|
|
||||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
|
||||||
else
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
|
|
||||||
index df931f7..3230e8d 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_drv.h
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_drv.h
|
|
||||||
@@ -235,5 +235,5 @@ extern int intel_overlay_put_image(struct drm_device *dev, void *data,
|
|
||||||
extern int intel_overlay_attrs(struct drm_device *dev, void *data,
|
|
||||||
struct drm_file *file_priv);
|
|
||||||
|
|
||||||
-extern void intel_fb_output_poll_changed(struct drm_device *dev);
|
|
||||||
+void intelfb_hotplug(struct drm_device *dev, bool polled);
|
|
||||||
#endif /* __INTEL_DRV_H__ */
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
|
|
||||||
index c3c5052..79098b3 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_fb.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_fb.c
|
|
||||||
@@ -211,6 +211,12 @@ static int intel_fb_find_or_create_single(struct drm_fb_helper *helper,
|
|
||||||
return new_fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void intelfb_hotplug(struct drm_device *dev, bool polled)
|
|
||||||
+{
|
|
||||||
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
||||||
+ drm_helper_fb_hpd_irq_event(&dev_priv->fbdev->helper);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
|
||||||
.gamma_set = intel_crtc_fb_gamma_set,
|
|
||||||
.gamma_get = intel_crtc_fb_gamma_get,
|
|
||||||
@@ -256,7 +262,7 @@ int intel_fbdev_init(struct drm_device *dev)
|
|
||||||
|
|
||||||
ret = drm_fb_helper_init(dev, &ifbdev->helper,
|
|
||||||
dev_priv->num_pipe,
|
|
||||||
- INTELFB_CONN_LIMIT);
|
|
||||||
+ INTELFB_CONN_LIMIT, false);
|
|
||||||
if (ret) {
|
|
||||||
kfree(ifbdev);
|
|
||||||
return ret;
|
|
||||||
@@ -278,9 +284,3 @@ void intel_fbdev_fini(struct drm_device *dev)
|
|
||||||
dev_priv->fbdev = NULL;
|
|
||||||
}
|
|
||||||
MODULE_LICENSE("GPL and additional rights");
|
|
||||||
-
|
|
||||||
-void intel_fb_output_poll_changed(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- drm_i915_private_t *dev_priv = dev->dev_private;
|
|
||||||
- drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
|
|
||||||
-}
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
|
|
||||||
index 83bd764..acaca07 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_hdmi.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
|
|
||||||
@@ -240,7 +240,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|
||||||
|
|
||||||
intel_encoder->type = INTEL_OUTPUT_HDMI;
|
|
||||||
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
connector->interlace_allowed = 0;
|
|
||||||
connector->doublescan_allowed = 0;
|
|
||||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
||||||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
|
|
||||||
index 76993ac..1c716b5 100644
|
|
||||||
--- a/drivers/gpu/drm/i915/intel_sdvo.c
|
|
||||||
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
|
|
||||||
@@ -2218,7 +2218,6 @@ intel_sdvo_dvi_init(struct intel_encoder *intel_encoder, int device)
|
|
||||||
}
|
|
||||||
|
|
||||||
connector = &intel_connector->base;
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
|
||||||
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
|
||||||
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
|
||||||
|
|
||||||
@@ -2285,7 +2284,6 @@ intel_sdvo_analog_init(struct intel_encoder *intel_encoder, int device)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
connector = &intel_connector->base;
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
encoder->encoder_type = DRM_MODE_ENCODER_DAC;
|
|
||||||
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
|
|
||||||
sdvo_connector = intel_connector->dev_priv;
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
||||||
index 149ed22..9a61f3c 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
||||||
@@ -846,7 +846,6 @@ nouveau_connector_create(struct drm_device *dev,
|
|
||||||
|
|
||||||
switch (dcb->type) {
|
|
||||||
case DCB_CONNECTOR_VGA:
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
if (dev_priv->card_type >= NV_50) {
|
|
||||||
drm_connector_attach_property(connector,
|
|
||||||
dev->mode_config.scaling_mode_property,
|
|
||||||
@@ -858,17 +857,6 @@ nouveau_connector_create(struct drm_device *dev,
|
|
||||||
case DCB_CONNECTOR_TV_3:
|
|
||||||
nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
|
|
||||||
break;
|
|
||||||
- case DCB_CONNECTOR_DP:
|
|
||||||
- case DCB_CONNECTOR_eDP:
|
|
||||||
- case DCB_CONNECTOR_HDMI_0:
|
|
||||||
- case DCB_CONNECTOR_HDMI_1:
|
|
||||||
- case DCB_CONNECTOR_DVI_I:
|
|
||||||
- case DCB_CONNECTOR_DVI_D:
|
|
||||||
- if (dev_priv->card_type >= NV_50)
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
- else
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
- /* fall-through */
|
|
||||||
default:
|
|
||||||
nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
|
|
||||||
index 74e6b4e..9d7928f 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
|
|
||||||
@@ -101,6 +101,5 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
|
|
||||||
|
|
||||||
const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
|
|
||||||
.fb_create = nouveau_user_framebuffer_create,
|
|
||||||
- .output_poll_changed = nouveau_fbcon_output_poll_changed,
|
|
||||||
};
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
|
|
||||||
index c9a4a0d..0a59f96 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
|
|
||||||
@@ -326,11 +326,15 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper,
|
|
||||||
return new_fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void
|
|
||||||
-nouveau_fbcon_output_poll_changed(struct drm_device *dev)
|
|
||||||
+void nouveau_fbcon_hotplug(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
||||||
- drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
|
|
||||||
+ drm_helper_fb_hpd_irq_event(&dev_priv->nfbdev->helper);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void nouveau_fbcon_output_status_changed(struct drm_fb_helper *fb_helper)
|
|
||||||
+{
|
|
||||||
+ drm_helper_fb_hotplug_event(fb_helper, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
@@ -370,6 +374,7 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
|
|
||||||
.gamma_set = nouveau_fbcon_gamma_set,
|
|
||||||
.gamma_get = nouveau_fbcon_gamma_get,
|
|
||||||
.fb_probe = nouveau_fbcon_find_or_create_single,
|
|
||||||
+ .fb_output_status_changed = nouveau_fbcon_output_status_changed,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -387,7 +392,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
|
|
||||||
dev_priv->nfbdev = nfbdev;
|
|
||||||
nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
|
|
||||||
|
|
||||||
- ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
|
|
||||||
+ ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4, true);
|
|
||||||
if (ret) {
|
|
||||||
kfree(nfbdev);
|
|
||||||
return ret;
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
|
|
||||||
index e7e1268..bf8e00d 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
|
|
||||||
@@ -58,6 +58,6 @@ void nouveau_fbcon_zfill_all(struct drm_device *dev);
|
|
||||||
void nouveau_fbcon_save_disable_accel(struct drm_device *dev);
|
|
||||||
void nouveau_fbcon_restore_accel(struct drm_device *dev);
|
|
||||||
|
|
||||||
-void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
|
|
||||||
+void nouveau_fbcon_hotplug(struct drm_device *dev);
|
|
||||||
#endif /* __NV50_FBCON_H__ */
|
|
||||||
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
||||||
index b02a231..4dcb976 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
||||||
@@ -519,10 +519,8 @@ nouveau_card_init(struct drm_device *dev)
|
|
||||||
|
|
||||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
|
|
||||||
|
|
||||||
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
|
||||||
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
|
|
||||||
nouveau_fbcon_init(dev);
|
|
||||||
- drm_kms_helper_poll_init(dev);
|
|
||||||
- }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
@@ -844,7 +842,6 @@ int nouveau_unload(struct drm_device *dev)
|
|
||||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
||||||
|
|
||||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
|
||||||
- drm_kms_helper_poll_fini(dev);
|
|
||||||
nouveau_fbcon_fini(dev);
|
|
||||||
if (dev_priv->card_type >= NV_50)
|
|
||||||
nv50_display_destroy(dev);
|
|
||||||
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
|
|
||||||
index 580a5d1..e6a44af 100644
|
|
||||||
--- a/drivers/gpu/drm/nouveau/nv50_display.c
|
|
||||||
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
|
|
||||||
@@ -980,7 +980,7 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
|
|
||||||
if (dev_priv->chipset >= 0x90)
|
|
||||||
nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
|
|
||||||
|
|
||||||
- drm_helper_hpd_irq_event(dev);
|
|
||||||
+ nouveau_fbcon_hotplug(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
||||||
index 0c7ccc6..40a24c9 100644
|
|
||||||
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
||||||
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
||||||
@@ -1085,7 +1085,6 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|
||||||
drm_connector_attach_property(&radeon_connector->base,
|
|
||||||
rdev->mode_info.load_detect_property,
|
|
||||||
1);
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
break;
|
|
||||||
case DRM_MODE_CONNECTOR_DVIA:
|
|
||||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
|
||||||
@@ -1212,12 +1211,6 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (hpd->hpd == RADEON_HPD_NONE) {
|
|
||||||
- if (i2c_bus->valid)
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
- } else
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
-
|
|
||||||
connector->display_info.subpixel_order = subpixel_order;
|
|
||||||
drm_sysfs_connector_add(connector);
|
|
||||||
return;
|
|
||||||
@@ -1279,7 +1272,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|
||||||
drm_connector_attach_property(&radeon_connector->base,
|
|
||||||
rdev->mode_info.load_detect_property,
|
|
||||||
1);
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
break;
|
|
||||||
case DRM_MODE_CONNECTOR_DVIA:
|
|
||||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
|
||||||
@@ -1348,11 +1340,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (hpd->hpd == RADEON_HPD_NONE) {
|
|
||||||
- if (i2c_bus->valid)
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
||||||
- } else
|
|
||||||
- connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
||||||
connector->display_info.subpixel_order = subpixel_order;
|
|
||||||
drm_sysfs_connector_add(connector);
|
|
||||||
return;
|
|
||||||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
|
|
||||||
index c73444a..ed756be 100644
|
|
||||||
--- a/drivers/gpu/drm/radeon/radeon_display.c
|
|
||||||
+++ b/drivers/gpu/drm/radeon/radeon_display.c
|
|
||||||
@@ -887,15 +887,8 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
|
||||||
return &radeon_fb->base;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void radeon_output_poll_changed(struct drm_device *dev)
|
|
||||||
-{
|
|
||||||
- struct radeon_device *rdev = dev->dev_private;
|
|
||||||
- radeon_fb_output_poll_changed(rdev);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static const struct drm_mode_config_funcs radeon_mode_funcs = {
|
|
||||||
.fb_create = radeon_user_framebuffer_create,
|
|
||||||
- .output_poll_changed = radeon_output_poll_changed
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_prop_enum_list {
|
|
||||||
@@ -1044,8 +1037,6 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|
||||||
radeon_pm_init(rdev);
|
|
||||||
|
|
||||||
radeon_fbdev_init(rdev);
|
|
||||||
- drm_kms_helper_poll_init(rdev->ddev);
|
|
||||||
-
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1058,7 +1049,6 @@ void radeon_modeset_fini(struct radeon_device *rdev)
|
|
||||||
radeon_pm_fini(rdev);
|
|
||||||
|
|
||||||
if (rdev->mode_info.mode_config_initialized) {
|
|
||||||
- drm_kms_helper_poll_fini(rdev->ddev);
|
|
||||||
radeon_hpd_fini(rdev);
|
|
||||||
drm_mode_config_cleanup(rdev->ddev);
|
|
||||||
rdev->mode_info.mode_config_initialized = false;
|
|
||||||
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
|
|
||||||
index dc1634b..7dc38f6 100644
|
|
||||||
--- a/drivers/gpu/drm/radeon/radeon_fb.c
|
|
||||||
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
|
|
||||||
@@ -316,9 +316,16 @@ int radeon_parse_options(char *options)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void radeon_fb_output_poll_changed(struct radeon_device *rdev)
|
|
||||||
+void radeonfb_hotplug(struct drm_device *dev, bool polled)
|
|
||||||
{
|
|
||||||
- drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper);
|
|
||||||
+ struct radeon_device *rdev = dev->dev_private;
|
|
||||||
+
|
|
||||||
+ drm_helper_fb_hpd_irq_event(&rdev->mode_info.rfbdev->helper);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void radeon_fb_output_status_changed(struct drm_fb_helper *fb_helper)
|
|
||||||
+{
|
|
||||||
+ drm_helper_fb_hotplug_event(fb_helper, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
|
|
||||||
@@ -357,6 +364,7 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
|
|
||||||
.gamma_set = radeon_crtc_fb_gamma_set,
|
|
||||||
.gamma_get = radeon_crtc_fb_gamma_get,
|
|
||||||
.fb_probe = radeon_fb_find_or_create_single,
|
|
||||||
+ .fb_output_status_changed = radeon_fb_output_status_changed,
|
|
||||||
};
|
|
||||||
|
|
||||||
int radeon_fbdev_init(struct radeon_device *rdev)
|
|
||||||
@@ -379,7 +387,7 @@ int radeon_fbdev_init(struct radeon_device *rdev)
|
|
||||||
|
|
||||||
ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
|
|
||||||
rdev->num_crtc,
|
|
||||||
- RADEONFB_CONN_LIMIT);
|
|
||||||
+ RADEONFB_CONN_LIMIT, true);
|
|
||||||
if (ret) {
|
|
||||||
kfree(rfbdev);
|
|
||||||
return ret;
|
|
||||||
@@ -388,6 +396,7 @@ int radeon_fbdev_init(struct radeon_device *rdev)
|
|
||||||
drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
|
|
||||||
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
|
|
||||||
return 0;
|
|
||||||
+
|
|
||||||
}
|
|
||||||
|
|
||||||
void radeon_fbdev_fini(struct radeon_device *rdev)
|
|
||||||
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
||||||
index 059bfa4..b0178de 100644
|
|
||||||
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
||||||
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
||||||
@@ -26,7 +26,6 @@
|
|
||||||
* Jerome Glisse
|
|
||||||
*/
|
|
||||||
#include "drmP.h"
|
|
||||||
-#include "drm_crtc_helper.h"
|
|
||||||
#include "radeon_drm.h"
|
|
||||||
#include "radeon_reg.h"
|
|
||||||
#include "radeon.h"
|
|
||||||
@@ -56,7 +55,9 @@ static void radeon_hotplug_work_func(struct work_struct *work)
|
|
||||||
radeon_connector_hotplug(connector);
|
|
||||||
}
|
|
||||||
/* Just fire off a uevent and let userspace tell us what to do */
|
|
||||||
- drm_helper_hpd_irq_event(dev);
|
|
||||||
+ radeonfb_hotplug(dev, false);
|
|
||||||
+
|
|
||||||
+ drm_sysfs_hotplug_event(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
|
||||||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
|
|
||||||
index 67358ba..fdd1611 100644
|
|
||||||
--- a/drivers/gpu/drm/radeon/radeon_mode.h
|
|
||||||
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
|
|
||||||
@@ -588,6 +588,5 @@ void radeon_fbdev_fini(struct radeon_device *rdev);
|
|
||||||
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
|
|
||||||
int radeon_fbdev_total_size(struct radeon_device *rdev);
|
|
||||||
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
|
|
||||||
-
|
|
||||||
-void radeon_fb_output_poll_changed(struct radeon_device *rdev);
|
|
||||||
+void radeonfb_hotplug(struct drm_device *dev, bool polled);
|
|
||||||
#endif
|
|
||||||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
|
|
||||||
index 93a1a31..a7148d2 100644
|
|
||||||
--- a/include/drm/drm_crtc.h
|
|
||||||
+++ b/include/drm/drm_crtc.h
|
|
||||||
@@ -31,7 +31,6 @@
|
|
||||||
#include <linux/idr.h>
|
|
||||||
|
|
||||||
#include <linux/fb.h>
|
|
||||||
-#include <linux/slow-work.h>
|
|
||||||
|
|
||||||
struct drm_device;
|
|
||||||
struct drm_mode_set;
|
|
||||||
@@ -461,15 +460,6 @@ enum drm_connector_force {
|
|
||||||
DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* should we poll this connector for connects and disconnects */
|
|
||||||
-/* hot plug detectable */
|
|
||||||
-#define DRM_CONNECTOR_POLL_HPD (1 << 0)
|
|
||||||
-/* poll for connections */
|
|
||||||
-#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
|
|
||||||
-/* can cleanly poll for disconnections without flickering the screen */
|
|
||||||
-/* DACs should rarely do this without a lot of testing */
|
|
||||||
-#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
|
|
||||||
-
|
|
||||||
/**
|
|
||||||
* drm_connector - central DRM connector control structure
|
|
||||||
* @crtc: CRTC this connector is currently connected to, NULL if none
|
|
||||||
@@ -514,8 +504,6 @@ struct drm_connector {
|
|
||||||
u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY];
|
|
||||||
uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY];
|
|
||||||
|
|
||||||
- uint8_t polled; /* DRM_CONNECTOR_POLL_* */
|
|
||||||
-
|
|
||||||
/* requested DPMS state */
|
|
||||||
int dpms;
|
|
||||||
|
|
||||||
@@ -555,7 +543,6 @@ struct drm_mode_set {
|
|
||||||
*/
|
|
||||||
struct drm_mode_config_funcs {
|
|
||||||
struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
|
|
||||||
- void (*output_poll_changed)(struct drm_device *dev);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_mode_group {
|
|
||||||
@@ -593,10 +580,6 @@ struct drm_mode_config {
|
|
||||||
struct drm_mode_config_funcs *funcs;
|
|
||||||
resource_size_t fb_base;
|
|
||||||
|
|
||||||
- /* output poll support */
|
|
||||||
- bool poll_enabled;
|
|
||||||
- struct delayed_slow_work output_poll_slow_work;
|
|
||||||
-
|
|
||||||
/* pointers to standard properties */
|
|
||||||
struct list_head property_blob_list;
|
|
||||||
struct drm_property *edid_property;
|
|
||||||
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
|
|
||||||
index 1121f77..b1fa0f8 100644
|
|
||||||
--- a/include/drm/drm_crtc_helper.h
|
|
||||||
+++ b/include/drm/drm_crtc_helper.h
|
|
||||||
@@ -127,10 +127,4 @@ static inline void drm_connector_helper_add(struct drm_connector *connector,
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int drm_helper_resume_force_mode(struct drm_device *dev);
|
|
||||||
-extern void drm_kms_helper_poll_init(struct drm_device *dev);
|
|
||||||
-extern void drm_kms_helper_poll_fini(struct drm_device *dev);
|
|
||||||
-extern void drm_helper_hpd_irq_event(struct drm_device *dev);
|
|
||||||
-
|
|
||||||
-extern void drm_kms_helper_poll_disable(struct drm_device *dev);
|
|
||||||
-extern void drm_kms_helper_poll_enable(struct drm_device *dev);
|
|
||||||
#endif
|
|
||||||
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
|
|
||||||
index f0a6afc..9b55a94 100644
|
|
||||||
--- a/include/drm/drm_fb_helper.h
|
|
||||||
+++ b/include/drm/drm_fb_helper.h
|
|
||||||
@@ -30,6 +30,8 @@
|
|
||||||
#ifndef DRM_FB_HELPER_H
|
|
||||||
#define DRM_FB_HELPER_H
|
|
||||||
|
|
||||||
+#include <linux/slow-work.h>
|
|
||||||
+
|
|
||||||
struct drm_fb_helper;
|
|
||||||
|
|
||||||
struct drm_fb_helper_crtc {
|
|
||||||
@@ -69,6 +71,9 @@ struct drm_fb_helper_funcs {
|
|
||||||
|
|
||||||
int (*fb_probe)(struct drm_fb_helper *helper,
|
|
||||||
struct drm_fb_helper_surface_size *sizes);
|
|
||||||
+
|
|
||||||
+ void (*fb_output_status_changed)(struct drm_fb_helper *helper);
|
|
||||||
+
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_fb_helper_connector {
|
|
||||||
@@ -90,6 +95,8 @@ struct drm_fb_helper {
|
|
||||||
u32 pseudo_palette[17];
|
|
||||||
struct list_head kernel_fb_list;
|
|
||||||
|
|
||||||
+ struct delayed_slow_work output_status_change_slow_work;
|
|
||||||
+ bool poll_enabled;
|
|
||||||
/* we got a hotplug but fbdev wasn't running the console
|
|
||||||
delay until next set_par */
|
|
||||||
bool delayed_hotplug;
|
|
||||||
@@ -100,7 +107,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper,
|
|
||||||
|
|
||||||
int drm_fb_helper_init(struct drm_device *dev,
|
|
||||||
struct drm_fb_helper *helper, int crtc_count,
|
|
||||||
- int max_conn);
|
|
||||||
+ int max_conn, bool polled);
|
|
||||||
void drm_fb_helper_fini(struct drm_fb_helper *helper);
|
|
||||||
int drm_fb_helper_blank(int blank, struct fb_info *info);
|
|
||||||
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
|
|
||||||
@@ -123,8 +130,10 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
|
|
||||||
|
|
||||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
|
|
||||||
|
|
||||||
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
|
|
||||||
+bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper,
|
|
||||||
+ bool polled);
|
|
||||||
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
|
|
||||||
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
|
|
||||||
|
|
||||||
+void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper);
|
|
||||||
#endif
|
|
||||||
--
|
|
||||||
1.7.0.1
|
|
||||||
|
|
|
@ -0,0 +1,592 @@
|
||||||
|
From f1719f0dcd68ca4de42c7b00ef2b37658007dda7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Date: Thu, 22 Jul 2010 17:06:18 +0200
|
||||||
|
Subject: [PATCH 2/5] drm-sil164-module
|
||||||
|
|
||||||
|
drm: Import driver for the sil164 I2C TMDS transmitter.
|
||||||
|
|
||||||
|
sil164 transmitters are used for DVI outputs on Intel/nvidia and ATI setups.
|
||||||
|
|
||||||
|
So far only nouveau can use this driver.
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Tested-by: Patrice Mandin <patmandin@gmail.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/i2c/Makefile | 3 +
|
||||||
|
drivers/gpu/drm/i2c/sil164_drv.c | 462 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
drivers/gpu/drm/nouveau/Kconfig | 9 +
|
||||||
|
include/drm/i2c/sil164.h | 63 +++++
|
||||||
|
4 files changed, 537 insertions(+), 0 deletions(-)
|
||||||
|
create mode 100644 drivers/gpu/drm/i2c/sil164_drv.c
|
||||||
|
create mode 100644 include/drm/i2c/sil164.h
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
|
||||||
|
index 6d2abaf..9286256 100644
|
||||||
|
--- a/drivers/gpu/drm/i2c/Makefile
|
||||||
|
+++ b/drivers/gpu/drm/i2c/Makefile
|
||||||
|
@@ -2,3 +2,6 @@ ccflags-y := -Iinclude/drm
|
||||||
|
|
||||||
|
ch7006-y := ch7006_drv.o ch7006_mode.o
|
||||||
|
obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
|
||||||
|
+
|
||||||
|
+sil164-y := sil164_drv.o
|
||||||
|
+obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
|
||||||
|
diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0b67732
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/gpu/drm/i2c/sil164_drv.c
|
||||||
|
@@ -0,0 +1,462 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2010 Francisco Jerez.
|
||||||
|
+ * All Rights Reserved.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
+ * a copy of this software and associated documentation files (the
|
||||||
|
+ * "Software"), to deal in the Software without restriction, including
|
||||||
|
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
+ * the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice (including the
|
||||||
|
+ * next paragraph) shall be included in all copies or substantial
|
||||||
|
+ * portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||||
|
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "drmP.h"
|
||||||
|
+#include "drm_crtc_helper.h"
|
||||||
|
+#include "drm_encoder_slave.h"
|
||||||
|
+#include "i2c/sil164.h"
|
||||||
|
+
|
||||||
|
+struct sil164_priv {
|
||||||
|
+ struct sil164_encoder_params config;
|
||||||
|
+ struct i2c_client *duallink_slave;
|
||||||
|
+
|
||||||
|
+ uint8_t saved_state[0x10];
|
||||||
|
+ uint8_t saved_slave_state[0x10];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define to_sil164_priv(x) \
|
||||||
|
+ ((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
|
||||||
|
+
|
||||||
|
+#define sil164_dbg(client, format, ...) do { \
|
||||||
|
+ if (drm_debug & DRM_UT_KMS) \
|
||||||
|
+ dev_printk(KERN_DEBUG, &client->dev, \
|
||||||
|
+ "%s: " format, __func__, ## __VA_ARGS__); \
|
||||||
|
+ } while (0)
|
||||||
|
+#define sil164_info(client, format, ...) \
|
||||||
|
+ dev_info(&client->dev, format, __VA_ARGS__)
|
||||||
|
+#define sil164_err(client, format, ...) \
|
||||||
|
+ dev_err(&client->dev, format, __VA_ARGS__)
|
||||||
|
+
|
||||||
|
+#define SIL164_I2C_ADDR_MASTER 0x38
|
||||||
|
+#define SIL164_I2C_ADDR_SLAVE 0x39
|
||||||
|
+
|
||||||
|
+/* HW register definitions */
|
||||||
|
+
|
||||||
|
+#define SIL164_VENDOR_LO 0x0
|
||||||
|
+#define SIL164_VENDOR_HI 0x1
|
||||||
|
+#define SIL164_DEVICE_LO 0x2
|
||||||
|
+#define SIL164_DEVICE_HI 0x3
|
||||||
|
+#define SIL164_REVISION 0x4
|
||||||
|
+#define SIL164_FREQ_MIN 0x6
|
||||||
|
+#define SIL164_FREQ_MAX 0x7
|
||||||
|
+#define SIL164_CONTROL0 0x8
|
||||||
|
+# define SIL164_CONTROL0_POWER_ON 0x01
|
||||||
|
+# define SIL164_CONTROL0_EDGE_RISING 0x02
|
||||||
|
+# define SIL164_CONTROL0_INPUT_24BIT 0x04
|
||||||
|
+# define SIL164_CONTROL0_DUAL_EDGE 0x08
|
||||||
|
+# define SIL164_CONTROL0_HSYNC_ON 0x10
|
||||||
|
+# define SIL164_CONTROL0_VSYNC_ON 0x20
|
||||||
|
+#define SIL164_DETECT 0x9
|
||||||
|
+# define SIL164_DETECT_INTR_STAT 0x01
|
||||||
|
+# define SIL164_DETECT_HOTPLUG_STAT 0x02
|
||||||
|
+# define SIL164_DETECT_RECEIVER_STAT 0x04
|
||||||
|
+# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00
|
||||||
|
+# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08
|
||||||
|
+# define SIL164_DETECT_OUT_MODE_HIGH 0x00
|
||||||
|
+# define SIL164_DETECT_OUT_MODE_INTR 0x10
|
||||||
|
+# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20
|
||||||
|
+# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30
|
||||||
|
+# define SIL164_DETECT_VSWING_STAT 0x80
|
||||||
|
+#define SIL164_CONTROL1 0xa
|
||||||
|
+# define SIL164_CONTROL1_DESKEW_ENABLE 0x10
|
||||||
|
+# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5
|
||||||
|
+#define SIL164_GPIO 0xb
|
||||||
|
+#define SIL164_CONTROL2 0xc
|
||||||
|
+# define SIL164_CONTROL2_FILTER_ENABLE 0x01
|
||||||
|
+# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1
|
||||||
|
+# define SIL164_CONTROL2_DUALLINK_MASTER 0x40
|
||||||
|
+# define SIL164_CONTROL2_SYNC_CONT 0x80
|
||||||
|
+#define SIL164_DUALLINK 0xd
|
||||||
|
+# define SIL164_DUALLINK_ENABLE 0x10
|
||||||
|
+# define SIL164_DUALLINK_SKEW_SHIFT 5
|
||||||
|
+#define SIL164_PLLZONE 0xe
|
||||||
|
+# define SIL164_PLLZONE_STAT 0x08
|
||||||
|
+# define SIL164_PLLZONE_FORCE_ON 0x10
|
||||||
|
+# define SIL164_PLLZONE_FORCE_HIGH 0x20
|
||||||
|
+
|
||||||
|
+/* HW access functions */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val)
|
||||||
|
+{
|
||||||
|
+ uint8_t buf[] = {addr, val};
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ sil164_err(client, "Error %d writing to subaddress 0x%x\n",
|
||||||
|
+ ret, addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static uint8_t
|
||||||
|
+sil164_read(struct i2c_client *client, uint8_t addr)
|
||||||
|
+{
|
||||||
|
+ uint8_t val;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = i2c_master_send(client, &addr, sizeof(addr));
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ ret = i2c_master_recv(client, &val, sizeof(val));
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ return val;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+ sil164_err(client, "Error %d reading from subaddress 0x%x\n",
|
||||||
|
+ ret, addr);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_save_state(struct i2c_client *client, uint8_t *state)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0x8; i <= 0xe; i++)
|
||||||
|
+ state[i] = sil164_read(client, i);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_restore_state(struct i2c_client *client, uint8_t *state)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0x8; i <= 0xe; i++)
|
||||||
|
+ sil164_write(client, i, state[i]);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_set_power_state(struct i2c_client *client, bool on)
|
||||||
|
+{
|
||||||
|
+ uint8_t control0 = sil164_read(client, SIL164_CONTROL0);
|
||||||
|
+
|
||||||
|
+ if (on)
|
||||||
|
+ control0 |= SIL164_CONTROL0_POWER_ON;
|
||||||
|
+ else
|
||||||
|
+ control0 &= ~SIL164_CONTROL0_POWER_ON;
|
||||||
|
+
|
||||||
|
+ sil164_write(client, SIL164_CONTROL0, control0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_init_state(struct i2c_client *client,
|
||||||
|
+ struct sil164_encoder_params *config,
|
||||||
|
+ bool duallink)
|
||||||
|
+{
|
||||||
|
+ sil164_write(client, SIL164_CONTROL0,
|
||||||
|
+ SIL164_CONTROL0_HSYNC_ON |
|
||||||
|
+ SIL164_CONTROL0_VSYNC_ON |
|
||||||
|
+ (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) |
|
||||||
|
+ (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) |
|
||||||
|
+ (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0));
|
||||||
|
+
|
||||||
|
+ sil164_write(client, SIL164_DETECT,
|
||||||
|
+ SIL164_DETECT_INTR_STAT |
|
||||||
|
+ SIL164_DETECT_OUT_MODE_RECEIVER);
|
||||||
|
+
|
||||||
|
+ sil164_write(client, SIL164_CONTROL1,
|
||||||
|
+ (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) |
|
||||||
|
+ (((config->input_skew + 4) & 0x7)
|
||||||
|
+ << SIL164_CONTROL1_DESKEW_INCR_SHIFT));
|
||||||
|
+
|
||||||
|
+ sil164_write(client, SIL164_CONTROL2,
|
||||||
|
+ SIL164_CONTROL2_SYNC_CONT |
|
||||||
|
+ (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) |
|
||||||
|
+ (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT));
|
||||||
|
+
|
||||||
|
+ sil164_write(client, SIL164_PLLZONE, 0);
|
||||||
|
+
|
||||||
|
+ if (duallink)
|
||||||
|
+ sil164_write(client, SIL164_DUALLINK,
|
||||||
|
+ SIL164_DUALLINK_ENABLE |
|
||||||
|
+ (((config->duallink_skew + 4) & 0x7)
|
||||||
|
+ << SIL164_DUALLINK_SKEW_SHIFT));
|
||||||
|
+ else
|
||||||
|
+ sil164_write(client, SIL164_DUALLINK, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* DRM encoder functions */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_set_config(struct drm_encoder *encoder, void *params)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+
|
||||||
|
+ priv->config = *(struct sil164_encoder_params *)params;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+ bool on = (mode == DRM_MODE_DPMS_ON);
|
||||||
|
+ bool duallink = (on && encoder->crtc->mode.clock > 165000);
|
||||||
|
+
|
||||||
|
+ sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
|
||||||
|
+
|
||||||
|
+ if (priv->duallink_slave)
|
||||||
|
+ sil164_set_power_state(priv->duallink_slave, duallink);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_save(struct drm_encoder *encoder)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+
|
||||||
|
+ sil164_save_state(drm_i2c_encoder_get_client(encoder),
|
||||||
|
+ priv->saved_state);
|
||||||
|
+
|
||||||
|
+ if (priv->duallink_slave)
|
||||||
|
+ sil164_save_state(priv->duallink_slave,
|
||||||
|
+ priv->saved_slave_state);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_restore(struct drm_encoder *encoder)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+
|
||||||
|
+ sil164_restore_state(drm_i2c_encoder_get_client(encoder),
|
||||||
|
+ priv->saved_state);
|
||||||
|
+
|
||||||
|
+ if (priv->duallink_slave)
|
||||||
|
+ sil164_restore_state(priv->duallink_slave,
|
||||||
|
+ priv->saved_slave_state);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+sil164_encoder_mode_fixup(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_display_mode *mode,
|
||||||
|
+ struct drm_display_mode *adjusted_mode)
|
||||||
|
+{
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_encoder_mode_valid(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_display_mode *mode)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+
|
||||||
|
+ if (mode->clock < 32000)
|
||||||
|
+ return MODE_CLOCK_LOW;
|
||||||
|
+
|
||||||
|
+ if (mode->clock > 330000 ||
|
||||||
|
+ (mode->clock > 165000 && !priv->duallink_slave))
|
||||||
|
+ return MODE_CLOCK_HIGH;
|
||||||
|
+
|
||||||
|
+ return MODE_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_mode_set(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_display_mode *mode,
|
||||||
|
+ struct drm_display_mode *adjusted_mode)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+ bool duallink = adjusted_mode->clock > 165000;
|
||||||
|
+
|
||||||
|
+ sil164_init_state(drm_i2c_encoder_get_client(encoder),
|
||||||
|
+ &priv->config, duallink);
|
||||||
|
+
|
||||||
|
+ if (priv->duallink_slave)
|
||||||
|
+ sil164_init_state(priv->duallink_slave,
|
||||||
|
+ &priv->config, duallink);
|
||||||
|
+
|
||||||
|
+ sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static enum drm_connector_status
|
||||||
|
+sil164_encoder_detect(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_connector *connector)
|
||||||
|
+{
|
||||||
|
+ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
|
||||||
|
+
|
||||||
|
+ if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
|
||||||
|
+ return connector_status_connected;
|
||||||
|
+ else
|
||||||
|
+ return connector_status_disconnected;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_encoder_get_modes(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_connector *connector)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_encoder_create_resources(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_connector *connector)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_encoder_set_property(struct drm_encoder *encoder,
|
||||||
|
+ struct drm_connector *connector,
|
||||||
|
+ struct drm_property *property,
|
||||||
|
+ uint64_t val)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sil164_encoder_destroy(struct drm_encoder *encoder)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||||
|
+
|
||||||
|
+ if (priv->duallink_slave)
|
||||||
|
+ i2c_unregister_device(priv->duallink_slave);
|
||||||
|
+
|
||||||
|
+ kfree(priv);
|
||||||
|
+ drm_i2c_encoder_destroy(encoder);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct drm_encoder_slave_funcs sil164_encoder_funcs = {
|
||||||
|
+ .set_config = sil164_encoder_set_config,
|
||||||
|
+ .destroy = sil164_encoder_destroy,
|
||||||
|
+ .dpms = sil164_encoder_dpms,
|
||||||
|
+ .save = sil164_encoder_save,
|
||||||
|
+ .restore = sil164_encoder_restore,
|
||||||
|
+ .mode_fixup = sil164_encoder_mode_fixup,
|
||||||
|
+ .mode_valid = sil164_encoder_mode_valid,
|
||||||
|
+ .mode_set = sil164_encoder_mode_set,
|
||||||
|
+ .detect = sil164_encoder_detect,
|
||||||
|
+ .get_modes = sil164_encoder_get_modes,
|
||||||
|
+ .create_resources = sil164_encoder_create_resources,
|
||||||
|
+ .set_property = sil164_encoder_set_property,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* I2C driver functions */
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
|
+{
|
||||||
|
+ int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
|
||||||
|
+ sil164_read(client, SIL164_VENDOR_LO);
|
||||||
|
+ int device = sil164_read(client, SIL164_DEVICE_HI) << 8 |
|
||||||
|
+ sil164_read(client, SIL164_DEVICE_LO);
|
||||||
|
+ int rev = sil164_read(client, SIL164_REVISION);
|
||||||
|
+
|
||||||
|
+ if (vendor != 0x1 || device != 0x6) {
|
||||||
|
+ sil164_dbg(client, "Unknown device %x:%x.%x\n",
|
||||||
|
+ vendor, device, rev);
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sil164_info(client, "Detected device %x:%x.%x\n",
|
||||||
|
+ vendor, device, rev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_remove(struct i2c_client *client)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct i2c_client *
|
||||||
|
+sil164_detect_slave(struct i2c_client *client)
|
||||||
|
+{
|
||||||
|
+ struct i2c_adapter *adap = client->adapter;
|
||||||
|
+ struct i2c_msg msg = {
|
||||||
|
+ .addr = SIL164_I2C_ADDR_SLAVE,
|
||||||
|
+ .len = 0,
|
||||||
|
+ };
|
||||||
|
+ const struct i2c_board_info info = {
|
||||||
|
+ I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE)
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if (i2c_transfer(adap, &msg, 1) != 1) {
|
||||||
|
+ sil164_dbg(adap, "No dual-link slave found.");
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return i2c_new_device(adap, &info);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sil164_encoder_init(struct i2c_client *client,
|
||||||
|
+ struct drm_device *dev,
|
||||||
|
+ struct drm_encoder_slave *encoder)
|
||||||
|
+{
|
||||||
|
+ struct sil164_priv *priv;
|
||||||
|
+
|
||||||
|
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
|
+ if (!priv)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ encoder->slave_priv = priv;
|
||||||
|
+ encoder->slave_funcs = &sil164_encoder_funcs;
|
||||||
|
+
|
||||||
|
+ priv->duallink_slave = sil164_detect_slave(client);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct i2c_device_id sil164_ids[] = {
|
||||||
|
+ { "sil164", 0 },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(i2c, sil164_ids);
|
||||||
|
+
|
||||||
|
+static struct drm_i2c_encoder_driver sil164_driver = {
|
||||||
|
+ .i2c_driver = {
|
||||||
|
+ .probe = sil164_probe,
|
||||||
|
+ .remove = sil164_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "sil164",
|
||||||
|
+ },
|
||||||
|
+ .id_table = sil164_ids,
|
||||||
|
+ },
|
||||||
|
+ .encoder_init = sil164_encoder_init,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Module initialization */
|
||||||
|
+
|
||||||
|
+static int __init
|
||||||
|
+sil164_init(void)
|
||||||
|
+{
|
||||||
|
+ return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __exit
|
||||||
|
+sil164_exit(void)
|
||||||
|
+{
|
||||||
|
+ drm_i2c_encoder_unregister(&sil164_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
|
||||||
|
+MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver");
|
||||||
|
+MODULE_LICENSE("GPL and additional rights");
|
||||||
|
+
|
||||||
|
+module_init(sil164_init);
|
||||||
|
+module_exit(sil164_exit);
|
||||||
|
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
|
||||||
|
index 1175429..6b8967a 100644
|
||||||
|
--- a/drivers/gpu/drm/nouveau/Kconfig
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/Kconfig
|
||||||
|
@@ -41,4 +41,13 @@ config DRM_I2C_CH7006
|
||||||
|
|
||||||
|
This driver is currently only useful if you're also using
|
||||||
|
the nouveau driver.
|
||||||
|
+
|
||||||
|
+config DRM_I2C_SIL164
|
||||||
|
+ tristate "Silicon Image sil164 TMDS transmitter"
|
||||||
|
+ default m if DRM_NOUVEAU
|
||||||
|
+ help
|
||||||
|
+ Support for sil164 and similar single-link (or dual-link
|
||||||
|
+ when used in pairs) TMDS transmitters, used in some nVidia
|
||||||
|
+ video cards.
|
||||||
|
+
|
||||||
|
endmenu
|
||||||
|
diff --git a/include/drm/i2c/sil164.h b/include/drm/i2c/sil164.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..205e273
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/drm/i2c/sil164.h
|
||||||
|
@@ -0,0 +1,63 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2010 Francisco Jerez.
|
||||||
|
+ * All Rights Reserved.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
+ * a copy of this software and associated documentation files (the
|
||||||
|
+ * "Software"), to deal in the Software without restriction, including
|
||||||
|
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
+ * the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice (including the
|
||||||
|
+ * next paragraph) shall be included in all copies or substantial
|
||||||
|
+ * portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||||
|
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef __DRM_I2C_SIL164_H__
|
||||||
|
+#define __DRM_I2C_SIL164_H__
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * struct sil164_encoder_params
|
||||||
|
+ *
|
||||||
|
+ * Describes how the sil164 is connected to the GPU. It should be used
|
||||||
|
+ * as the @params parameter of its @set_config method.
|
||||||
|
+ *
|
||||||
|
+ * See "http://www.siliconimage.com/docs/SiI-DS-0021-E-164.pdf".
|
||||||
|
+ */
|
||||||
|
+struct sil164_encoder_params {
|
||||||
|
+ enum {
|
||||||
|
+ SIL164_INPUT_EDGE_FALLING = 0,
|
||||||
|
+ SIL164_INPUT_EDGE_RISING
|
||||||
|
+ } input_edge;
|
||||||
|
+
|
||||||
|
+ enum {
|
||||||
|
+ SIL164_INPUT_WIDTH_12BIT = 0,
|
||||||
|
+ SIL164_INPUT_WIDTH_24BIT
|
||||||
|
+ } input_width;
|
||||||
|
+
|
||||||
|
+ enum {
|
||||||
|
+ SIL164_INPUT_SINGLE_EDGE = 0,
|
||||||
|
+ SIL164_INPUT_DUAL_EDGE
|
||||||
|
+ } input_dual;
|
||||||
|
+
|
||||||
|
+ enum {
|
||||||
|
+ SIL164_PLL_FILTER_ON = 0,
|
||||||
|
+ SIL164_PLL_FILTER_OFF,
|
||||||
|
+ } pll_filter;
|
||||||
|
+
|
||||||
|
+ int input_skew; /** < Allowed range [-4, 3], use 0 for no de-skew. */
|
||||||
|
+ int duallink_skew; /** < Allowed range [-4, 3]. */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
--
|
||||||
|
1.7.2
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
From 74ef65374ae6d0eead4a631aea3aca80d016ff0f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Date: Thu, 22 Jul 2010 17:07:38 +0200
|
||||||
|
Subject: [PATCH 1/5] drm-simplify-i2c-config
|
||||||
|
|
||||||
|
drm/kms: Simplify setup of the initial I2C encoder config.
|
||||||
|
|
||||||
|
In most use cases the driver will be using the same static config all
|
||||||
|
the time: interpreting i2c_board_info::platform_data as the default
|
||||||
|
config we can can save the GPU driver a redundant set_config() call.
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/drm_encoder_slave.c | 7 +++++++
|
||||||
|
1 files changed, 7 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c
|
||||||
|
index f018469..d62c064 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_encoder_slave.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_encoder_slave.c
|
||||||
|
@@ -41,6 +41,9 @@
|
||||||
|
* &drm_encoder_slave. The @slave_funcs field will be initialized with
|
||||||
|
* the hooks provided by the slave driver.
|
||||||
|
*
|
||||||
|
+ * If @info->platform_data is non-NULL it will be used as the initial
|
||||||
|
+ * slave config.
|
||||||
|
+ *
|
||||||
|
* Returns 0 on success or a negative errno on failure, in particular,
|
||||||
|
* -ENODEV is returned when no matching driver is found.
|
||||||
|
*/
|
||||||
|
@@ -85,6 +88,10 @@ int drm_i2c_encoder_init(struct drm_device *dev,
|
||||||
|
if (err)
|
||||||
|
goto fail_unregister;
|
||||||
|
|
||||||
|
+ if (info->platform_data)
|
||||||
|
+ encoder->slave_funcs->set_config(&encoder->base,
|
||||||
|
+ info->platform_data);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_unregister:
|
||||||
|
--
|
||||||
|
1.7.2
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
From 08ae078a33245bc01dcf895bd886f30103cc6178 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Thomas Hellstrom <thellstrom@vmware.com>
|
||||||
|
Date: Thu, 30 Sep 2010 12:36:45 +0200
|
||||||
|
Subject: drm/ttm: Fix two race conditions + fix busy codepaths
|
||||||
|
|
||||||
|
This fixes a race pointed out by Dave Airlie where we don't take a buffer
|
||||||
|
object about to be destroyed off the LRU lists properly. It also fixes a rare
|
||||||
|
case where a buffer object could be destroyed in the middle of an
|
||||||
|
accelerated eviction.
|
||||||
|
|
||||||
|
The patch also adds a utility function that can be used to prematurely
|
||||||
|
release GPU memory space usage of an object waiting to be destroyed.
|
||||||
|
For example during eviction or swapout.
|
||||||
|
|
||||||
|
The above mentioned commit didn't queue the buffer on the delayed destroy
|
||||||
|
list under some rare circumstances. It also didn't completely honor the
|
||||||
|
remove_all parameter.
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=615505
|
||||||
|
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=591061
|
||||||
|
|
||||||
|
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/ttm/ttm_bo.c | 84 +++++++++++++++++++++++++++++++++++------
|
||||||
|
include/drm/ttm/ttm_bo_api.h | 4 +-
|
||||||
|
2 files changed, 74 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
|
||||||
|
index 555ebb1..77f22ba 100644
|
||||||
|
--- a/drivers/gpu/drm/ttm/ttm_bo.c
|
||||||
|
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
|
||||||
|
@@ -442,6 +442,43 @@ out_err:
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * Call bo::reserved and with the lru lock held.
|
||||||
|
+ * Will release GPU memory type usage on destruction.
|
||||||
|
+ * This is the place to put in driver specific hooks.
|
||||||
|
+ * Will release the bo::reserved lock and the
|
||||||
|
+ * lru lock on exit.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
|
||||||
|
+{
|
||||||
|
+ struct ttm_bo_global *glob = bo->glob;
|
||||||
|
+
|
||||||
|
+ if (bo->ttm) {
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Release the lru_lock, since we don't want to have
|
||||||
|
+ * an atomic requirement on ttm_tt[unbind|destroy].
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ spin_unlock(&glob->lru_lock);
|
||||||
|
+ ttm_tt_unbind(bo->ttm);
|
||||||
|
+ ttm_tt_destroy(bo->ttm);
|
||||||
|
+ bo->ttm = NULL;
|
||||||
|
+ spin_lock(&glob->lru_lock);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (bo->mem.mm_node) {
|
||||||
|
+ drm_mm_put_block(bo->mem.mm_node);
|
||||||
|
+ bo->mem.mm_node = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ atomic_set(&bo->reserved, 0);
|
||||||
|
+ wake_up_all(&bo->event_queue);
|
||||||
|
+ spin_unlock(&glob->lru_lock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* If bo idle, remove from delayed- and lru lists, and unref.
|
||||||
|
* If not idle, and already on delayed list, do nothing.
|
||||||
|
* If not idle, and not on delayed list, put on delayed list,
|
||||||
|
@@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock(&bo->lock);
|
||||||
|
+retry:
|
||||||
|
(void) ttm_bo_wait(bo, false, false, !remove_all);
|
||||||
|
|
||||||
|
if (!bo->sync_obj) {
|
||||||
|
@@ -464,32 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
|
||||||
|
spin_unlock(&bo->lock);
|
||||||
|
|
||||||
|
spin_lock(&glob->lru_lock);
|
||||||
|
- put_count = ttm_bo_del_from_lru(bo);
|
||||||
|
+ ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Someone else has the object reserved. Bail and retry.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
- ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
|
||||||
|
- BUG_ON(ret);
|
||||||
|
- if (bo->ttm)
|
||||||
|
- ttm_tt_unbind(bo->ttm);
|
||||||
|
+ if (unlikely(ret == -EBUSY)) {
|
||||||
|
+ spin_unlock(&glob->lru_lock);
|
||||||
|
+ spin_lock(&bo->lock);
|
||||||
|
+ goto requeue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * We can re-check for sync object without taking
|
||||||
|
+ * the bo::lock since setting the sync object requires
|
||||||
|
+ * also bo::reserved. A busy object at this point may
|
||||||
|
+ * be caused by another thread starting an accelerated
|
||||||
|
+ * eviction.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ if (unlikely(bo->sync_obj)) {
|
||||||
|
+ atomic_set(&bo->reserved, 0);
|
||||||
|
+ wake_up_all(&bo->event_queue);
|
||||||
|
+ spin_unlock(&glob->lru_lock);
|
||||||
|
+ spin_lock(&bo->lock);
|
||||||
|
+ if (remove_all)
|
||||||
|
+ goto retry;
|
||||||
|
+ else
|
||||||
|
+ goto requeue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ put_count = ttm_bo_del_from_lru(bo);
|
||||||
|
|
||||||
|
if (!list_empty(&bo->ddestroy)) {
|
||||||
|
list_del_init(&bo->ddestroy);
|
||||||
|
++put_count;
|
||||||
|
}
|
||||||
|
- if (bo->mem.mm_node) {
|
||||||
|
- bo->mem.mm_node->private = NULL;
|
||||||
|
- drm_mm_put_block(bo->mem.mm_node);
|
||||||
|
- bo->mem.mm_node = NULL;
|
||||||
|
- }
|
||||||
|
- spin_unlock(&glob->lru_lock);
|
||||||
|
|
||||||
|
- atomic_set(&bo->reserved, 0);
|
||||||
|
+ ttm_bo_cleanup_memtype_use(bo);
|
||||||
|
|
||||||
|
while (put_count--)
|
||||||
|
kref_put(&bo->list_kref, ttm_bo_ref_bug);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+requeue:
|
||||||
|
spin_lock(&glob->lru_lock);
|
||||||
|
if (list_empty(&bo->ddestroy)) {
|
||||||
|
void *sync_obj = bo->sync_obj;
|
||||||
|
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
|
||||||
|
index 267a86c..2040e6c 100644
|
||||||
|
--- a/include/drm/ttm/ttm_bo_api.h
|
||||||
|
+++ b/include/drm/ttm/ttm_bo_api.h
|
||||||
|
@@ -246,9 +246,11 @@ struct ttm_buffer_object {
|
||||||
|
|
||||||
|
atomic_t reserved;
|
||||||
|
|
||||||
|
-
|
||||||
|
/**
|
||||||
|
* Members protected by the bo::lock
|
||||||
|
+ * In addition, setting sync_obj to anything else
|
||||||
|
+ * than NULL requires bo::reserved to be held. This allows for
|
||||||
|
+ * checking NULL while reserved but not holding bo::lock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *sync_obj_arg;
|
||||||
|
--
|
||||||
|
1.7.3.2
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
From 0fbecd400dd0a82d465b3086f209681e8c54cb0f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Date: Tue, 21 Sep 2010 02:15:15 +0200
|
||||||
|
Subject: [PATCH] drm/ttm: Clear the ghost cpu_writers flag on ttm_buffer_object_transfer.
|
||||||
|
|
||||||
|
It makes sense for a BO to move after a process has requested
|
||||||
|
exclusive RW access on it (e.g. because the BO used to be located in
|
||||||
|
unmappable VRAM and we intercepted the CPU access from the fault
|
||||||
|
handler).
|
||||||
|
|
||||||
|
If we let the ghost object inherit cpu_writers from the original
|
||||||
|
object, ttm_bo_release_list() will raise a kernel BUG when the ghost
|
||||||
|
object is destroyed. This can be reproduced with the nouveau driver on
|
||||||
|
nv5x.
|
||||||
|
|
||||||
|
Reported-by: Marcin Slusarz <marcin.slusarz@gmail.com>
|
||||||
|
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
|
||||||
|
Tested-by: Marcin Slusarz <marcin.slusarz@gmail.com>
|
||||||
|
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||||
|
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/ttm/ttm_bo_util.c | 1 +
|
||||||
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
|
||||||
|
index 7cffb3e..3451a82 100644
|
||||||
|
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
|
||||||
|
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
|
||||||
|
@@ -351,6 +351,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
|
||||||
|
INIT_LIST_HEAD(&fbo->lru);
|
||||||
|
INIT_LIST_HEAD(&fbo->swap);
|
||||||
|
fbo->vm_node = NULL;
|
||||||
|
+ atomic_set(&fbo->cpu_writers, 0);
|
||||||
|
|
||||||
|
fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
|
||||||
|
kref_init(&fbo->list_kref);
|
||||||
|
--
|
||||||
|
1.7.3.1
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
From: Bruce Allan <bruce.w.allan@intel.com>
|
||||||
|
Date: Wed, 22 Sep 2010 17:15:54 +0000 (+0000)
|
||||||
|
Subject: e1000e: 82566DC fails to get link
|
||||||
|
X-Git-Tag: v2.6.36-rc6~6^2~23
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5f3eed6fe0e36e4b56c8dd9160241a868ee0de2a
|
||||||
|
|
||||||
|
e1000e: 82566DC fails to get link
|
||||||
|
|
||||||
|
Two recent patches to cleanup the reset[1] and initial PHY configuration[2]
|
||||||
|
code paths for ICH/PCH devices inadvertently left out a 10msec delay and
|
||||||
|
device ID check respectively which are necessary for the 82566DC (device id
|
||||||
|
0x104b) to be configured properly, otherwise it will not get link.
|
||||||
|
|
||||||
|
[1] commit e98cac447cc1cc418dff1d610a5c79c4f2bdec7f
|
||||||
|
[2] commit 3f0c16e84438d657d29446f85fe375794a93f159
|
||||||
|
|
||||||
|
CC: stable@kernel.org
|
||||||
|
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
|
||||||
|
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
|
||||||
|
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
|
||||||
|
index fc8c3ce..6f9cb0d 100644
|
||||||
|
--- a/drivers/net/e1000e/ich8lan.c
|
||||||
|
+++ b/drivers/net/e1000e/ich8lan.c
|
||||||
|
@@ -932,7 +932,6 @@ out:
|
||||||
|
**/
|
||||||
|
static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
||||||
|
{
|
||||||
|
- struct e1000_adapter *adapter = hw->adapter;
|
||||||
|
struct e1000_phy_info *phy = &hw->phy;
|
||||||
|
u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
|
||||||
|
s32 ret_val = 0;
|
||||||
|
@@ -950,7 +949,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
||||||
|
if (phy->type != e1000_phy_igp_3)
|
||||||
|
return ret_val;
|
||||||
|
|
||||||
|
- if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) {
|
||||||
|
+ if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) ||
|
||||||
|
+ (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) {
|
||||||
|
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1626,6 +1626,9 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
|
||||||
|
if (e1000_check_reset_block(hw))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
+ /* Allow time for h/w to get to quiescent state after reset */
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
/* Perform any necessary post-reset workarounds */
|
||||||
|
switch (hw->mac.type) {
|
||||||
|
case e1000_pchlan:
|
|
@ -0,0 +1,68 @@
|
||||||
|
From: Bruce Allan <bruce.w.allan@intel.com>
|
||||||
|
Date: Wed, 16 Jun 2010 13:26:17 +0000 (+0000)
|
||||||
|
Subject: e1000e: cleanup e1000_sw_lcd_config_ich8lan()
|
||||||
|
X-Git-Tag: v2.6.36-rc1~571^2~529
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3f0c16e84438d657d29446f85fe375794a93f159
|
||||||
|
|
||||||
|
e1000e: cleanup e1000_sw_lcd_config_ich8lan()
|
||||||
|
|
||||||
|
Do not acquire and release the PHY unnecessarily for parts that return
|
||||||
|
from this workaround without actually accessing the PHY registers.
|
||||||
|
|
||||||
|
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
|
||||||
|
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
|
||||||
|
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
|
||||||
|
index b2507d9..5d8fad3 100644
|
||||||
|
--- a/drivers/net/e1000e/ich8lan.c
|
||||||
|
+++ b/drivers/net/e1000e/ich8lan.c
|
||||||
|
@@ -820,14 +820,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
||||||
|
s32 ret_val = 0;
|
||||||
|
u16 word_addr, reg_data, reg_addr, phy_page = 0;
|
||||||
|
|
||||||
|
- if (!(hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) &&
|
||||||
|
- !(hw->mac.type == e1000_pchlan))
|
||||||
|
- return ret_val;
|
||||||
|
-
|
||||||
|
- ret_val = hw->phy.ops.acquire(hw);
|
||||||
|
- if (ret_val)
|
||||||
|
- return ret_val;
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Initialize the PHY from the NVM on ICH platforms. This
|
||||||
|
* is needed due to an issue where the NVM configuration is
|
||||||
|
@@ -835,12 +827,26 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
||||||
|
* Therefore, after each PHY reset, we will load the
|
||||||
|
* configuration data out of the NVM manually.
|
||||||
|
*/
|
||||||
|
- if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
|
||||||
|
- (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
|
||||||
|
- (hw->mac.type == e1000_pchlan))
|
||||||
|
+ switch (hw->mac.type) {
|
||||||
|
+ case e1000_ich8lan:
|
||||||
|
+ if (phy->type != e1000_phy_igp_3)
|
||||||
|
+ return ret_val;
|
||||||
|
+
|
||||||
|
+ if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) {
|
||||||
|
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* Fall-thru */
|
||||||
|
+ case e1000_pchlan:
|
||||||
|
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
|
||||||
|
- else
|
||||||
|
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return ret_val;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret_val = hw->phy.ops.acquire(hw);
|
||||||
|
+ if (ret_val)
|
||||||
|
+ return ret_val;
|
||||||
|
|
||||||
|
data = er32(FEXTNVM);
|
||||||
|
if (!(data & sw_cfg_mask))
|
|
@ -0,0 +1,124 @@
|
||||||
|
commit a5757c2a474a15f87e5baa9a4caacc31cde2bae6
|
||||||
|
Author: Luke Macken <lmacken@redhat.com>
|
||||||
|
Date: Wed Sep 22 13:05:04 2010 -0700
|
||||||
|
|
||||||
|
efifb: support the EFI framebuffer on more Apple hardware
|
||||||
|
|
||||||
|
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
|
||||||
|
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
|
||||||
|
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
|
||||||
|
MacBookPro7,1
|
||||||
|
|
||||||
|
Information gathered from various user submissions.
|
||||||
|
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=528232
|
||||||
|
http://ubuntuforums.org/showthread.php?t=1557326
|
||||||
|
|
||||||
|
[akpm@linux-foundation.org: coding-style fixes]
|
||||||
|
Signed-off-by: Luke Macken <lmacken@redhat.com>
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
|
||||||
|
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
|
||||||
|
index c082b61..70477c2 100644
|
||||||
|
--- a/drivers/video/efifb.c
|
||||||
|
+++ b/drivers/video/efifb.c
|
||||||
|
@@ -39,17 +39,31 @@ enum {
|
||||||
|
M_I20, /* 20-Inch iMac */
|
||||||
|
M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
|
||||||
|
M_I24, /* 24-Inch iMac */
|
||||||
|
+ M_I24_8_1, /* 24-Inch iMac, 8,1th gen */
|
||||||
|
+ M_I24_10_1, /* 24-Inch iMac, 10,1th gen */
|
||||||
|
+ M_I27_11_1, /* 27-Inch iMac, 11,1th gen */
|
||||||
|
M_MINI, /* Mac Mini */
|
||||||
|
+ M_MINI_3_1, /* Mac Mini, 3,1th gen */
|
||||||
|
+ M_MINI_4_1, /* Mac Mini, 4,1th gen */
|
||||||
|
M_MB, /* MacBook */
|
||||||
|
M_MB_2, /* MacBook, 2nd rev. */
|
||||||
|
M_MB_3, /* MacBook, 3rd rev. */
|
||||||
|
+ M_MB_5_1, /* MacBook, 5th rev. */
|
||||||
|
+ M_MB_6_1, /* MacBook, 6th rev. */
|
||||||
|
+ M_MB_7_1, /* MacBook, 7th rev. */
|
||||||
|
M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
|
||||||
|
M_MBA, /* MacBook Air */
|
||||||
|
M_MBP, /* MacBook Pro */
|
||||||
|
M_MBP_2, /* MacBook Pro 2nd gen */
|
||||||
|
+ M_MBP_2_2, /* MacBook Pro 2,2nd gen */
|
||||||
|
M_MBP_SR, /* MacBook Pro (Santa Rosa) */
|
||||||
|
M_MBP_4, /* MacBook Pro, 4th gen */
|
||||||
|
M_MBP_5_1, /* MacBook Pro, 5,1th gen */
|
||||||
|
+ M_MBP_5_2, /* MacBook Pro, 5,2th gen */
|
||||||
|
+ M_MBP_5_3, /* MacBook Pro, 5,3rd gen */
|
||||||
|
+ M_MBP_6_1, /* MacBook Pro, 6,1th gen */
|
||||||
|
+ M_MBP_6_2, /* MacBook Pro, 6,2th gen */
|
||||||
|
+ M_MBP_7_1, /* MacBook Pro, 7,1th gen */
|
||||||
|
M_UNKNOWN /* placeholder */
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -64,14 +78,28 @@ static struct efifb_dmi_info {
|
||||||
|
[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
|
||||||
|
[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
|
||||||
|
[M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
|
||||||
|
+ [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 },
|
||||||
|
+ [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 },
|
||||||
|
+ [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 },
|
||||||
|
[M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
|
||||||
|
+ [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 },
|
||||||
|
+ [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 },
|
||||||
|
[M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
|
||||||
|
+ [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 },
|
||||||
|
+ [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 },
|
||||||
|
+ [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 },
|
||||||
|
[M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
|
||||||
|
[M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
|
||||||
|
[M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
|
||||||
|
+ [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 },
|
||||||
|
[M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
|
||||||
|
[M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
|
||||||
|
[M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
|
||||||
|
+ [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 },
|
||||||
|
+ [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 },
|
||||||
|
+ [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
|
||||||
|
+ [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
|
||||||
|
+ [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
|
||||||
|
[M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -92,7 +120,12 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
|
||||||
|
/* At least one of these two will be right; maybe both? */
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
|
||||||
|
@@ -101,14 +134,23 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
|
||||||
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
|
||||||
|
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
commit 85a00d9bbfb4704fbf368944b1cb9fed8f1598c5
|
||||||
|
Author: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Wed Sep 22 13:05:04 2010 -0700
|
||||||
|
|
||||||
|
efifb: check that the base address is plausible on pci systems
|
||||||
|
|
||||||
|
Some Apple machines have identical DMI data but different memory
|
||||||
|
configurations for the video. Given that, check that the address in our
|
||||||
|
table is actually within the range of a PCI BAR on a VGA device in the
|
||||||
|
machine.
|
||||||
|
|
||||||
|
This also fixes up the return value from set_system(), which has always
|
||||||
|
been wrong, but never resulted in bad behavior since there's only ever
|
||||||
|
been one matching entry in the dmi table.
|
||||||
|
|
||||||
|
The patch
|
||||||
|
|
||||||
|
1) stops people's machines from crashing when we get their display wrong,
|
||||||
|
which seems to be unfortunately inevitable,
|
||||||
|
|
||||||
|
2) allows us to support identical dmi data with differing video memory
|
||||||
|
configurations
|
||||||
|
|
||||||
|
This also adds me as the efifb maintainer, since I've effectively been
|
||||||
|
acting as such for quite some time.
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||||
|
|
||||||
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||||
|
index 726433a..4d4881d 100644
|
||||||
|
--- a/MAINTAINERS
|
||||||
|
+++ b/MAINTAINERS
|
||||||
|
@@ -2199,6 +2199,12 @@ W: http://acpi4asus.sf.net
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/platform/x86/eeepc-laptop.c
|
||||||
|
|
||||||
|
+EFIFB FRAMEBUFFER DRIVER
|
||||||
|
+L: linux-fbdev@vger.kernel.org
|
||||||
|
+M: Peter Jones <pjones@redhat.com>
|
||||||
|
+S: Maintained
|
||||||
|
+F: drivers/video/efifb.c
|
||||||
|
+
|
||||||
|
EFS FILESYSTEM
|
||||||
|
W: http://aeschi.ch.eu.org/efs/
|
||||||
|
S: Orphan
|
||||||
|
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
|
||||||
|
index 815f84b..c082b61 100644
|
||||||
|
--- a/drivers/video/efifb.c
|
||||||
|
+++ b/drivers/video/efifb.c
|
||||||
|
@@ -13,7 +13,7 @@
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/screen_info.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
-
|
||||||
|
+#include <linux/pci.h>
|
||||||
|
#include <video/vga.h>
|
||||||
|
|
||||||
|
static struct fb_var_screeninfo efifb_defined __devinitdata = {
|
||||||
|
@@ -116,7 +116,7 @@ static int set_system(const struct dmi_system_id *id)
|
||||||
|
{
|
||||||
|
struct efifb_dmi_info *info = id->driver_data;
|
||||||
|
if (info->base == 0)
|
||||||
|
- return -ENODEV;
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
|
||||||
|
"(%dx%d, stride %d)\n", id->ident,
|
||||||
|
@@ -124,18 +124,55 @@ static int set_system(const struct dmi_system_id *id)
|
||||||
|
info->stride);
|
||||||
|
|
||||||
|
/* Trust the bootloader over the DMI tables */
|
||||||
|
- if (screen_info.lfb_base == 0)
|
||||||
|
+ if (screen_info.lfb_base == 0) {
|
||||||
|
+#if defined(CONFIG_PCI)
|
||||||
|
+ struct pci_dev *dev = NULL;
|
||||||
|
+ int found_bar = 0;
|
||||||
|
+#endif
|
||||||
|
screen_info.lfb_base = info->base;
|
||||||
|
- if (screen_info.lfb_linelength == 0)
|
||||||
|
- screen_info.lfb_linelength = info->stride;
|
||||||
|
- if (screen_info.lfb_width == 0)
|
||||||
|
- screen_info.lfb_width = info->width;
|
||||||
|
- if (screen_info.lfb_height == 0)
|
||||||
|
- screen_info.lfb_height = info->height;
|
||||||
|
- if (screen_info.orig_video_isVGA == 0)
|
||||||
|
- screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+#if defined(CONFIG_PCI)
|
||||||
|
+ /* make sure that the address in the table is actually on a
|
||||||
|
+ * VGA device's PCI BAR */
|
||||||
|
+
|
||||||
|
+ for_each_pci_dev(dev) {
|
||||||
|
+ int i;
|
||||||
|
+ if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
|
||||||
|
+ continue;
|
||||||
|
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||||
|
+ resource_size_t start, end;
|
||||||
|
+
|
||||||
|
+ start = pci_resource_start(dev, i);
|
||||||
|
+ if (start == 0)
|
||||||
|
+ break;
|
||||||
|
+ end = pci_resource_end(dev, i);
|
||||||
|
+ if (screen_info.lfb_base >= start &&
|
||||||
|
+ screen_info.lfb_base < end) {
|
||||||
|
+ found_bar = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (!found_bar)
|
||||||
|
+ screen_info.lfb_base = 0;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+ if (screen_info.lfb_base) {
|
||||||
|
+ if (screen_info.lfb_linelength == 0)
|
||||||
|
+ screen_info.lfb_linelength = info->stride;
|
||||||
|
+ if (screen_info.lfb_width == 0)
|
||||||
|
+ screen_info.lfb_width = info->width;
|
||||||
|
+ if (screen_info.lfb_height == 0)
|
||||||
|
+ screen_info.lfb_height = info->height;
|
||||||
|
+ if (screen_info.orig_video_isVGA == 0)
|
||||||
|
+ screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
|
||||||
|
+ } else {
|
||||||
|
+ screen_info.lfb_linelength = 0;
|
||||||
|
+ screen_info.lfb_width = 0;
|
||||||
|
+ screen_info.lfb_height = 0;
|
||||||
|
+ screen_info.orig_video_isVGA = 0;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|
@ -0,0 +1,116 @@
|
||||||
|
epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s
|
||||||
|
at once in the case where one epoll fd is monitoring another epoll
|
||||||
|
fd. This is perfectly OK, since we're careful about the lock ordering,
|
||||||
|
but causes spurious lockdep warnings. Annotate the recursion using
|
||||||
|
mutex_lock_nested, and add a comment explaining the nesting rules for
|
||||||
|
good measure.
|
||||||
|
|
||||||
|
Reported-by: Paul Bolle <pebolle@tiscali.nl>
|
||||||
|
Signed-off-by: Nelson Elhage <nelhage@nelhage.com>
|
||||||
|
---
|
||||||
|
I've tested this on a synthetic epoll test case, that just adds e1 to
|
||||||
|
e2 and then does an epoll_wait(). I verified that it caused lockdep
|
||||||
|
problems on 3.0 and that this patch fixed it, but I haven't done more
|
||||||
|
extensive testing. Paul, are you able to test systemd against this?
|
||||||
|
|
||||||
|
fs/eventpoll.c | 25 ++++++++++++++++++-------
|
||||||
|
1 files changed, 18 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
|
||||||
|
index f9cfd16..0cb7bc6 100644
|
||||||
|
--- a/fs/eventpoll.c
|
||||||
|
+++ b/fs/eventpoll.c
|
||||||
|
@@ -76,6 +76,15 @@
|
||||||
|
* Events that require holding "epmutex" are very rare, while for
|
||||||
|
* normal operations the epoll private "ep->mtx" will guarantee
|
||||||
|
* a better scalability.
|
||||||
|
+ * It is possible to acquire multiple "ep->mtx"es at once in the case
|
||||||
|
+ * when one epoll fd is added to another. In this case, we always
|
||||||
|
+ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1,
|
||||||
|
+ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before
|
||||||
|
+ * e2->mtx). Since we disallow cycles of epoll file descriptors, this
|
||||||
|
+ * ensures that the mutexes are well-ordered. In order to communicate
|
||||||
|
+ * this nesting to lockdep, when walking a tree of epoll file
|
||||||
|
+ * descriptors, we use the current recursion depth as the lockdep
|
||||||
|
+ * subkey.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Epoll private bits inside the event mask */
|
||||||
|
@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
|
||||||
|
* @ep: Pointer to the epoll private data structure.
|
||||||
|
* @sproc: Pointer to the scan callback.
|
||||||
|
* @priv: Private opaque data passed to the @sproc callback.
|
||||||
|
+ * @depth: The current depth of recursive f_op->poll calls.
|
||||||
|
*
|
||||||
|
* Returns: The same integer error code returned by the @sproc callback.
|
||||||
|
*/
|
||||||
|
static int ep_scan_ready_list(struct eventpoll *ep,
|
||||||
|
int (*sproc)(struct eventpoll *,
|
||||||
|
struct list_head *, void *),
|
||||||
|
- void *priv)
|
||||||
|
+ void *priv,
|
||||||
|
+ int depth)
|
||||||
|
{
|
||||||
|
int error, pwake = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep,
|
||||||
|
* We need to lock this because we could be hit by
|
||||||
|
* eventpoll_release_file() and epoll_ctl().
|
||||||
|
*/
|
||||||
|
- mutex_lock(&ep->mtx);
|
||||||
|
+ mutex_lock_nested(&ep->mtx, depth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Steal the ready list, and re-init the original one to the
|
||||||
|
@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
|
||||||
|
|
||||||
|
static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests)
|
||||||
|
{
|
||||||
|
- return ep_scan_ready_list(priv, ep_read_events_proc, NULL);
|
||||||
|
+ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
|
||||||
|
@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file)
|
||||||
|
|
||||||
|
ep = epi->ep;
|
||||||
|
list_del_init(&epi->fllink);
|
||||||
|
- mutex_lock(&ep->mtx);
|
||||||
|
+ mutex_lock_nested(&ep->mtx, 0);
|
||||||
|
ep_remove(ep, epi);
|
||||||
|
mutex_unlock(&ep->mtx);
|
||||||
|
}
|
||||||
|
@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep,
|
||||||
|
esed.maxevents = maxevents;
|
||||||
|
esed.events = events;
|
||||||
|
|
||||||
|
- return ep_scan_ready_list(ep, ep_send_events_proc, &esed);
|
||||||
|
+ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct timespec ep_set_mstimeout(long ms)
|
||||||
|
@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
|
||||||
|
struct rb_node *rbp;
|
||||||
|
struct epitem *epi;
|
||||||
|
|
||||||
|
- mutex_lock(&ep->mtx);
|
||||||
|
+ mutex_lock_nested(&ep->mtx, call_nests + 1);
|
||||||
|
for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
|
||||||
|
epi = rb_entry(rbp, struct epitem, rbn);
|
||||||
|
if (unlikely(is_file_epoll(epi->ffd.file))) {
|
||||||
|
@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- mutex_lock(&ep->mtx);
|
||||||
|
+ mutex_lock_nested(&ep->mtx, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to lookup the file inside our RB tree, Since we grabbed "mtx"
|
||||||
|
--
|
||||||
|
1.7.4.1
|
||||||
|
|
||||||
|
--
|
||||||
|
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
|
||||||
|
the body of a message to majordomo@vger.kernel.org
|
||||||
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
|
@ -0,0 +1,465 @@
|
||||||
|
From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jason Baron <jbaron@redhat.com>
|
||||||
|
Date: Mon, 24 Oct 2011 14:59:02 +1100
|
||||||
|
Subject: [PATCH] epoll: limit paths
|
||||||
|
|
||||||
|
epoll: limit paths
|
||||||
|
|
||||||
|
The current epoll code can be tickled to run basically indefinitely in
|
||||||
|
both loop detection path check (on ep_insert()), and in the wakeup paths.
|
||||||
|
The programs that tickle this behavior set up deeply linked networks of
|
||||||
|
epoll file descriptors that cause the epoll algorithms to traverse them
|
||||||
|
indefinitely. A couple of these sample programs have been previously
|
||||||
|
posted in this thread: https://lkml.org/lkml/2011/2/25/297.
|
||||||
|
|
||||||
|
To fix the loop detection path check algorithms, I simply keep track of
|
||||||
|
the epoll nodes that have been already visited. Thus, the loop detection
|
||||||
|
becomes proportional to the number of epoll file descriptor and links.
|
||||||
|
This dramatically decreases the run-time of the loop check algorithm. In
|
||||||
|
one diabolical case I tried it reduced the run-time from 15 mintues (all
|
||||||
|
in kernel time) to .3 seconds.
|
||||||
|
|
||||||
|
Fixing the wakeup paths could be done at wakeup time in a similar manner
|
||||||
|
by keeping track of nodes that have already been visited, but the
|
||||||
|
complexity is harder, since there can be multiple wakeups on different
|
||||||
|
cpus...Thus, I've opted to limit the number of possible wakeup paths when
|
||||||
|
the paths are created.
|
||||||
|
|
||||||
|
This is accomplished, by noting that the end file descriptor points that
|
||||||
|
are found during the loop detection pass (from the newly added link), are
|
||||||
|
actually the sources for wakeup events. I keep a list of these file
|
||||||
|
descriptors and limit the number and length of these paths that emanate
|
||||||
|
from these 'source file descriptors'. In the current implemetation I
|
||||||
|
allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of
|
||||||
|
length 4 and 10 of length 5. Note that it is sufficient to check the
|
||||||
|
'source file descriptors' reachable from the newly added link, since no
|
||||||
|
other 'source file descriptors' will have newly added links. This allows
|
||||||
|
us to check only the wakeup paths that may have gotten too long, and not
|
||||||
|
re-check all possible wakeup paths on the system.
|
||||||
|
|
||||||
|
In terms of the path limit selection, I think its first worth noting that
|
||||||
|
the most common case for epoll, is probably the model where you have 1
|
||||||
|
epoll file descriptor that is monitoring n number of 'source file
|
||||||
|
descriptors'. In this case, each 'source file descriptor' has a 1 path of
|
||||||
|
length 1. Thus, I believe that the limits I'm proposing are quite
|
||||||
|
reasonable and in fact may be too generous. Thus, I'm hoping that the
|
||||||
|
proposed limits will not prevent any workloads that currently work to
|
||||||
|
fail.
|
||||||
|
|
||||||
|
In terms of locking, I have extended the use of the 'epmutex' to all
|
||||||
|
epoll_ctl add and remove operations. Currently its only used in a subset
|
||||||
|
of the add paths. I need to hold the epmutex, so that we can correctly
|
||||||
|
traverse a coherent graph, to check the number of paths. I believe that
|
||||||
|
this additional locking is probably ok, since its in the setup/teardown
|
||||||
|
paths, and doesn't affect the running paths, but it certainly is going to
|
||||||
|
add some extra overhead. Also, worth noting is that the epmuex was
|
||||||
|
recently added to the ep_ctl add operations in the initial path loop
|
||||||
|
detection code using the argument that it was not on a critical path.
|
||||||
|
|
||||||
|
Another thing to note here, is the length of epoll chains that is allowed.
|
||||||
|
Currently, eventpoll.c defines:
|
||||||
|
|
||||||
|
/* Maximum number of nesting allowed inside epoll sets */
|
||||||
|
#define EP_MAX_NESTS 4
|
||||||
|
|
||||||
|
This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS
|
||||||
|
+ 1). However, this limit is currently only enforced during the loop
|
||||||
|
check detection code, and only when the epoll file descriptors are added
|
||||||
|
in a certain order. Thus, this limit is currently easily bypassed. The
|
||||||
|
newly added check for wakeup paths, stricly limits the wakeup paths to a
|
||||||
|
length of 5, regardless of the order in which ep's are linked together.
|
||||||
|
Thus, a side-effect of the new code is a more consistent enforcement of
|
||||||
|
the graph depth.
|
||||||
|
|
||||||
|
Thus far, I've tested this, using the sample programs previously
|
||||||
|
mentioned, which now either return quickly or return -EINVAL. I've also
|
||||||
|
testing using the piptest.c epoll tester, which showed no difference in
|
||||||
|
performance. I've also created a number of different epoll networks and
|
||||||
|
tested that they behave as expectded.
|
||||||
|
|
||||||
|
I believe this solves the original diabolical test cases, while still
|
||||||
|
preserving the sane epoll nesting.
|
||||||
|
|
||||||
|
Signed-off-by: Jason Baron <jbaron@redhat.com>
|
||||||
|
Cc: Nelson Elhage <nelhage@ksplice.com>
|
||||||
|
Cc: Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
---
|
||||||
|
fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++-----
|
||||||
|
include/linux/eventpoll.h | 1 +
|
||||||
|
include/linux/fs.h | 1 +
|
||||||
|
3 files changed, 203 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
|
||||||
|
index 4a53743..414ac74 100644
|
||||||
|
--- a/fs/eventpoll.c
|
||||||
|
+++ b/fs/eventpoll.c
|
||||||
|
@@ -197,6 +197,12 @@ struct eventpoll {
|
||||||
|
|
||||||
|
/* The user that created the eventpoll descriptor */
|
||||||
|
struct user_struct *user;
|
||||||
|
+
|
||||||
|
+ struct file *file;
|
||||||
|
+
|
||||||
|
+ /* used to optimize loop detection check */
|
||||||
|
+ int visited;
|
||||||
|
+ struct list_head visitedllink;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Wait structure used by the poll hooks */
|
||||||
|
@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly;
|
||||||
|
/* Slab cache used to allocate "struct eppoll_entry" */
|
||||||
|
static struct kmem_cache *pwq_cache __read_mostly;
|
||||||
|
|
||||||
|
+/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
|
||||||
|
+LIST_HEAD(visited_list);
|
||||||
|
+
|
||||||
|
+/* Files with newly added links, which need a limit on emanating paths */
|
||||||
|
+LIST_HEAD(tfile_check_list);
|
||||||
|
+
|
||||||
|
#ifdef CONFIG_SYSCTL
|
||||||
|
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
@@ -276,6 +288,12 @@ ctl_table epoll_table[] = {
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_SYSCTL */
|
||||||
|
|
||||||
|
+static const struct file_operations eventpoll_fops;
|
||||||
|
+
|
||||||
|
+static inline int is_file_epoll(struct file *f)
|
||||||
|
+{
|
||||||
|
+ return f->f_op == &eventpoll_fops;
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Setup the structure that is used as key for the RB tree */
|
||||||
|
static inline void ep_set_ffd(struct epoll_filefd *ffd,
|
||||||
|
@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = {
|
||||||
|
.llseek = noop_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Fast test to see if the file is an evenpoll file */
|
||||||
|
-static inline int is_file_epoll(struct file *f)
|
||||||
|
-{
|
||||||
|
- return f->f_op == &eventpoll_fops;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* This is called from eventpoll_release() to unlink files from the eventpoll
|
||||||
|
* interface. We need to have this facility to cleanup correctly files that are
|
||||||
|
@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
|
||||||
|
rb_insert_color(&epi->rbn, &ep->rbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#define PATH_ARR_SIZE 5
|
||||||
|
+/* These are the number paths of length 1 to 5, that we are allowing to emanate
|
||||||
|
+ * from a single file of interest. For example, we allow 1000 paths of length
|
||||||
|
+ * 1, to emanate from each file of interest. This essentially represents the
|
||||||
|
+ * potential wakeup paths, which need to be limited in order to avoid massive
|
||||||
|
+ * uncontrolled wakeup storms. The common use case should be a single ep which
|
||||||
|
+ * is connected to n file sources. In this case each file source has 1 path
|
||||||
|
+ * of length 1. Thus, the numbers below should be more than sufficient.
|
||||||
|
+ */
|
||||||
|
+int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };
|
||||||
|
+int path_count[PATH_ARR_SIZE];
|
||||||
|
+
|
||||||
|
+static int path_count_inc(int nests)
|
||||||
|
+{
|
||||||
|
+ if (++path_count[nests] > path_limits[nests])
|
||||||
|
+ return -1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void path_count_init(void)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < PATH_ARR_SIZE; i++)
|
||||||
|
+ path_count[i] = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
|
||||||
|
+{
|
||||||
|
+ int error = 0;
|
||||||
|
+ struct file *file = priv;
|
||||||
|
+ struct file *child_file;
|
||||||
|
+ struct epitem *epi;
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(epi, &file->f_ep_links, fllink) {
|
||||||
|
+ child_file = epi->ep->file;
|
||||||
|
+ if (is_file_epoll(child_file)) {
|
||||||
|
+ if (list_empty(&child_file->f_ep_links)) {
|
||||||
|
+ if (path_count_inc(call_nests)) {
|
||||||
|
+ error = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ error = ep_call_nested(&poll_loop_ncalls,
|
||||||
|
+ EP_MAX_NESTS,
|
||||||
|
+ reverse_path_check_proc,
|
||||||
|
+ child_file, child_file,
|
||||||
|
+ current);
|
||||||
|
+ }
|
||||||
|
+ if (error != 0)
|
||||||
|
+ break;
|
||||||
|
+ } else {
|
||||||
|
+ printk(KERN_ERR "reverse_path_check_proc: "
|
||||||
|
+ "file is not an ep!\n");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return error;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * reverse_path_check - The tfile_check_list is list of file *, which have
|
||||||
|
+ * links that are proposed to be newly added. We need to
|
||||||
|
+ * make sure that those added links don't add too many
|
||||||
|
+ * paths such that we will spend all our time waking up
|
||||||
|
+ * eventpoll objects.
|
||||||
|
+ *
|
||||||
|
+ * Returns: Returns zero if the proposed links don't create too many paths,
|
||||||
|
+ * -1 otherwise.
|
||||||
|
+ */
|
||||||
|
+static int reverse_path_check(void)
|
||||||
|
+{
|
||||||
|
+ int length = 0;
|
||||||
|
+ int error = 0;
|
||||||
|
+ struct file *current_file;
|
||||||
|
+
|
||||||
|
+ /* let's call this for all tfiles */
|
||||||
|
+ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) {
|
||||||
|
+ length++;
|
||||||
|
+ path_count_init();
|
||||||
|
+ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
|
||||||
|
+ reverse_path_check_proc, current_file,
|
||||||
|
+ current_file, current);
|
||||||
|
+ if (error)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ return error;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Must be called with "mtx" held.
|
||||||
|
*/
|
||||||
|
@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
||||||
|
*/
|
||||||
|
ep_rbtree_insert(ep, epi);
|
||||||
|
|
||||||
|
+ /* now check if we've created too many backpaths */
|
||||||
|
+ error = -EINVAL;
|
||||||
|
+ if (reverse_path_check())
|
||||||
|
+ goto error_remove_epi;
|
||||||
|
+
|
||||||
|
/* We have to drop the new item inside our item list to keep track of it */
|
||||||
|
spin_lock_irqsave(&ep->lock, flags);
|
||||||
|
|
||||||
|
@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
+error_remove_epi:
|
||||||
|
+ spin_lock(&tfile->f_lock);
|
||||||
|
+ if (ep_is_linked(&epi->fllink))
|
||||||
|
+ list_del_init(&epi->fllink);
|
||||||
|
+ spin_unlock(&tfile->f_lock);
|
||||||
|
+
|
||||||
|
+ rb_erase(&epi->rbn, &ep->rbr);
|
||||||
|
+
|
||||||
|
error_unregister:
|
||||||
|
ep_unregister_pollwait(ep, epi);
|
||||||
|
|
||||||
|
@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
|
||||||
|
int error = 0;
|
||||||
|
struct file *file = priv;
|
||||||
|
struct eventpoll *ep = file->private_data;
|
||||||
|
+ struct eventpoll *ep_tovisit;
|
||||||
|
struct rb_node *rbp;
|
||||||
|
struct epitem *epi;
|
||||||
|
|
||||||
|
mutex_lock_nested(&ep->mtx, call_nests + 1);
|
||||||
|
+ ep->visited = 1;
|
||||||
|
+ list_add(&ep->visitedllink, &visited_list);
|
||||||
|
for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
|
||||||
|
epi = rb_entry(rbp, struct epitem, rbn);
|
||||||
|
if (unlikely(is_file_epoll(epi->ffd.file))) {
|
||||||
|
+ ep_tovisit = epi->ffd.file->private_data;
|
||||||
|
+ if (ep_tovisit->visited)
|
||||||
|
+ continue;
|
||||||
|
error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
|
||||||
|
- ep_loop_check_proc, epi->ffd.file,
|
||||||
|
- epi->ffd.file->private_data, current);
|
||||||
|
+ ep_loop_check_proc, epi->ffd.file,
|
||||||
|
+ ep_tovisit, current);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
+ } else {
|
||||||
|
+ /* if we've reached a file that is not associated with
|
||||||
|
+ * an ep, then then we need to check if the newly added
|
||||||
|
+ * links are going to add too many wakeup paths. We do
|
||||||
|
+ * this by adding it to the tfile_check_list, if it's
|
||||||
|
+ * not already there, and calling reverse_path_check()
|
||||||
|
+ * during ep_insert()
|
||||||
|
+ */
|
||||||
|
+ if (list_empty(&epi->ffd.file->f_tfile_llink))
|
||||||
|
+ list_add(&epi->ffd.file->f_tfile_llink,
|
||||||
|
+ &tfile_check_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&ep->mtx);
|
||||||
|
@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
|
||||||
|
*/
|
||||||
|
static int ep_loop_check(struct eventpoll *ep, struct file *file)
|
||||||
|
{
|
||||||
|
- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
|
||||||
|
+ int ret;
|
||||||
|
+ struct eventpoll *ep_cur, *ep_next;
|
||||||
|
+
|
||||||
|
+ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
|
||||||
|
ep_loop_check_proc, file, ep, current);
|
||||||
|
+ /* clear visited list */
|
||||||
|
+ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) {
|
||||||
|
+ ep_cur->visited = 0;
|
||||||
|
+ list_del(&ep_cur->visitedllink);
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void clear_tfile_check_list(void)
|
||||||
|
+{
|
||||||
|
+ struct file *file;
|
||||||
|
+
|
||||||
|
+ /* first clear the tfile_check_list */
|
||||||
|
+ while (!list_empty(&tfile_check_list)) {
|
||||||
|
+ file = list_first_entry(&tfile_check_list, struct file,
|
||||||
|
+ f_tfile_llink);
|
||||||
|
+ list_del_init(&file->f_tfile_llink);
|
||||||
|
+ }
|
||||||
|
+ INIT_LIST_HEAD(&tfile_check_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file)
|
||||||
|
*/
|
||||||
|
SYSCALL_DEFINE1(epoll_create1, int, flags)
|
||||||
|
{
|
||||||
|
- int error;
|
||||||
|
+ int error, fd;
|
||||||
|
struct eventpoll *ep = NULL;
|
||||||
|
+ struct file *file;
|
||||||
|
|
||||||
|
/* Check the EPOLL_* constant for consistency. */
|
||||||
|
BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
|
||||||
|
@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
|
||||||
|
* Creates all the items needed to setup an eventpoll file. That is,
|
||||||
|
* a file structure and a free file descriptor.
|
||||||
|
*/
|
||||||
|
- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
|
||||||
|
+ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC));
|
||||||
|
+ if (fd < 0) {
|
||||||
|
+ error = fd;
|
||||||
|
+ goto out_free_ep;
|
||||||
|
+ }
|
||||||
|
+ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep,
|
||||||
|
O_RDWR | (flags & O_CLOEXEC));
|
||||||
|
- if (error < 0)
|
||||||
|
- ep_free(ep);
|
||||||
|
-
|
||||||
|
+ if (IS_ERR(file)) {
|
||||||
|
+ error = PTR_ERR(file);
|
||||||
|
+ goto out_free_fd;
|
||||||
|
+ }
|
||||||
|
+ fd_install(fd, file);
|
||||||
|
+ ep->file = file;
|
||||||
|
+ return fd;
|
||||||
|
+
|
||||||
|
+out_free_fd:
|
||||||
|
+ put_unused_fd(fd);
|
||||||
|
+out_free_ep:
|
||||||
|
+ ep_free(ep);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
||||||
|
/*
|
||||||
|
* When we insert an epoll file descriptor, inside another epoll file
|
||||||
|
* descriptor, there is the change of creating closed loops, which are
|
||||||
|
- * better be handled here, than in more critical paths.
|
||||||
|
+ * better be handled here, than in more critical paths. While we are
|
||||||
|
+ * checking for loops we also determine the list of files reachable
|
||||||
|
+ * and hang them on the tfile_check_list, so we can check that we
|
||||||
|
+ * haven't created too many possible wakeup paths.
|
||||||
|
*
|
||||||
|
- * We hold epmutex across the loop check and the insert in this case, in
|
||||||
|
- * order to prevent two separate inserts from racing and each doing the
|
||||||
|
- * insert "at the same time" such that ep_loop_check passes on both
|
||||||
|
- * before either one does the insert, thereby creating a cycle.
|
||||||
|
+ * We need to hold the epmutex across both ep_insert and ep_remove
|
||||||
|
+ * b/c we want to make sure we are looking at a coherent view of
|
||||||
|
+ * epoll network.
|
||||||
|
*/
|
||||||
|
- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) {
|
||||||
|
+ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
|
||||||
|
mutex_lock(&epmutex);
|
||||||
|
did_lock_epmutex = 1;
|
||||||
|
- error = -ELOOP;
|
||||||
|
- if (ep_loop_check(ep, tfile) != 0)
|
||||||
|
- goto error_tgt_fput;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ if (op == EPOLL_CTL_ADD) {
|
||||||
|
+ if (is_file_epoll(tfile)) {
|
||||||
|
+ error = -ELOOP;
|
||||||
|
+ if (ep_loop_check(ep, tfile) != 0)
|
||||||
|
+ goto error_tgt_fput;
|
||||||
|
+ } else
|
||||||
|
+ list_add(&tfile->f_tfile_llink, &tfile_check_list);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
mutex_lock_nested(&ep->mtx, 0);
|
||||||
|
|
||||||
|
@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
||||||
|
error = ep_insert(ep, &epds, tfile, fd);
|
||||||
|
} else
|
||||||
|
error = -EEXIST;
|
||||||
|
+ clear_tfile_check_list();
|
||||||
|
break;
|
||||||
|
case EPOLL_CTL_DEL:
|
||||||
|
if (epi)
|
||||||
|
@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
||||||
|
mutex_unlock(&ep->mtx);
|
||||||
|
|
||||||
|
error_tgt_fput:
|
||||||
|
- if (unlikely(did_lock_epmutex))
|
||||||
|
+ if (did_lock_epmutex)
|
||||||
|
mutex_unlock(&epmutex);
|
||||||
|
|
||||||
|
fput(tfile);
|
||||||
|
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
|
||||||
|
index f362733..657ab55 100644
|
||||||
|
--- a/include/linux/eventpoll.h
|
||||||
|
+++ b/include/linux/eventpoll.h
|
||||||
|
@@ -61,6 +61,7 @@ struct file;
|
||||||
|
static inline void eventpoll_init_file(struct file *file)
|
||||||
|
{
|
||||||
|
INIT_LIST_HEAD(&file->f_ep_links);
|
||||||
|
+ INIT_LIST_HEAD(&file->f_tfile_llink);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/include/linux/fs.h b/include/linux/fs.h
|
||||||
|
index 277f497..93778e0 100644
|
||||||
|
--- a/include/linux/fs.h
|
||||||
|
+++ b/include/linux/fs.h
|
||||||
|
@@ -985,6 +985,7 @@ struct file {
|
||||||
|
#ifdef CONFIG_EPOLL
|
||||||
|
/* Used by fs/eventpoll.c to link all the hooks to this file */
|
||||||
|
struct list_head f_ep_links;
|
||||||
|
+ struct list_head f_tfile_llink;
|
||||||
|
#endif /* #ifdef CONFIG_EPOLL */
|
||||||
|
struct address_space *f_mapping;
|
||||||
|
#ifdef CONFIG_DEBUG_WRITECOUNT
|
||||||
|
--
|
||||||
|
1.7.6.4
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
From be31c919e6ff27f1a08bc3e0725c51935313b002 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kara <jack@suse.cz>
|
||||||
|
Date: Tue, 27 Jul 2010 11:56:07 -0400
|
||||||
|
Subject: ext4: Always journal quota file modifications
|
||||||
|
|
||||||
|
When journaled quota options are not specified, we do writes
|
||||||
|
to quota files just in data=ordered mode. This actually causes
|
||||||
|
warnings from JBD2 about dirty journaled buffer because ext4_getblk
|
||||||
|
unconditionally treats a block allocated by it as metadata. Since
|
||||||
|
quota actually is filesystem metadata, the easiest way to get rid
|
||||||
|
of the warning is to always treat quota writes as metadata...
|
||||||
|
|
||||||
|
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||||
|
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
|
||||||
|
---
|
||||||
|
fs/ext4/super.c | 19 +++++--------------
|
||||||
|
1 files changed, 5 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
||||||
|
index a45ced9..f12daa7 100644
|
||||||
|
--- a/fs/ext4/super.c
|
||||||
|
+++ b/fs/ext4/super.c
|
||||||
|
@@ -4030,7 +4030,6 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
|
||||||
|
ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
|
||||||
|
int err = 0;
|
||||||
|
int offset = off & (sb->s_blocksize - 1);
|
||||||
|
- int journal_quota = EXT4_SB(sb)->s_qf_names[type] != NULL;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
handle_t *handle = journal_current_handle();
|
||||||
|
|
||||||
|
@@ -4055,24 +4054,16 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
|
||||||
|
bh = ext4_bread(handle, inode, blk, 1, &err);
|
||||||
|
if (!bh)
|
||||||
|
goto out;
|
||||||
|
- if (journal_quota) {
|
||||||
|
- err = ext4_journal_get_write_access(handle, bh);
|
||||||
|
- if (err) {
|
||||||
|
- brelse(bh);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
+ err = ext4_journal_get_write_access(handle, bh);
|
||||||
|
+ if (err) {
|
||||||
|
+ brelse(bh);
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
lock_buffer(bh);
|
||||||
|
memcpy(bh->b_data+offset, data, len);
|
||||||
|
flush_dcache_page(bh->b_page);
|
||||||
|
unlock_buffer(bh);
|
||||||
|
- if (journal_quota)
|
||||||
|
- err = ext4_handle_dirty_metadata(handle, NULL, bh);
|
||||||
|
- else {
|
||||||
|
- /* Always do at least ordered writes for quotas */
|
||||||
|
- err = ext4_jbd2_file_inode(handle, inode);
|
||||||
|
- mark_buffer_dirty(bh);
|
||||||
|
- }
|
||||||
|
+ err = ext4_handle_dirty_metadata(handle, NULL, bh);
|
||||||
|
brelse(bh);
|
||||||
|
out:
|
||||||
|
if (err) {
|
||||||
|
--
|
||||||
|
1.7.3.3
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
BZ 742091
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=742091
|
||||||
|
|
||||||
|
This bug was never properly fixed upstream since the code got
|
||||||
|
reorganized in:
|
||||||
|
|
||||||
|
667eff35a1f56fa74ce98a0c7c29a40adc1ba4e3 ext4: reimplement convert and
|
||||||
|
split_unwritten
|
||||||
|
|
||||||
|
This fix has proposed by Zheng Liu <wenqing.lz@taobao.com>, then updated,
|
||||||
|
reviewed and tested by me.
|
||||||
|
|
||||||
|
We will meet with a BUG_ON() if following script is run.
|
||||||
|
|
||||||
|
mkfs.ext4 -b 4096 /dev/sdb1 1000000
|
||||||
|
mount -t ext4 /dev/sdb1 /mnt/sdb1
|
||||||
|
fallocate -l 100M /mnt/sdb1/test
|
||||||
|
sync
|
||||||
|
for((i=0;i<170;i++))
|
||||||
|
do
|
||||||
|
dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 seek=`expr $i \* 2`
|
||||||
|
done
|
||||||
|
umount /mnt/sdb1
|
||||||
|
mount -t ext4 /dev/sdb1 /mnt/sdb1
|
||||||
|
dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 seek=341
|
||||||
|
umount /mnt/sdb1
|
||||||
|
mount /dev/sdb1 /mnt/sdb1
|
||||||
|
dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 seek=340
|
||||||
|
sync
|
||||||
|
|
||||||
|
The reason is that it forgot to mark dirty when splitting two extents in
|
||||||
|
ext4_ext_convert_to_initialized(). Althrough ex has been updated in memory,
|
||||||
|
it is not dirtied both in ext4_ext_convert_to_initialized() and
|
||||||
|
ext4_ext_insert_extent(). The disk layout is corrupted. Then it will meet with
|
||||||
|
a BUG_ON() when writting at the start of that extent again.
|
||||||
|
|
||||||
|
Originally-from: Zheng Liu <wenqing.lz@taobao.com>
|
||||||
|
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
|
||||||
|
---
|
||||||
|
fs/ext4/extents.c | 2 ++
|
||||||
|
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
Index: linux-2.6.35.noarch/fs/ext4/extents.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.35.noarch.orig/fs/ext4/extents.c
|
||||||
|
+++ linux-2.6.35.noarch/fs/ext4/extents.c
|
||||||
|
@@ -2687,6 +2687,7 @@ static int ext4_ext_convert_to_initializ
|
||||||
|
ex1 = ex;
|
||||||
|
ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
|
||||||
|
ext4_ext_mark_uninitialized(ex1);
|
||||||
|
+ ext4_ext_dirty(handle, inode, path + depth);
|
||||||
|
ex2 = &newex;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
@@ -2850,6 +2851,7 @@ static int ext4_ext_convert_to_initializ
|
||||||
|
ex1 = ex;
|
||||||
|
ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
|
||||||
|
ext4_ext_mark_uninitialized(ex1);
|
||||||
|
+ ext4_ext_dirty(handle, inode, path + depth);
|
||||||
|
ex2 = &newex;
|
||||||
|
}
|
||||||
|
/* ex2: map->m_lblk to map->m_lblk + maxblocks-1 : initialised */
|
|
@ -0,0 +1,258 @@
|
||||||
|
From: Lukas Czerner <lczerner@redhat.com>
|
||||||
|
Date: Mon, 6 Jun 2011 04:05:17 +0000 (-0400)
|
||||||
|
Subject: ext4: Fix max file size and logical block counting of extent format file
|
||||||
|
X-Git-Tag: v3.0-rc5~53^2~4
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f17722f917b2f21497deb6edc62fb1683daa08e6
|
||||||
|
|
||||||
|
ext4: Fix max file size and logical block counting of extent format file
|
||||||
|
|
||||||
|
[ backport for 2.6.35 ]
|
||||||
|
|
||||||
|
Kazuya Mio reported that he was able to hit BUG_ON(next == lblock)
|
||||||
|
in ext4_ext_put_gap_in_cache() while creating a sparse file in extent
|
||||||
|
format and fill the tail of file up to its end. We will hit the BUG_ON
|
||||||
|
when we write the last block (2^32-1) into the sparse file.
|
||||||
|
|
||||||
|
The root cause of the problem lies in the fact that we specifically set
|
||||||
|
s_maxbytes so that block at s_maxbytes fit into on-disk extent format,
|
||||||
|
which is 32 bit long. However, we are not storing start and end block
|
||||||
|
number, but rather start block number and length in blocks. It means
|
||||||
|
that in order to cover extent from 0 to EXT_MAX_BLOCK we need
|
||||||
|
EXT_MAX_BLOCK+1 to fit into len (because we counting block 0 as well) -
|
||||||
|
and it does not.
|
||||||
|
|
||||||
|
The only way to fix it without changing the meaning of the struct
|
||||||
|
ext4_extent members is, as Kazuya Mio suggested, to lower s_maxbytes
|
||||||
|
by one fs block so we can cover the whole extent we can get by the
|
||||||
|
on-disk extent format.
|
||||||
|
|
||||||
|
Also in many places EXT_MAX_BLOCK is used as length instead of maximum
|
||||||
|
logical block number as the name suggests, it is all a bit messy. So
|
||||||
|
this commit renames it to EXT_MAX_BLOCKS and change its usage in some
|
||||||
|
places to actually be maximum number of blocks in the extent.
|
||||||
|
|
||||||
|
The bug which this commit fixes can be reproduced as follows:
|
||||||
|
|
||||||
|
dd if=/dev/zero of=/mnt/mp1/file bs=<blocksize> count=1 seek=$((2**32-2))
|
||||||
|
sync
|
||||||
|
dd if=/dev/zero of=/mnt/mp1/file bs=<blocksize> count=1 seek=$((2**32-1))
|
||||||
|
|
||||||
|
Reported-by: Kazuya Mio <k-mio@sx.jp.nec.com>
|
||||||
|
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
|
||||||
|
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
|
||||||
|
index 2e29abb..4764146 100644
|
||||||
|
--- a/fs/ext4/ext4_extents.h
|
||||||
|
+++ b/fs/ext4/ext4_extents.h
|
||||||
|
@@ -133,8 +133,11 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
|
||||||
|
#define EXT_BREAK 1
|
||||||
|
#define EXT_REPEAT 2
|
||||||
|
|
||||||
|
-/* Maximum logical block in a file; ext4_extent's ee_block is __le32 */
|
||||||
|
-#define EXT_MAX_BLOCK 0xffffffff
|
||||||
|
+/*
|
||||||
|
+ * Maximum number of logical blocks in a file; ext4_extent's ee_block is
|
||||||
|
+ * __le32.
|
||||||
|
+ */
|
||||||
|
+#define EXT_MAX_BLOCKS 0xffffffff
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
|
||||||
|
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
|
||||||
|
index 5199bac..4157570 100644
|
||||||
|
--- a/fs/ext4/extents.c
|
||||||
|
+++ b/fs/ext4/extents.c
|
||||||
|
@@ -1408,7 +1408,7 @@ got_index:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ext4_ext_next_allocated_block:
|
||||||
|
- * returns allocated block in subsequent extent or EXT_MAX_BLOCK.
|
||||||
|
+ * returns allocated block in subsequent extent or EXT_MAX_BLOCKS.
|
||||||
|
* NOTE: it considers block number from index entry as
|
||||||
|
* allocated block. Thus, index entries have to be consistent
|
||||||
|
* with leaves.
|
||||||
|
@@ -1422,7 +1422,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
|
||||||
|
depth = path->p_depth;
|
||||||
|
|
||||||
|
if (depth == 0 && path->p_ext == NULL)
|
||||||
|
- return EXT_MAX_BLOCK;
|
||||||
|
+ return EXT_MAX_BLOCKS;
|
||||||
|
|
||||||
|
while (depth >= 0) {
|
||||||
|
if (depth == path->p_depth) {
|
||||||
|
@@ -1439,12 +1439,12 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return EXT_MAX_BLOCK;
|
||||||
|
+ return EXT_MAX_BLOCKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ext4_ext_next_leaf_block:
|
||||||
|
- * returns first allocated block from next leaf or EXT_MAX_BLOCK
|
||||||
|
+ * returns first allocated block from next leaf or EXT_MAX_BLOCKS
|
||||||
|
*/
|
||||||
|
static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
|
||||||
|
struct ext4_ext_path *path)
|
||||||
|
@@ -1456,7 +1456,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
|
||||||
|
|
||||||
|
/* zero-tree has no leaf blocks at all */
|
||||||
|
if (depth == 0)
|
||||||
|
- return EXT_MAX_BLOCK;
|
||||||
|
+ return EXT_MAX_BLOCKS;
|
||||||
|
|
||||||
|
/* go to index block */
|
||||||
|
depth--;
|
||||||
|
@@ -1469,7 +1469,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return EXT_MAX_BLOCK;
|
||||||
|
+ return EXT_MAX_BLOCKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1677,13 +1677,13 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
|
||||||
|
*/
|
||||||
|
if (b2 < b1) {
|
||||||
|
b2 = ext4_ext_next_allocated_block(path);
|
||||||
|
- if (b2 == EXT_MAX_BLOCK)
|
||||||
|
+ if (b2 == EXT_MAX_BLOCKS)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for wrap through zero on extent logical start block*/
|
||||||
|
if (b1 + len1 < b1) {
|
||||||
|
- len1 = EXT_MAX_BLOCK - b1;
|
||||||
|
+ len1 = EXT_MAX_BLOCKS - b1;
|
||||||
|
newext->ee_len = cpu_to_le16(len1);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
@@ -1767,7 +1767,7 @@ repeat:
|
||||||
|
fex = EXT_LAST_EXTENT(eh);
|
||||||
|
next = ext4_ext_next_leaf_block(inode, path);
|
||||||
|
if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block)
|
||||||
|
- && next != EXT_MAX_BLOCK) {
|
||||||
|
+ && next != EXT_MAX_BLOCKS) {
|
||||||
|
ext_debug("next leaf block - %d\n", next);
|
||||||
|
BUG_ON(npath != NULL);
|
||||||
|
npath = ext4_ext_find_extent(inode, next, NULL);
|
||||||
|
@@ -1887,7 +1887,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
|
||||||
|
BUG_ON(func == NULL);
|
||||||
|
BUG_ON(inode == NULL);
|
||||||
|
|
||||||
|
- while (block < last && block != EXT_MAX_BLOCK) {
|
||||||
|
+ while (block < last && block != EXT_MAX_BLOCKS) {
|
||||||
|
num = last - block;
|
||||||
|
/* find extent for this block */
|
||||||
|
down_read(&EXT4_I(inode)->i_data_sem);
|
||||||
|
@@ -2020,7 +2020,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
|
||||||
|
if (ex == NULL) {
|
||||||
|
/* there is no extent yet, so gap is [0;-] */
|
||||||
|
lblock = 0;
|
||||||
|
- len = EXT_MAX_BLOCK;
|
||||||
|
+ len = EXT_MAX_BLOCKS;
|
||||||
|
ext_debug("cache gap(whole file):");
|
||||||
|
} else if (block < le32_to_cpu(ex->ee_block)) {
|
||||||
|
lblock = block;
|
||||||
|
@@ -2239,8 +2239,8 @@ ext4_ext_rm_leaf(handle_t *handle, struc
|
||||||
|
path[depth].p_ext = ex;
|
||||||
|
|
||||||
|
a = ex_ee_block > start ? ex_ee_block : start;
|
||||||
|
- b = ex_ee_block + ex_ee_len - 1 < EXT_MAX_BLOCK ?
|
||||||
|
- ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCK;
|
||||||
|
+ b = ex_ee_block + ex_ee_len - 1 < EXT_MAX_BLOCKS ?
|
||||||
|
+ ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCKS;
|
||||||
|
|
||||||
|
ext_debug(" border %u:%u\n", a, b);
|
||||||
|
|
||||||
|
@@ -3869,15 +3869,15 @@ static int ext4_ext_fiemap_cb(struct ino
|
||||||
|
flags |= FIEMAP_EXTENT_UNWRITTEN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * If this extent reaches EXT_MAX_BLOCK, it must be last.
|
||||||
|
+ * If this extent reaches EXT_MAX_BLOCKS, it must be last.
|
||||||
|
*
|
||||||
|
- * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK,
|
||||||
|
+ * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCKS,
|
||||||
|
* this also indicates no more allocated blocks.
|
||||||
|
*
|
||||||
|
* XXX this might miss a single-block extent at EXT_MAX_BLOCK
|
||||||
|
*/
|
||||||
|
- if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK ||
|
||||||
|
- newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) {
|
||||||
|
+ if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCKS ||
|
||||||
|
+ newex->ec_block + newex->ec_len == EXT_MAX_BLOCKS) {
|
||||||
|
loff_t size = i_size_read(inode);
|
||||||
|
loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb);
|
||||||
|
|
||||||
|
@@ -4347,8 +4347,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||||
|
|
||||||
|
start_blk = start >> inode->i_sb->s_blocksize_bits;
|
||||||
|
last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits;
|
||||||
|
- if (last_blk >= EXT_MAX_BLOCK)
|
||||||
|
- last_blk = EXT_MAX_BLOCK-1;
|
||||||
|
+ if (last_blk >= EXT_MAX_BLOCKS)
|
||||||
|
+ last_blk = EXT_MAX_BLOCKS-1;
|
||||||
|
len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
|
||||||
|
index 2b8304b..f57455a 100644
|
||||||
|
--- a/fs/ext4/move_extent.c
|
||||||
|
+++ b/fs/ext4/move_extent.c
|
||||||
|
@@ -1002,12 +1002,12 @@ mext_check_arguments(struct inode *orig_inode,
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((orig_start > EXT_MAX_BLOCK) ||
|
||||||
|
- (donor_start > EXT_MAX_BLOCK) ||
|
||||||
|
- (*len > EXT_MAX_BLOCK) ||
|
||||||
|
- (orig_start + *len > EXT_MAX_BLOCK)) {
|
||||||
|
+ if ((orig_start >= EXT_MAX_BLOCKS) ||
|
||||||
|
+ (donor_start >= EXT_MAX_BLOCKS) ||
|
||||||
|
+ (*len > EXT_MAX_BLOCKS) ||
|
||||||
|
+ (orig_start + *len >= EXT_MAX_BLOCKS)) {
|
||||||
|
ext4_debug("ext4 move extent: Can't handle over [%u] blocks "
|
||||||
|
- "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCK,
|
||||||
|
+ "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS,
|
||||||
|
orig_inode->i_ino, donor_inode->i_ino);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
||||||
|
index cc5c157..9ea71aa 100644
|
||||||
|
--- a/fs/ext4/super.c
|
||||||
|
+++ b/fs/ext4/super.c
|
||||||
|
@@ -2243,6 +2243,12 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
||||||
|
* in the vfs. ext4 inode has 48 bits of i_block in fsblock units,
|
||||||
|
* so that won't be a limiting factor.
|
||||||
|
*
|
||||||
|
+ * However there is other limiting factor. We do store extents in the form
|
||||||
|
+ * of starting block and length, hence the resulting length of the extent
|
||||||
|
+ * covering maximum file size must fit into on-disk format containers as
|
||||||
|
+ * well. Given that length is always by 1 unit bigger than max unit (because
|
||||||
|
+ * we count 0 as well) we have to lower the s_maxbytes by one fs block.
|
||||||
|
+ *
|
||||||
|
* Note, this does *not* consider any metadata overhead for vfs i_blocks.
|
||||||
|
*/
|
||||||
|
static loff_t ext4_max_size(int blkbits, int has_huge_files)
|
||||||
|
@@ -2264,10 +2270,13 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files)
|
||||||
|
upper_limit <<= blkbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* 32-bit extent-start container, ee_block */
|
||||||
|
- res = 1LL << 32;
|
||||||
|
+ /*
|
||||||
|
+ * 32-bit extent-start container, ee_block. We lower the maxbytes
|
||||||
|
+ * by one fs block, so ee_len can cover the extent of maximum file
|
||||||
|
+ * size
|
||||||
|
+ */
|
||||||
|
+ res = (1LL << 32) - 1;
|
||||||
|
res <<= blkbits;
|
||||||
|
- res -= 1;
|
||||||
|
|
||||||
|
/* Sanity check against vm- & vfs- imposed limits */
|
||||||
|
if (res > upper_limit)
|
|
@ -0,0 +1,27 @@
|
||||||
|
diff --git a/kernel/sched.c b/kernel/sched.c
|
||||||
|
index 6d0dbeb..3640c20 100644
|
||||||
|
--- a/kernel/sched.c
|
||||||
|
+++ b/kernel/sched.c
|
||||||
|
@@ -5155,9 +5155,11 @@ void __cpuinit init_idle_bootup_task(struct task_struct *idle)
|
||||||
|
void __cpuinit init_idle(struct task_struct *idle, int cpu)
|
||||||
|
{
|
||||||
|
struct rq *rq = cpu_rq(cpu);
|
||||||
|
+ struct rq *oldrq = task_rq(idle);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
- raw_spin_lock_irqsave(&rq->lock, flags);
|
||||||
|
+ local_irq_save(flags);
|
||||||
|
+ double_rq_lock(oldrq, rq);
|
||||||
|
|
||||||
|
__sched_fork(idle);
|
||||||
|
idle->state = TASK_RUNNING;
|
||||||
|
@@ -5170,7 +5172,8 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
|
||||||
|
#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
|
||||||
|
idle->oncpu = 1;
|
||||||
|
#endif
|
||||||
|
- raw_spin_unlock_irqrestore(&rq->lock, flags);
|
||||||
|
+ double_rq_unlock(oldrq, rq);
|
||||||
|
+ local_irq_restore(flags);
|
||||||
|
|
||||||
|
/* Set the preempt count _outside_ the spinlocks! */
|
||||||
|
#if defined(CONFIG_PREEMPT)
|
|
@ -0,0 +1,34 @@
|
||||||
|
From 6a7fc984c7bd3c98839e28c47f4a9a27af024ca7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Miklos Szeredi <mszeredi@suse.cz>
|
||||||
|
Date: Wed, 24 Aug 2011 10:20:17 +0200
|
||||||
|
Subject: [PATCH] fuse: check size of FUSE_NOTIFY_INVAL_ENTRY message
|
||||||
|
|
||||||
|
FUSE_NOTIFY_INVAL_ENTRY didn't check the length of the write so the
|
||||||
|
message processing could overrun and result in a "kernel BUG at
|
||||||
|
fs/fuse/dev.c:629!"
|
||||||
|
|
||||||
|
Reported-by: Han-Wen Nienhuys <hanwenn@gmail.com>
|
||||||
|
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
|
||||||
|
CC: stable@kernel.org
|
||||||
|
---
|
||||||
|
fs/fuse/dev.c | 4 ++++
|
||||||
|
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||||
|
index e5cdabf..517430a 100644
|
||||||
|
--- a/fs/fuse/dev.c
|
||||||
|
+++ b/fs/fuse/dev.c
|
||||||
|
@@ -1208,6 +1208,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
|
||||||
|
if (outarg.namelen > FUSE_NAME_MAX)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
+ err = -EINVAL;
|
||||||
|
+ if (size != sizeof(outarg) + outarg.namelen + 1)
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
name.name = buf;
|
||||||
|
name.len = outarg.namelen;
|
||||||
|
err = fuse_copy_one(cs, buf, outarg.namelen + 1);
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
From 17dd759c67f21e34f2156abcf415e1f60605a188 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
Date: Wed, 27 Jul 2011 06:16:28 -0700
|
||||||
|
Subject: [PATCH] gro: Only reset frag0 when skb can be pulled
|
||||||
|
|
||||||
|
Currently skb_gro_header_slow unconditionally resets frag0 and
|
||||||
|
frag0_len. However, when we can't pull on the skb this leaves
|
||||||
|
the GRO fields in an inconsistent state.
|
||||||
|
|
||||||
|
This patch fixes this by only resetting those fields after the
|
||||||
|
pskb_may_pull test.
|
||||||
|
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
include/linux/netdevice.h | 5 ++++-
|
||||||
|
1 files changed, 4 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
|
||||||
|
index 1d92acc..661a077 100644
|
||||||
|
--- a/include/linux/netdevice.h
|
||||||
|
+++ b/include/linux/netdevice.h
|
||||||
|
@@ -1649,9 +1649,12 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
|
||||||
|
static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
|
||||||
|
unsigned int offset)
|
||||||
|
{
|
||||||
|
+ if (!pskb_may_pull(skb, hlen))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
NAPI_GRO_CB(skb)->frag0 = NULL;
|
||||||
|
NAPI_GRO_CB(skb)->frag0_len = 0;
|
||||||
|
- return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
|
||||||
|
+ return skb->data + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *skb_gro_mac_header(struct sk_buff *skb)
|
||||||
|
--
|
||||||
|
1.7.6
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
From: Hendrik Iben <Hendrik_Iben@web.de>
|
||||||
|
Date: Mon, 4 Oct 2010 13:39:49 +0000 (+0200)
|
||||||
|
Subject: HID: force feedback support for Logitech RumblePad gamepad
|
||||||
|
X-Git-Tag: v2.6.37-rc1~144^2~3^4
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=2c6118e43040034d80894daeba41960bf0035b31
|
||||||
|
|
||||||
|
HID: force feedback support for Logitech RumblePad gamepad
|
||||||
|
|
||||||
|
This patch adds force feedback support for Logitech WingMan RumblePad
|
||||||
|
gamepads by extending the Logitech Rumblepad 2 force feedback code.
|
||||||
|
|
||||||
|
Signed-off-by: Hendrik Iben <Hendrik_Iben@web.de>
|
||||||
|
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||||
|
index 6664c57..3892ff5 100644
|
||||||
|
--- a/drivers/hid/Kconfig
|
||||||
|
+++ b/drivers/hid/Kconfig
|
||||||
|
@@ -220,12 +220,12 @@ config LOGITECH_FF
|
||||||
|
force feedback.
|
||||||
|
|
||||||
|
config LOGIRUMBLEPAD2_FF
|
||||||
|
- bool "Logitech Rumblepad 2 force feedback support"
|
||||||
|
+ bool "Logitech RumblePad/Rumblepad 2 force feedback support"
|
||||||
|
depends on HID_LOGITECH
|
||||||
|
select INPUT_FF_MEMLESS
|
||||||
|
help
|
||||||
|
Say Y here if you want to enable force feedback support for Logitech
|
||||||
|
- Rumblepad 2 devices.
|
||||||
|
+ RumblePad and Rumblepad 2 devices.
|
||||||
|
|
||||||
|
config LOGIG940_FF
|
||||||
|
bool "Logitech Flight System G940 force feedback support"
|
||||||
|
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||||||
|
index 19d4547..0120557 100644
|
||||||
|
--- a/drivers/hid/hid-core.c
|
||||||
|
+++ b/drivers/hid/hid-core.c
|
||||||
|
@@ -1326,6 +1326,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
|
||||||
|
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||||
|
index 6b111e1..79f0304 100644
|
||||||
|
--- a/drivers/hid/hid-ids.h
|
||||||
|
+++ b/drivers/hid/hid-ids.h
|
||||||
|
@@ -339,6 +339,7 @@
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
|
||||||
|
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
|
||||||
|
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
|
||||||
|
index 8989f15..9e92c27 100644
|
||||||
|
--- a/drivers/hid/hid-lg.c
|
||||||
|
+++ b/drivers/hid/hid-lg.c
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
* Copyright (c) 2006-2007 Jiri Kosina
|
||||||
|
* Copyright (c) 2007 Paul Walmsley
|
||||||
|
* Copyright (c) 2008 Jiri Slaby
|
||||||
|
+ * Copyright (c) 2010 Hendrik Iben
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -361,6 +362,8 @@ static const struct hid_device_id lg_devices[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
|
||||||
|
.driver_data = LG_NOGET | LG_FF },
|
||||||
|
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
|
||||||
|
+ .driver_data = LG_FF2 },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
|
||||||
|
.driver_data = LG_FF },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
|
||||||
|
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
|
||||||
|
index d888f1e..4258253 100644
|
||||||
|
--- a/drivers/hid/hid-lg2ff.c
|
||||||
|
+++ b/drivers/hid/hid-lg2ff.c
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
/*
|
||||||
|
- * Force feedback support for Logitech Rumblepad 2
|
||||||
|
+ * Force feedback support for Logitech RumblePad and Rumblepad 2
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com>
|
||||||
|
*/
|
||||||
|
@@ -110,7 +110,7 @@ int lg2ff_init(struct hid_device *hid)
|
||||||
|
|
||||||
|
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||||
|
|
||||||
|
- dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by "
|
||||||
|
+ dev_info(&hid->dev, "Force feedback for Logitech RumblePad/Rumblepad 2 by "
|
||||||
|
"Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||||
|
|
||||||
|
return 0;
|
|
@ -0,0 +1,163 @@
|
||||||
|
[PATCH] hid: support for bluetooth tivo slide remote and usb dongle
|
||||||
|
|
||||||
|
This patch adds full support for the TiVo Slide Remote, primarily by way
|
||||||
|
of extending the existing generic HID support. Only four keys are not
|
||||||
|
usages within a standard usage page, but they're easily handled by the
|
||||||
|
addition of a HID_UP_TIVOVENDOR usage page. Note that the UP is 0xffff,
|
||||||
|
which matches the mask, but its also a valid vendor-specific UP, according
|
||||||
|
to the spec.
|
||||||
|
|
||||||
|
What's actually connected to the computer is a Broadcom-made usb dongle,
|
||||||
|
which has an embedded hub, bluetooth adapter, mouse and keyboard devices.
|
||||||
|
You pair with the dongle, then the remote sends data that its converted
|
||||||
|
into HID on the keyboard interface (the mouse interface doesn't do anything
|
||||||
|
interesting right now, so far as I can tell).
|
||||||
|
|
||||||
|
lsusb for this device:
|
||||||
|
Bus 004 Device 005: ID 0a5c:2190 Broadcom Corp.
|
||||||
|
Bus 004 Device 004: ID 0a5c:4503 Broadcom Corp.
|
||||||
|
Bus 004 Device 003: ID 150a:1201
|
||||||
|
Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)
|
||||||
|
|
||||||
|
Speaking of the keyboard interface, the remote actually does contain a
|
||||||
|
keyboard as well. The top slides away, revealing a reasonably functional
|
||||||
|
qwerty keyboard (not unlike many slide cell phones), thus the product
|
||||||
|
name.
|
||||||
|
|
||||||
|
Now for some caveats... This device seems to report 0xc (consumer usage
|
||||||
|
page) 0x20 ("+10") after most key presses. At the moment, this will simply
|
||||||
|
be ignored, but if a mapping for that usage is added, the remote behaves
|
||||||
|
very badly (we end up w/a repeating/stuck key until another key is pressed).
|
||||||
|
Not quite sure what to do about that one, if that usage does get mapped. I
|
||||||
|
guess a device-specific quirk to just ignore it would work.
|
||||||
|
|
||||||
|
Anyway, the thing is working 100% as expected with this patch right now.
|
||||||
|
|
||||||
|
Three more things to note... This patch fixes an incorrect mapping of 0xc 0x45,
|
||||||
|
which was mapped to KEY_RADIO, which is definitely wrong, but may cause some
|
||||||
|
existing device to now report KEY_RIGHT there. Second, there's also an
|
||||||
|
unrelated fix for a redundant KERN_DEBUG in a dbg_hid call. Third, the
|
||||||
|
additions to HID_UP_GENDESK aren't strictly needed by the remote, but the
|
||||||
|
dongle does try to register those, and they're all technically correct, so
|
||||||
|
I've included them for the benefit of a device that comes along and
|
||||||
|
actually does try to use them.
|
||||||
|
|
||||||
|
Applies cleanly to hid master, tested w/a 2.6.35.4-based Fedora kernel.
|
||||||
|
|
||||||
|
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/hid/hid-input.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
|
||||||
|
include/linux/hid.h | 1 +
|
||||||
|
2 files changed, 41 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
|
||||||
|
index 6c03dcc..bd1479e 100644
|
||||||
|
--- a/drivers/hid/hid-input.c
|
||||||
|
+++ b/drivers/hid/hid-input.c
|
||||||
|
@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = {
|
||||||
|
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
|
||||||
|
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
|
||||||
|
115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
|
||||||
|
- 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
+ 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
|
||||||
|
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
+ unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
|
||||||
|
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
|
||||||
|
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
|
||||||
|
};
|
||||||
|
@@ -136,7 +136,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
|
||||||
|
|
||||||
|
clear_bit(old_keycode, dev->keybit);
|
||||||
|
set_bit(usage->code, dev->keybit);
|
||||||
|
- dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
|
||||||
|
+ dbg_hid("Assigned keycode %d to HID usage code %x\n", keycode, scancode);
|
||||||
|
/* Set the keybit for the old keycode if the old keycode is used
|
||||||
|
* by another key */
|
||||||
|
if (hidinput_find_key (hid, 0, old_keycode))
|
||||||
|
@@ -235,6 +235,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
|
case 0x1: map_key_clear(KEY_POWER); break;
|
||||||
|
case 0x2: map_key_clear(KEY_SLEEP); break;
|
||||||
|
case 0x3: map_key_clear(KEY_WAKEUP); break;
|
||||||
|
+ case 0x4: map_key_clear(KEY_CONTEXT_MENU); break;
|
||||||
|
+ case 0x5: map_key_clear(KEY_MENU); break;
|
||||||
|
+ case 0x6: map_key_clear(KEY_PROG1); break;
|
||||||
|
+ case 0x7: map_key_clear(KEY_HELP); break;
|
||||||
|
+ case 0x8: map_key_clear(KEY_EXIT); break;
|
||||||
|
+ case 0x9: map_key_clear(KEY_SELECT); break;
|
||||||
|
+ case 0xa: map_key_clear(KEY_RIGHT); break;
|
||||||
|
+ case 0xb: map_key_clear(KEY_LEFT); break;
|
||||||
|
+ case 0xc: map_key_clear(KEY_UP); break;
|
||||||
|
+ case 0xd: map_key_clear(KEY_DOWN); break;
|
||||||
|
+ case 0xe: map_key_clear(KEY_POWER2); break;
|
||||||
|
+ case 0xf: map_key_clear(KEY_RESTART); break;
|
||||||
|
default: goto unknown;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
@@ -343,12 +355,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
|
case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
|
||||||
|
switch (usage->hid & HID_USAGE) {
|
||||||
|
case 0x000: goto ignore;
|
||||||
|
+ case 0x030: map_key_clear(KEY_POWER); break;
|
||||||
|
case 0x034: map_key_clear(KEY_SLEEP); break;
|
||||||
|
case 0x036: map_key_clear(BTN_MISC); break;
|
||||||
|
|
||||||
|
case 0x040: map_key_clear(KEY_MENU); break;
|
||||||
|
- case 0x045: map_key_clear(KEY_RADIO); break;
|
||||||
|
-
|
||||||
|
+ case 0x041: map_key_clear(KEY_SELECT); break;
|
||||||
|
+ case 0x042: map_key_clear(KEY_UP); break;
|
||||||
|
+ case 0x043: map_key_clear(KEY_DOWN); break;
|
||||||
|
+ case 0x044: map_key_clear(KEY_LEFT); break;
|
||||||
|
+ case 0x045: map_key_clear(KEY_RIGHT); break;
|
||||||
|
+
|
||||||
|
+ case 0x069: map_key_clear(KEY_RED); break;
|
||||||
|
+ case 0x06a: map_key_clear(KEY_GREEN); break;
|
||||||
|
+ case 0x06b: map_key_clear(KEY_BLUE); break;
|
||||||
|
+ case 0x06c: map_key_clear(KEY_YELLOW); break;
|
||||||
|
+ case 0x06d: map_key_clear(KEY_ZOOM); break;
|
||||||
|
+
|
||||||
|
+ case 0x082: map_key_clear(KEY_VIDEO_NEXT); break;
|
||||||
|
case 0x083: map_key_clear(KEY_LAST); break;
|
||||||
|
case 0x088: map_key_clear(KEY_PC); break;
|
||||||
|
case 0x089: map_key_clear(KEY_TV); break;
|
||||||
|
@@ -390,6 +414,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
|
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
|
||||||
|
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
|
||||||
|
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
|
||||||
|
+ case 0x0f5: map_key_clear(KEY_SLOW); break;
|
||||||
|
|
||||||
|
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
|
||||||
|
case 0x183: map_key_clear(KEY_CONFIG); break;
|
||||||
|
@@ -491,6 +516,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case HID_UP_TIVOVENDOR:
|
||||||
|
+ switch (usage->hid & HID_USAGE) {
|
||||||
|
+ case 0x3d: map_key_clear(KEY_PROG1); break;
|
||||||
|
+ case 0x3e: map_key_clear(KEY_TV); break;
|
||||||
|
+ case 0x41: map_key_clear(KEY_PAGEDOWN); break;
|
||||||
|
+ case 0x42: map_key_clear(KEY_PAGEUP); break;
|
||||||
|
+ default: goto unknown;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
default:
|
||||||
|
unknown:
|
||||||
|
if (field->report_size == 1) {
|
||||||
|
diff --git a/include/linux/hid.h b/include/linux/hid.h
|
||||||
|
index 42a0f1d..083cfb2 100644
|
||||||
|
--- a/include/linux/hid.h
|
||||||
|
+++ b/include/linux/hid.h
|
||||||
|
@@ -200,6 +200,7 @@ struct hid_item {
|
||||||
|
#define HID_UP_MSVENDOR 0xff000000
|
||||||
|
#define HID_UP_CUSTOM 0x00ff0000
|
||||||
|
#define HID_UP_LOGIVENDOR 0xffbc0000
|
||||||
|
+#define HID_UP_TIVOVENDOR 0xffff0000
|
||||||
|
|
||||||
|
#define HID_USAGE 0x0000ffff
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
From 785465d9cffd65b5a69dd2f465d2f7c917713220 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kyle McMartin <kyle@mcmartin.ca>
|
||||||
|
Date: Mon, 18 Oct 2010 13:30:39 -0400
|
||||||
|
Subject: [PATCH] ima: provide a toggle to disable it entirely
|
||||||
|
|
||||||
|
Signed-off-by: Kyle McMartin <kyle@redhat.com>
|
||||||
|
---
|
||||||
|
security/integrity/ima/ima.h | 1 +
|
||||||
|
security/integrity/ima/ima_iint.c | 9 +++++++++
|
||||||
|
security/integrity/ima/ima_main.c | 24 +++++++++++++++++++++---
|
||||||
|
3 files changed, 31 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
|
||||||
|
index 3fbcd1d..65c3977 100644
|
||||||
|
--- a/security/integrity/ima/ima.h
|
||||||
|
+++ b/security/integrity/ima/ima.h
|
||||||
|
@@ -37,6 +37,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
|
||||||
|
/* set during initialization */
|
||||||
|
extern int iint_initialized;
|
||||||
|
extern int ima_initialized;
|
||||||
|
+extern int ima_enabled;
|
||||||
|
extern int ima_used_chip;
|
||||||
|
extern char *ima_hash;
|
||||||
|
|
||||||
|
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
|
||||||
|
index afba4ae..3d191ef 100644
|
||||||
|
--- a/security/integrity/ima/ima_iint.c
|
||||||
|
+++ b/security/integrity/ima/ima_iint.c
|
||||||
|
@@ -54,6 +54,9 @@ int ima_inode_alloc(struct inode *inode)
|
||||||
|
struct ima_iint_cache *iint = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
|
||||||
|
if (!iint)
|
||||||
|
return -ENOMEM;
|
||||||
|
@@ -116,6 +119,9 @@ void ima_inode_free(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct ima_iint_cache *iint;
|
||||||
|
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
spin_lock(&ima_iint_lock);
|
||||||
|
iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
|
||||||
|
spin_unlock(&ima_iint_lock);
|
||||||
|
@@ -139,6 +145,9 @@ static void init_once(void *foo)
|
||||||
|
|
||||||
|
static int __init ima_iintcache_init(void)
|
||||||
|
{
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
iint_cache =
|
||||||
|
kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
|
||||||
|
SLAB_PANIC, init_once);
|
||||||
|
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
|
||||||
|
index e662b89..6e91905 100644
|
||||||
|
--- a/security/integrity/ima/ima_main.c
|
||||||
|
+++ b/security/integrity/ima/ima_main.c
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#include "ima.h"
|
||||||
|
|
||||||
|
int ima_initialized;
|
||||||
|
+int ima_enabled;
|
||||||
|
|
||||||
|
char *ima_hash = "sha1";
|
||||||
|
static int __init hash_setup(char *str)
|
||||||
|
@@ -36,6 +37,14 @@ static int __init hash_setup(char *str)
|
||||||
|
}
|
||||||
|
__setup("ima_hash=", hash_setup);
|
||||||
|
|
||||||
|
+static int __init ima_enable(char *str)
|
||||||
|
+{
|
||||||
|
+ if (strncmp(str, "on", 2) == 0)
|
||||||
|
+ ima_enabled = 1;
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+__setup("ima=", ima_enable);
|
||||||
|
+
|
||||||
|
struct ima_imbalance {
|
||||||
|
struct hlist_node node;
|
||||||
|
unsigned long fsmagic;
|
||||||
|
@@ -148,7 +157,7 @@ void ima_counts_get(struct file *file)
|
||||||
|
struct ima_iint_cache *iint;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- if (!iint_initialized || !S_ISREG(inode->i_mode))
|
||||||
|
+ if (!ima_enabled || !iint_initialized || !S_ISREG(inode->i_mode))
|
||||||
|
return;
|
||||||
|
iint = ima_iint_find_get(inode);
|
||||||
|
if (!iint)
|
||||||
|
@@ -215,7 +224,7 @@ void ima_file_free(struct file *file)
|
||||||
|
struct inode *inode = file->f_dentry->d_inode;
|
||||||
|
struct ima_iint_cache *iint;
|
||||||
|
|
||||||
|
- if (!iint_initialized || !S_ISREG(inode->i_mode))
|
||||||
|
+ if (!ima_enabled || !iint_initialized || !S_ISREG(inode->i_mode))
|
||||||
|
return;
|
||||||
|
iint = ima_iint_find_get(inode);
|
||||||
|
if (!iint)
|
||||||
|
@@ -269,7 +278,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- if (!file)
|
||||||
|
+ if (!ima_enabled || !file)
|
||||||
|
return 0;
|
||||||
|
if (prot & PROT_EXEC)
|
||||||
|
rc = process_measurement(file, file->f_dentry->d_name.name,
|
||||||
|
@@ -294,6 +303,9 @@ int ima_bprm_check(struct linux_binprm *bprm)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
rc = process_measurement(bprm->file, bprm->filename,
|
||||||
|
MAY_EXEC, BPRM_CHECK);
|
||||||
|
return 0;
|
||||||
|
@@ -313,6 +325,9 @@ int ima_file_check(struct file *file, int mask)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
rc = process_measurement(file, file->f_dentry->d_name.name,
|
||||||
|
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
|
||||||
|
FILE_CHECK);
|
||||||
|
@@ -324,6 +339,9 @@ static int __init init_ima(void)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
+ if (!ima_enabled)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
error = ima_init();
|
||||||
|
ima_initialized = 1;
|
||||||
|
return error;
|
||||||
|
--
|
||||||
|
1.7.3.1
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
From: Jarod Wilson <jarod@redhat.com>
|
||||||
|
Date: Sat, 23 Oct 2010 14:54:06 -0400
|
||||||
|
Subject: [PATCH] imon: add back modparam for default protocol
|
||||||
|
|
||||||
|
The latest imon devices support both imon and mce remotes, but we
|
||||||
|
default to using the imon native protocol. Upstream, ir-keytable
|
||||||
|
can be used to change protocol and upload the mce keytable, but it
|
||||||
|
isn't functional with the input layer interfaces in 2.6.35. As a
|
||||||
|
work-around for now, add back a modparam so people can have the
|
||||||
|
driver load the mce keytable by default.
|
||||||
|
|
||||||
|
Note, this patch won't be going upstream. Upstream, we're moving
|
||||||
|
towards all keytables being in userspace, uploaded at driver init
|
||||||
|
time by ir-keytable (triggered by udev events).
|
||||||
|
|
||||||
|
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/media/rc/imon.c | 14 ++++++++++++++
|
||||||
|
1 files changed, 14 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
Index: linux-2.6.35.x86_64/drivers/media/rc/imon.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.35.x86_64.orig/drivers/media/rc/imon.c
|
||||||
|
+++ linux-2.6.35.x86_64/drivers/media/rc/imon.c
|
||||||
|
@@ -328,6 +328,17 @@ MODULE_PARM_DESC(pad_stabilize, "Apply s
|
||||||
|
"presses in arrow key mode. 0=disable, 1=enable (default).");
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * The latest imon devices support both imon and mce remotes, but we default
|
||||||
|
+ * to using the imon native protocol. Rather than require people to have and
|
||||||
|
+ * run ir-keytable to switch every module load, they can add mce=1 to their
|
||||||
|
+ * modparams to default to mce/rc6 instead.
|
||||||
|
+ */
|
||||||
|
+static bool mce;
|
||||||
|
+module_param(mce, bool, S_IRUGO);
|
||||||
|
+MODULE_PARM_DESC(mce, "Configure for mce/rc6 protocol instead of imon native, "
|
||||||
|
+ "if supported: 0=no, 1=yes (default: no)");
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* In certain use cases, mouse mode isn't really helpful, and could actually
|
||||||
|
* cause confusion, so allow disabling it when the IR device is open.
|
||||||
|
*/
|
||||||
|
@@ -1851,6 +1862,9 @@ static struct rc_dev *imon_init_rdev(str
|
||||||
|
|
||||||
|
imon_set_display_type(ictx);
|
||||||
|
|
||||||
|
+ if (mce && ((rdev->allowed_protos & RC_TYPE_RC6) == RC_TYPE_RC6))
|
||||||
|
+ ictx->rc_type = RC_TYPE_RC6;
|
||||||
|
+
|
||||||
|
if (ictx->rc_type == RC_TYPE_RC6)
|
||||||
|
rdev->map_name = RC_MAP_IMON_MCE;
|
||||||
|
else
|
|
@ -0,0 +1,103 @@
|
||||||
|
From jasowang@redhat.com Sat Oct 8 20:56:54 2011
|
||||||
|
Subject: ipv6: fix NULL dereference in udp6_ufo_fragment()
|
||||||
|
To: gregkh@suse.de, stable@kernel.org
|
||||||
|
From: Jason Wang <jasowang@redhat.com>
|
||||||
|
Cc: davem@davemloft.net, eric.dumazet@gmail.com
|
||||||
|
Date: Sun, 09 Oct 2011 10:56:44 +0800
|
||||||
|
Message-ID: <20111009025644.9437.53281.stgit@dhcp-8-146.nay.redhat.com>
|
||||||
|
|
||||||
|
From: Jason Wang <jasowang@redhat.com>
|
||||||
|
|
||||||
|
This patch fixes the issue caused by ef81bb40bf15f350fe865f31fa42f1082772a576
|
||||||
|
which is a backport of upstream 87c48fa3b4630905f98268dde838ee43626a060c. The
|
||||||
|
problem does not exist in upstream.
|
||||||
|
|
||||||
|
We do not check whether route is attached before trying to assign ip
|
||||||
|
identification through route dest which lead NULL pointer dereference. This
|
||||||
|
happens when host bridge transmit a packet from guest.
|
||||||
|
|
||||||
|
This patch changes ipv6_select_ident() to accept in6_addr as its paramter and
|
||||||
|
fix the issue by using the destination address in ipv6 header when no route is
|
||||||
|
attached.
|
||||||
|
|
||||||
|
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||||
|
Acked-by: David S. Miller <davem@davemloft.net>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
include/net/ipv6.h | 2 +-
|
||||||
|
net/ipv6/ip6_output.c | 10 +++++-----
|
||||||
|
net/ipv6/udp.c | 4 +++-
|
||||||
|
3 files changed, 9 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/net/ipv6.h
|
||||||
|
+++ b/include/net/ipv6.h
|
||||||
|
@@ -463,7 +463,7 @@ static inline int ipv6_addr_diff(const s
|
||||||
|
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
-extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
|
||||||
|
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prototypes exported by ipv6
|
||||||
|
--- a/net/ipv6/ip6_output.c
|
||||||
|
+++ b/net/ipv6/ip6_output.c
|
||||||
|
@@ -620,9 +620,9 @@ static u32 __ipv6_select_ident(const str
|
||||||
|
return hash + newid;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
||||||
|
+void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
- fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
|
||||||
|
+ fhdr->identification = htonl(__ipv6_select_ident(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
||||||
|
@@ -709,7 +709,7 @@ int ip6_fragment(struct sk_buff *skb, in
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
memcpy(skb_network_header(skb), tmp_hdr, hlen);
|
||||||
|
|
||||||
|
- ipv6_select_ident(fh, rt);
|
||||||
|
+ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
|
||||||
|
fh->nexthdr = nexthdr;
|
||||||
|
fh->reserved = 0;
|
||||||
|
fh->frag_off = htons(IP6_MF);
|
||||||
|
@@ -855,7 +855,7 @@ slow_path:
|
||||||
|
fh->nexthdr = nexthdr;
|
||||||
|
fh->reserved = 0;
|
||||||
|
if (!frag_id) {
|
||||||
|
- ipv6_select_ident(fh, rt);
|
||||||
|
+ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
|
||||||
|
frag_id = fh->identification;
|
||||||
|
} else
|
||||||
|
fh->identification = frag_id;
|
||||||
|
@@ -1146,7 +1146,7 @@ static inline int ip6_ufo_append_data(st
|
||||||
|
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
|
||||||
|
sizeof(struct frag_hdr)) & ~7;
|
||||||
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||||
|
- ipv6_select_ident(&fhdr, rt);
|
||||||
|
+ ipv6_select_ident(&fhdr, &rt->rt6i_dst.addr);
|
||||||
|
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
|
||||||
|
__skb_queue_tail(&sk->sk_write_queue, skb);
|
||||||
|
|
||||||
|
--- a/net/ipv6/udp.c
|
||||||
|
+++ b/net/ipv6/udp.c
|
||||||
|
@@ -1309,6 +1309,7 @@ static struct sk_buff *udp6_ufo_fragment
|
||||||
|
u8 frag_hdr_sz = sizeof(struct frag_hdr);
|
||||||
|
int offset;
|
||||||
|
__wsum csum;
|
||||||
|
+ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
|
||||||
|
|
||||||
|
mss = skb_shinfo(skb)->gso_size;
|
||||||
|
if (unlikely(skb->len <= mss))
|
||||||
|
@@ -1359,7 +1360,8 @@ static struct sk_buff *udp6_ufo_fragment
|
||||||
|
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
|
||||||
|
fptr->nexthdr = nexthdr;
|
||||||
|
fptr->reserved = 0;
|
||||||
|
- ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
|
||||||
|
+ ipv6_select_ident(fptr,
|
||||||
|
+ rt ? &rt->rt6i_dst.addr : &ipv6_hdr(skb)->daddr);
|
||||||
|
|
||||||
|
/* Fragment the skb. ipv6 header and the remaining fields of the
|
||||||
|
* fragment header are updated in ipv6_gso_segment()
|
|
@ -0,0 +1,172 @@
|
||||||
|
From d8d972876c51f7344367414bef3682bcf97e4e87 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||||
|
Date: Mon, 8 Aug 2011 23:44:00 -0700
|
||||||
|
Subject: ipv6: make fragment identifications less predictable
|
||||||
|
|
||||||
|
|
||||||
|
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||||
|
|
||||||
|
[ Backport of upstream commit 87c48fa3b4630905f98268dde838ee43626a060c for 2.6.35 ]
|
||||||
|
|
||||||
|
Fernando Gont reported current IPv6 fragment identification generation
|
||||||
|
was not secure, because using a very predictable system-wide generator,
|
||||||
|
allowing various attacks.
|
||||||
|
|
||||||
|
IPv4 uses inetpeer cache to address this problem and to get good
|
||||||
|
performance. We'll use this mechanism when IPv6 inetpeer is stable
|
||||||
|
enough in linux-3.1
|
||||||
|
|
||||||
|
For the time being, we use jhash on destination address to provide less
|
||||||
|
predictable identifications. Also remove a spinlock and use cmpxchg() to
|
||||||
|
get better SMP performance.
|
||||||
|
|
||||||
|
Reported-by: Fernando Gont <fernando@gont.com.ar>
|
||||||
|
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
---
|
||||||
|
include/net/ipv6.h | 12 +-----------
|
||||||
|
include/net/transp_v6.h | 2 ++
|
||||||
|
net/ipv6/af_inet6.c | 2 ++
|
||||||
|
net/ipv6/ip6_output.c | 40 +++++++++++++++++++++++++++++++++++-----
|
||||||
|
net/ipv6/udp.c | 2 +-
|
||||||
|
5 files changed, 41 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/net/ipv6.h
|
||||||
|
+++ b/include/net/ipv6.h
|
||||||
|
@@ -463,17 +463,7 @@ static inline int ipv6_addr_diff(const s
|
||||||
|
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr)
|
||||||
|
-{
|
||||||
|
- static u32 ipv6_fragmentation_id = 1;
|
||||||
|
- static DEFINE_SPINLOCK(ip6_id_lock);
|
||||||
|
-
|
||||||
|
- spin_lock_bh(&ip6_id_lock);
|
||||||
|
- fhdr->identification = htonl(ipv6_fragmentation_id);
|
||||||
|
- if (++ipv6_fragmentation_id == 0)
|
||||||
|
- ipv6_fragmentation_id = 1;
|
||||||
|
- spin_unlock_bh(&ip6_id_lock);
|
||||||
|
-}
|
||||||
|
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prototypes exported by ipv6
|
||||||
|
--- a/include/net/transp_v6.h
|
||||||
|
+++ b/include/net/transp_v6.h
|
||||||
|
@@ -14,6 +14,8 @@ extern struct proto tcpv6_prot;
|
||||||
|
|
||||||
|
struct flowi;
|
||||||
|
|
||||||
|
+extern void initialize_hashidentrnd(void);
|
||||||
|
+
|
||||||
|
/* extention headers */
|
||||||
|
extern int ipv6_exthdrs_init(void);
|
||||||
|
extern void ipv6_exthdrs_exit(void);
|
||||||
|
--- a/net/ipv6/af_inet6.c
|
||||||
|
+++ b/net/ipv6/af_inet6.c
|
||||||
|
@@ -1078,6 +1078,8 @@ static int __init inet6_init(void)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ initialize_hashidentrnd();
|
||||||
|
+
|
||||||
|
err = proto_register(&tcpv6_prot, 1);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
--- a/net/ipv6/ip6_output.c
|
||||||
|
+++ b/net/ipv6/ip6_output.c
|
||||||
|
@@ -596,6 +596,35 @@ int ip6_find_1stfragopt(struct sk_buff *
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static u32 hashidentrnd __read_mostly;
|
||||||
|
+#define FID_HASH_SZ 16
|
||||||
|
+static u32 ipv6_fragmentation_id[FID_HASH_SZ];
|
||||||
|
+
|
||||||
|
+void __init initialize_hashidentrnd(void)
|
||||||
|
+{
|
||||||
|
+ get_random_bytes(&hashidentrnd, sizeof(hashidentrnd));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u32 __ipv6_select_ident(const struct in6_addr *addr)
|
||||||
|
+{
|
||||||
|
+ u32 newid, oldid, hash = jhash2((u32 *)addr, 4, hashidentrnd);
|
||||||
|
+ u32 *pid = &ipv6_fragmentation_id[hash % FID_HASH_SZ];
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ oldid = *pid;
|
||||||
|
+ newid = oldid + 1;
|
||||||
|
+ if (!(hash + newid))
|
||||||
|
+ newid++;
|
||||||
|
+ } while (cmpxchg(pid, oldid, newid) != oldid);
|
||||||
|
+
|
||||||
|
+ return hash + newid;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
||||||
|
+{
|
||||||
|
+ fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
||||||
|
{
|
||||||
|
struct sk_buff *frag;
|
||||||
|
@@ -680,7 +709,7 @@ int ip6_fragment(struct sk_buff *skb, in
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
memcpy(skb_network_header(skb), tmp_hdr, hlen);
|
||||||
|
|
||||||
|
- ipv6_select_ident(fh);
|
||||||
|
+ ipv6_select_ident(fh, rt);
|
||||||
|
fh->nexthdr = nexthdr;
|
||||||
|
fh->reserved = 0;
|
||||||
|
fh->frag_off = htons(IP6_MF);
|
||||||
|
@@ -826,7 +855,7 @@ slow_path:
|
||||||
|
fh->nexthdr = nexthdr;
|
||||||
|
fh->reserved = 0;
|
||||||
|
if (!frag_id) {
|
||||||
|
- ipv6_select_ident(fh);
|
||||||
|
+ ipv6_select_ident(fh, rt);
|
||||||
|
frag_id = fh->identification;
|
||||||
|
} else
|
||||||
|
fh->identification = frag_id;
|
||||||
|
@@ -1072,7 +1101,8 @@ static inline int ip6_ufo_append_data(st
|
||||||
|
int getfrag(void *from, char *to, int offset, int len,
|
||||||
|
int odd, struct sk_buff *skb),
|
||||||
|
void *from, int length, int hh_len, int fragheaderlen,
|
||||||
|
- int transhdrlen, int mtu,unsigned int flags)
|
||||||
|
+ int transhdrlen, int mtu,unsigned int flags,
|
||||||
|
+ struct rt6_info *rt)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
@@ -1116,7 +1146,7 @@ static inline int ip6_ufo_append_data(st
|
||||||
|
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
|
||||||
|
sizeof(struct frag_hdr)) & ~7;
|
||||||
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||||
|
- ipv6_select_ident(&fhdr);
|
||||||
|
+ ipv6_select_ident(&fhdr, rt);
|
||||||
|
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
|
||||||
|
__skb_queue_tail(&sk->sk_write_queue, skb);
|
||||||
|
|
||||||
|
@@ -1282,7 +1312,7 @@ int ip6_append_data(struct sock *sk, int
|
||||||
|
|
||||||
|
err = ip6_ufo_append_data(sk, getfrag, from, length,
|
||||||
|
hh_len, fragheaderlen,
|
||||||
|
- transhdrlen, mtu, flags);
|
||||||
|
+ transhdrlen, mtu, flags, rt);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
return 0;
|
||||||
|
--- a/net/ipv6/udp.c
|
||||||
|
+++ b/net/ipv6/udp.c
|
||||||
|
@@ -1359,7 +1359,7 @@ static struct sk_buff *udp6_ufo_fragment
|
||||||
|
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
|
||||||
|
fptr->nexthdr = nexthdr;
|
||||||
|
fptr->reserved = 0;
|
||||||
|
- ipv6_select_ident(fptr);
|
||||||
|
+ ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
|
||||||
|
|
||||||
|
/* Fragment the skb. ipv6 header and the remaining fields of the
|
||||||
|
* fragment header are updated in ipv6_gso_segment()
|
|
@ -0,0 +1,38 @@
|
||||||
|
From 33710d0cfda2e00144acf7b6c58bb86ea4fcbbac Mon Sep 17 00:00:00 2001
|
||||||
|
From: Shan Wei <shanwei@cn.fujitsu.com>
|
||||||
|
Date: Tue, 19 Apr 2011 22:52:49 +0000
|
||||||
|
Subject: [PATCH] ipv6: udp: fix the wrong headroom check
|
||||||
|
|
||||||
|
At this point, skb->data points to skb_transport_header.
|
||||||
|
So, headroom check is wrong.
|
||||||
|
|
||||||
|
For some case:bridge(UFO is on) + eth device(UFO is off),
|
||||||
|
there is no enough headroom for IPv6 frag head.
|
||||||
|
But headroom check is always false.
|
||||||
|
|
||||||
|
This will bring about data be moved to there prior to skb->head,
|
||||||
|
when adding IPv6 frag header to skb.
|
||||||
|
|
||||||
|
Signed-off-by: Shan Wei <shanwei@cn.fujitsu.com>
|
||||||
|
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
net/ipv6/udp.c | 2 +-
|
||||||
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
|
||||||
|
index 8a72f58..4aaae95 100644
|
||||||
|
--- a/net/ipv6/udp.c
|
||||||
|
+++ b/net/ipv6/udp.c
|
||||||
|
@@ -1339,7 +1339,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
|
||||||
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
|
|
||||||
|
/* Check if there is enough headroom to insert fragment header. */
|
||||||
|
- if ((skb_headroom(skb) < frag_hdr_sz) &&
|
||||||
|
+ if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
|
||||||
|
pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.7.1
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
From sgruszka@redhat.com Mon Jun 20 10:14:55 2011
|
||||||
|
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
To: kernel@lists.fedoraproject.org
|
||||||
|
Subject: [PATCH 2.6.35 2/3] iwlagn: fix "Received BA when not expected"
|
||||||
|
Date: Mon, 20 Jun 2011 16:15:13 +0200
|
||||||
|
Message-Id: <1308579314-19348-3-git-send-email-sgruszka@redhat.com>
|
||||||
|
|
||||||
|
commit bfd36103ec26599557c2bd3225a1f1c9267f8fcb upstream.
|
||||||
|
|
||||||
|
Need to use broadcast sta_id for management frames, otherwise we broke
|
||||||
|
BA session in the firmware and get messages like that:
|
||||||
|
|
||||||
|
"Received BA when not expected"
|
||||||
|
|
||||||
|
or (on older kernels):
|
||||||
|
|
||||||
|
"BA scd_flow 0 does not match txq_id 10"
|
||||||
|
|
||||||
|
This fix regression introduced in 2.6.35 during station management
|
||||||
|
code rewrite by:
|
||||||
|
|
||||||
|
commit 2a87c26bbe9587baeb9e56d3ce0b4971bd777643
|
||||||
|
Author: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
Date: Fri Apr 30 11:30:45 2010 -0700
|
||||||
|
|
||||||
|
iwlwifi: use iwl_find_station less
|
||||||
|
|
||||||
|
Patch partially resolve:
|
||||||
|
https://bugzilla.kernel.org/show_bug.cgi?id=16691
|
||||||
|
However, there are still 11n performance problems on 4965 and 5xxx
|
||||||
|
devices that need to be investigated.
|
||||||
|
|
||||||
|
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 5 +++--
|
||||||
|
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
|
||||||
|
index cf64575..6df61b4 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
|
||||||
|
@@ -548,10 +548,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||||
|
|
||||||
|
hdr_len = ieee80211_hdrlen(fc);
|
||||||
|
|
||||||
|
- /* Find index into station table for destination station */
|
||||||
|
- if (!info->control.sta)
|
||||||
|
+ /* For management frames use broadcast id to do not break aggregation */
|
||||||
|
+ if (!ieee80211_is_data(fc) || !info->control.sta)
|
||||||
|
sta_id = priv->hw_params.bcast_sta_id;
|
||||||
|
else
|
||||||
|
+ /* Find index into station table for destination station */
|
||||||
|
sta_id = iwl_sta_id(info->control.sta);
|
||||||
|
if (sta_id == IWL_INVALID_STATION) {
|
||||||
|
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||||
|
--
|
||||||
|
1.7.1
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
From sgruszka@redhat.com Mon Jun 20 10:14:57 2011
|
||||||
|
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
To: kernel@lists.fedoraproject.org
|
||||||
|
Subject: [PATCH 2.6.35 3/3] iwlagn: use cts-to-self protection on 5000 adapters series
|
||||||
|
Date: Mon, 20 Jun 2011 16:15:14 +0200
|
||||||
|
Message-Id: <1308579314-19348-4-git-send-email-sgruszka@redhat.com>
|
||||||
|
|
||||||
|
This patch fixes 802.11n stability and performance regression we have
|
||||||
|
since 2.6.35. It boost performance on my 5GHz N-only network from about
|
||||||
|
5MB/s to 8MB/s. Similar percentage boost can be observed on 2.4 GHz.
|
||||||
|
|
||||||
|
These are test results of 5x downloading of approximately 700MB iso
|
||||||
|
image:
|
||||||
|
|
||||||
|
vanilla: 5.27 5.22 4.94 4.47 5.31 ; avr 5.0420 std 0.35110
|
||||||
|
patched: 8.07 7.95 8.06 7.99 7.96 ; avr 8.0060 std 0.055946
|
||||||
|
|
||||||
|
This was achieved with NetworkManager configured to do not perform
|
||||||
|
periodical scans, by configuring constant BSSID. With periodical scans,
|
||||||
|
after some time, performance downgrade to unpatched driver level, like
|
||||||
|
in example below:
|
||||||
|
|
||||||
|
patched: 7.40 7.61 4.28 4.37 4.80 avr 5.6920 std 1.6683
|
||||||
|
|
||||||
|
However patch still make better here, since similar test on unpatched
|
||||||
|
driver make link disconnects with below messages after some time:
|
||||||
|
|
||||||
|
wlan1: authenticate with 00:23:69:35:d1:3f (try 1)
|
||||||
|
wlan1: authenticate with 00:23:69:35:d1:3f (try 2)
|
||||||
|
wlan1: authenticate with 00:23:69:35:d1:3f (try 3)
|
||||||
|
wlan1: authentication with 00:23:69:35:d1:3f timed out
|
||||||
|
|
||||||
|
On 2.6.35 kernel patch helps against connection hangs with messages:
|
||||||
|
|
||||||
|
iwlagn 0000:20:00.0: queue 10 stuck 3 time. Fw reload.
|
||||||
|
iwlagn 0000:20:00.0: On demand firmware reload
|
||||||
|
iwlagn 0000:20:00.0: Stopping AGG while state not ON or starting
|
||||||
|
|
||||||
|
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-5000.c | 5 -----
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 11 ++---------
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-agn.c | 7 +++++++
|
||||||
|
3 files changed, 9 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
|
||||||
|
index 0a67558..8270ed6 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
|
||||||
|
@@ -458,7 +458,6 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
||||||
|
.use_bsm = false,
|
||||||
|
.ht_greenfield_support = true,
|
||||||
|
.led_compensation = 51,
|
||||||
|
- .use_rts_for_ht = true, /* use rts/cts protection */
|
||||||
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
|
.chain_noise_scale = 1000,
|
||||||
|
@@ -489,7 +488,6 @@ struct iwl_cfg iwl5100_bgn_cfg = {
|
||||||
|
.use_bsm = false,
|
||||||
|
.ht_greenfield_support = true,
|
||||||
|
.led_compensation = 51,
|
||||||
|
- .use_rts_for_ht = true, /* use rts/cts protection */
|
||||||
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
|
.chain_noise_scale = 1000,
|
||||||
|
@@ -549,7 +547,6 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
||||||
|
.use_bsm = false,
|
||||||
|
.ht_greenfield_support = true,
|
||||||
|
.led_compensation = 51,
|
||||||
|
- .use_rts_for_ht = true, /* use rts/cts protection */
|
||||||
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
|
.chain_noise_scale = 1000,
|
||||||
|
@@ -580,7 +577,6 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
||||||
|
.use_bsm = false,
|
||||||
|
.ht_greenfield_support = true,
|
||||||
|
.led_compensation = 51,
|
||||||
|
- .use_rts_for_ht = true, /* use rts/cts protection */
|
||||||
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
|
.chain_noise_scale = 1000,
|
||||||
|
@@ -611,7 +607,6 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
||||||
|
.use_bsm = false,
|
||||||
|
.ht_greenfield_support = true,
|
||||||
|
.led_compensation = 51,
|
||||||
|
- .use_rts_for_ht = true, /* use rts/cts protection */
|
||||||
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
|
.chain_noise_scale = 1000,
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
|
||||||
|
index 2a30397..44e91af 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
|
||||||
|
@@ -214,16 +214,9 @@ static void iwlagn_rts_tx_cmd_flag(struct iwl_priv *priv,
|
||||||
|
__le16 fc, __le32 *tx_flags)
|
||||||
|
{
|
||||||
|
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
|
||||||
|
- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||||
|
+ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
|
||||||
|
+ info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||||
|
*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (priv->cfg->use_rts_for_ht &&
|
||||||
|
- info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||||
|
- *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calc max signal level (dBm) among 3 possible receivers */
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
index 6bd11c7..20ffe4b 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
@@ -103,6 +103,13 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||||
|
if (!iwl_is_alive(priv))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * force CTS-to-self frames protection if RTS-CTS is not preferred
|
||||||
|
+ * one aggregation protection method
|
||||||
|
+ */
|
||||||
|
+ if (!priv->cfg->use_rts_for_ht)
|
||||||
|
+ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
|
||||||
|
+
|
||||||
|
/* always get timestamp with Rx frame */
|
||||||
|
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||||
|
|
||||||
|
--
|
||||||
|
1.7.1
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
From sgruszka@redhat.com Mon Jun 20 10:14:54 2011
|
||||||
|
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
To: kernel@lists.fedoraproject.org
|
||||||
|
Subject: [PATCH 2.6.35 1/3] iwlwifi: add {ack, plpc}_check module parameters
|
||||||
|
Date: Mon, 20 Jun 2011 16:15:12 +0200
|
||||||
|
Message-Id: <1308579314-19348-2-git-send-email-sgruszka@redhat.com>
|
||||||
|
|
||||||
|
commit b7977ffaab5187ad75edaf04ac854615cea93828 upstream.
|
||||||
|
|
||||||
|
Add module ack_check, and plcp_check parameters. Ack_check is disabled
|
||||||
|
by default since is proved that check ack health can cause troubles.
|
||||||
|
Plcp_check is enabled by default.
|
||||||
|
|
||||||
|
This prevent connection hangs with "low ack count detected" messages.
|
||||||
|
|
||||||
|
Resolves:
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=666646
|
||||||
|
|
||||||
|
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 +
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++
|
||||||
|
drivers/net/wireless/iwlwifi/iwl-rx.c | 8 ++++++--
|
||||||
|
4 files changed, 15 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||||
|
index 0f292a2..3a79907 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
|
||||||
|
@@ -387,6 +387,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
|
||||||
|
struct iwl_mod_params iwlagn_mod_params = {
|
||||||
|
.amsdu_size_8K = 1,
|
||||||
|
.restart_fw = 1,
|
||||||
|
+ .plcp_check = true,
|
||||||
|
/* the rest are 0 by default */
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
index 8a2c4d7..6bd11c7 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
|
||||||
|
@@ -4180,3 +4180,9 @@ module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
|
||||||
|
S_IRUGO);
|
||||||
|
MODULE_PARM_DESC(ucode_alternative,
|
||||||
|
"specify ucode alternative to use from ucode file");
|
||||||
|
+
|
||||||
|
+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
|
||||||
|
+MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
|
||||||
|
+
|
||||||
|
+module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
|
||||||
|
+MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
|
||||||
|
index e8ef317..ef03c24 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
|
||||||
|
@@ -226,6 +226,8 @@ struct iwl_mod_params {
|
||||||
|
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
|
||||||
|
int antenna; /* def: 0 = both antennas (use diversity) */
|
||||||
|
int restart_fw; /* def: 1 = restart firmware */
|
||||||
|
+ bool plcp_check; /* def: true = enable plcp health check */
|
||||||
|
+ bool ack_check; /* def: false = disable ack health check */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
|
||||||
|
index 0a5d7cf..d6c5927 100644
|
||||||
|
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
|
||||||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
|
||||||
|
@@ -401,10 +401,13 @@ EXPORT_SYMBOL(iwl_good_plcp_health);
|
||||||
|
void iwl_recover_from_statistics(struct iwl_priv *priv,
|
||||||
|
struct iwl_rx_packet *pkt)
|
||||||
|
{
|
||||||
|
+ const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
|
||||||
|
+
|
||||||
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||||
|
return;
|
||||||
|
if (iwl_is_associated(priv)) {
|
||||||
|
- if (priv->cfg->ops->lib->check_ack_health) {
|
||||||
|
+ if (mod_params->ack_check &&
|
||||||
|
+ priv->cfg->ops->lib->check_ack_health) {
|
||||||
|
if (!priv->cfg->ops->lib->check_ack_health(
|
||||||
|
priv, pkt)) {
|
||||||
|
/*
|
||||||
|
@@ -417,7 +420,8 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (priv->cfg->ops->lib->check_plcp_health) {
|
||||||
|
+ if (mod_params->plcp_check &&
|
||||||
|
+ priv->cfg->ops->lib->check_plcp_health) {
|
||||||
|
if (!priv->cfg->ops->lib->check_plcp_health(
|
||||||
|
priv, pkt)) {
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
1.7.1
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
From 8762202dd0d6e46854f786bdb6fb3780a1625efe Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eryu Guan <guaneryu@gmail.com>
|
||||||
|
Date: Tue, 1 Nov 2011 19:04:59 -0400
|
||||||
|
Subject: [PATCH] jbd/jbd2: validate sb->s_first in journal_get_superblock()
|
||||||
|
|
||||||
|
I hit a J_ASSERT(blocknr != 0) failure in cleanup_journal_tail() when
|
||||||
|
mounting a fsfuzzed ext3 image. It turns out that the corrupted ext3
|
||||||
|
image has s_first = 0 in journal superblock, and the 0 is passed to
|
||||||
|
journal->j_head in journal_reset(), then to blocknr in
|
||||||
|
cleanup_journal_tail(), in the end the J_ASSERT failed.
|
||||||
|
|
||||||
|
So validate s_first after reading journal superblock from disk in
|
||||||
|
journal_get_superblock() to ensure s_first is valid.
|
||||||
|
|
||||||
|
The following script could reproduce it:
|
||||||
|
|
||||||
|
fstype=ext3
|
||||||
|
blocksize=1024
|
||||||
|
img=$fstype.img
|
||||||
|
offset=0
|
||||||
|
found=0
|
||||||
|
magic="c0 3b 39 98"
|
||||||
|
|
||||||
|
dd if=/dev/zero of=$img bs=1M count=8
|
||||||
|
mkfs -t $fstype -b $blocksize -F $img
|
||||||
|
filesize=`stat -c %s $img`
|
||||||
|
while [ $offset -lt $filesize ]
|
||||||
|
do
|
||||||
|
if od -j $offset -N 4 -t x1 $img | grep -i "$magic";then
|
||||||
|
echo "Found journal: $offset"
|
||||||
|
found=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
offset=`echo "$offset+$blocksize" | bc`
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $found -ne 1 ];then
|
||||||
|
echo "Magic \"$magic\" not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dd if=/dev/zero of=$img seek=$(($offset+23)) conv=notrunc bs=1 count=1
|
||||||
|
|
||||||
|
mkdir -p ./mnt
|
||||||
|
mount -o loop $img ./mnt
|
||||||
|
|
||||||
|
Cc: Jan Kara <jack@suse.cz>
|
||||||
|
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
|
||||||
|
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
|
||||||
|
---
|
||||||
|
fs/jbd/journal.c | 8 ++++++++
|
||||||
|
fs/jbd2/journal.c | 8 ++++++++
|
||||||
|
2 files changed, 16 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
|
||||||
|
index 9fe061f..fea8dd6 100644
|
||||||
|
--- a/fs/jbd/journal.c
|
||||||
|
+++ b/fs/jbd/journal.c
|
||||||
|
@@ -1135,6 +1135,14 @@ static int journal_get_superblock(journal_t *journal)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (be32_to_cpu(sb->s_first) == 0 ||
|
||||||
|
+ be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
|
||||||
|
+ printk(KERN_WARNING
|
||||||
|
+ "JBD: Invalid start block of journal: %u\n",
|
||||||
|
+ be32_to_cpu(sb->s_first));
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
|
||||||
|
index f24df13..d6e93d0 100644
|
||||||
|
--- a/fs/jbd2/journal.c
|
||||||
|
+++ b/fs/jbd2/journal.c
|
||||||
|
@@ -1251,6 +1251,14 @@ static int journal_get_superblock(journal_t *journal)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (be32_to_cpu(sb->s_first) == 0 ||
|
||||||
|
+ be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
|
||||||
|
+ printk(KERN_WARNING
|
||||||
|
+ "JBD2: Invalid start block of journal: %u\n",
|
||||||
|
+ be32_to_cpu(sb->s_first));
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
--
|
||||||
|
1.7.7.1
|
||||||
|
|
1351
kernel.spec
1351
kernel.spec
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,98 @@
|
||||||
|
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
|
||||||
|
Date: Tue, 29 Jun 2010 05:53:50 +0000 (+0900)
|
||||||
|
Subject: kprobes/x86: Fix kprobes to skip prefixes correctly
|
||||||
|
X-Git-Tag: v2.6.36-rc1~41^2~53
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=567a9fd86735ccdc897768ed2dacdd5e83a13509
|
||||||
|
|
||||||
|
kprobes/x86: Fix kprobes to skip prefixes correctly
|
||||||
|
|
||||||
|
Fix resume_execution() and is_IF_modifier() to skip x86
|
||||||
|
instruction prefixes correctly by using x86 instruction
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
Without this fix, resume_execution() can't handle instructions
|
||||||
|
which have non-REX prefixes (REX prefixes are skipped). This
|
||||||
|
will cause unexpected kernel panic by hitting bad address when a
|
||||||
|
kprobe hits on two-byte ret (e.g. "repz ret" generated for
|
||||||
|
Athlon/K8 optimization), because it just checks "repz" and can't
|
||||||
|
recognize the "ret" instruction.
|
||||||
|
|
||||||
|
These prefixes can be found easily with x86 instruction
|
||||||
|
attribute. This patch introduces skip_prefixes() and uses it in
|
||||||
|
resume_execution() and is_IF_modifier() to skip prefixes.
|
||||||
|
|
||||||
|
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
|
||||||
|
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
|
||||||
|
LKML-Reference: <4C298A6E.8070609@hitachi.com>
|
||||||
|
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
|
||||||
|
index 345a4b1..175f85c 100644
|
||||||
|
--- a/arch/x86/kernel/kprobes.c
|
||||||
|
+++ b/arch/x86/kernel/kprobes.c
|
||||||
|
@@ -126,16 +126,22 @@ static void __kprobes synthesize_reljump(void *from, void *to)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Check for the REX prefix which can only exist on X86_64
|
||||||
|
- * X86_32 always returns 0
|
||||||
|
+ * Skip the prefixes of the instruction.
|
||||||
|
*/
|
||||||
|
-static int __kprobes is_REX_prefix(kprobe_opcode_t *insn)
|
||||||
|
+static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn)
|
||||||
|
{
|
||||||
|
+ insn_attr_t attr;
|
||||||
|
+
|
||||||
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
||||||
|
+ while (inat_is_legacy_prefix(attr)) {
|
||||||
|
+ insn++;
|
||||||
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
||||||
|
+ }
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
- if ((*insn & 0xf0) == 0x40)
|
||||||
|
- return 1;
|
||||||
|
+ if (inat_is_rex_prefix(attr))
|
||||||
|
+ insn++;
|
||||||
|
#endif
|
||||||
|
- return 0;
|
||||||
|
+ return insn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -272,6 +278,9 @@ static int __kprobes can_probe(unsigned long paddr)
|
||||||
|
*/
|
||||||
|
static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
||||||
|
{
|
||||||
|
+ /* Skip prefixes */
|
||||||
|
+ insn = skip_prefixes(insn);
|
||||||
|
+
|
||||||
|
switch (*insn) {
|
||||||
|
case 0xfa: /* cli */
|
||||||
|
case 0xfb: /* sti */
|
||||||
|
@@ -280,13 +289,6 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * on X86_64, 0x40-0x4f are REX prefixes so we need to look
|
||||||
|
- * at the next byte instead.. but of course not recurse infinitely
|
||||||
|
- */
|
||||||
|
- if (is_REX_prefix(insn))
|
||||||
|
- return is_IF_modifier(++insn);
|
||||||
|
-
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -803,9 +805,8 @@ static void __kprobes resume_execution(struct kprobe *p,
|
||||||
|
unsigned long orig_ip = (unsigned long)p->addr;
|
||||||
|
kprobe_opcode_t *insn = p->ainsn.insn;
|
||||||
|
|
||||||
|
- /*skip the REX prefix*/
|
||||||
|
- if (is_REX_prefix(insn))
|
||||||
|
- insn++;
|
||||||
|
+ /* Skip prefixes */
|
||||||
|
+ insn = skip_prefixes(insn);
|
||||||
|
|
||||||
|
regs->flags &= ~X86_EFLAGS_TF;
|
||||||
|
switch (*insn) {
|
|
@ -0,0 +1,50 @@
|
||||||
|
From: Joerg Roedel <joerg.roedel@amd.com>
|
||||||
|
Date: Thu, 2 Sep 2010 15:29:45 +0000 (+0200)
|
||||||
|
Subject: KVM: MMU: Fix 32 bit legacy paging with NPT
|
||||||
|
X-Git-Tag: v2.6.37-rc1~142^2~75
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f87f928882d080eaec8b0d76aecff003d664697d
|
||||||
|
|
||||||
|
KVM: MMU: Fix 32 bit legacy paging with NPT
|
||||||
|
|
||||||
|
This patch fixes 32 bit legacy paging with NPT enabled. The
|
||||||
|
mmu_check_root call on the top-level of the loop causes
|
||||||
|
root_gfn to take values (in the tdp_enabled path) which are
|
||||||
|
outside of guest memory. So the mmu_check_root call fails at
|
||||||
|
some point in the loop interation causing the guest to
|
||||||
|
tiple-fault.
|
||||||
|
This patch changes the mmu_check_root calls to the places
|
||||||
|
where they are really necessary. As a side-effect it
|
||||||
|
introduces a check for the root of a pae page table too.
|
||||||
|
|
||||||
|
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
|
||||||
|
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
|
||||||
|
index d2dad65..b2136f9 100644
|
||||||
|
--- a/arch/x86/kvm/mmu.c
|
||||||
|
+++ b/arch/x86/kvm/mmu.c
|
||||||
|
@@ -2387,6 +2387,10 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
direct = !is_paging(vcpu);
|
||||||
|
+
|
||||||
|
+ if (mmu_check_root(vcpu, root_gfn))
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
hpa_t root = vcpu->arch.mmu.pae_root[i];
|
||||||
|
|
||||||
|
@@ -2398,10 +2402,10 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
root_gfn = pdptr >> PAGE_SHIFT;
|
||||||
|
+ if (mmu_check_root(vcpu, root_gfn))
|
||||||
|
+ return 1;
|
||||||
|
} else if (vcpu->arch.mmu.root_level == 0)
|
||||||
|
root_gfn = 0;
|
||||||
|
- if (mmu_check_root(vcpu, root_gfn))
|
||||||
|
- return 1;
|
||||||
|
if (tdp_enabled) {
|
||||||
|
direct = 1;
|
||||||
|
root_gfn = i << 30;
|
|
@ -0,0 +1,30 @@
|
||||||
|
Dump stack once on unsupported commands to see who is submitting them.
|
||||||
|
(#632753)
|
||||||
|
|
||||||
|
--- linux-2.6.34.noarch.orig/drivers/ata/pata_it821x.c
|
||||||
|
+++ linux-2.6.34.noarch/drivers/ata/pata_it821x.c
|
||||||
|
@@ -399,6 +399,16 @@ static void it821x_passthru_dev_select(s
|
||||||
|
ata_sff_dev_select(ap, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void it821x_dump_stack_once(void)
|
||||||
|
+{
|
||||||
|
+ static int dumped = 0;
|
||||||
|
+
|
||||||
|
+ if (!dumped) {
|
||||||
|
+ dump_stack();
|
||||||
|
+ dumped = 1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* it821x_smart_qc_issue - wrap qc issue prot
|
||||||
|
* @qc: command
|
||||||
|
@@ -433,6 +443,7 @@ static unsigned int it821x_smart_qc_issu
|
||||||
|
return ata_sff_qc_issue(qc);
|
||||||
|
}
|
||||||
|
printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
|
||||||
|
+ it821x_dump_stack_once();
|
||||||
|
return AC_ERR_DEV;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
diff -up linux-2.6.34.x86_64/drivers/acpi/acpica/dsobject.c.mjg59 linux-2.6.34.x86_64/drivers/acpi/acpica/dsobject.c
|
||||||
|
--- linux-2.6.34.x86_64/drivers/acpi/acpica/dsobject.c.mjg59 2010-05-16 17:17:36.000000000 -0400
|
||||||
|
+++ linux-2.6.34.x86_64/drivers/acpi/acpica/dsobject.c 2011-02-09 12:08:58.430275518 -0500
|
||||||
|
@@ -81,6 +81,7 @@ acpi_ds_build_internal_object(struct acp
|
||||||
|
{
|
||||||
|
union acpi_operand_object *obj_desc;
|
||||||
|
acpi_status status;
|
||||||
|
+ acpi_object_type type;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE(ds_build_internal_object);
|
||||||
|
|
||||||
|
@@ -172,7 +173,20 @@ acpi_ds_build_internal_object(struct acp
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (op->common.node->type) {
|
||||||
|
+ /*
|
||||||
|
+ * Special handling for Alias objects. We need to setup the type
|
||||||
|
+ * and the Op->Common.Node to point to the Alias target. Note,
|
||||||
|
+ * Alias has at most one level of indirection internally.
|
||||||
|
+ */
|
||||||
|
+ type = op->common.node->type;
|
||||||
|
+ if (type == ACPI_TYPE_LOCAL_ALIAS) {
|
||||||
|
+ type = obj_desc->common.type;
|
||||||
|
+ op->common.node =
|
||||||
|
+ ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||||
|
+ op->common.node->object);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
/*
|
||||||
|
* For these types, we need the actual node, not the subobject.
|
||||||
|
* However, the subobject did not get an extra reference count above.
|
|
@ -0,0 +1,71 @@
|
||||||
|
From: Neil Horman <nhorman@tuxdriver.com>
|
||||||
|
Date: Tue, 5 Oct 2010 03:39:21 +0000 (+0000)
|
||||||
|
Subject: bonding: fix WARN_ON when writing to bond_master sysfs file
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fdavem%2Fnet-2.6.git;a=commitdiff_plain;h=27e6f065df132b5270014d3285889b15185e9da9
|
||||||
|
|
||||||
|
bonding: fix WARN_ON when writing to bond_master sysfs file
|
||||||
|
|
||||||
|
Fix a WARN_ON failure in bond_masters sysfs file
|
||||||
|
|
||||||
|
Got a report of this warning recently
|
||||||
|
|
||||||
|
bonding: bond0 is being created...
|
||||||
|
------------[ cut here ]------------
|
||||||
|
WARNING: at fs/proc/generic.c:590 proc_register+0x14d/0x185()
|
||||||
|
Hardware name: ProLiant BL465c G1
|
||||||
|
proc_dir_entry 'bonding/bond0' already registered
|
||||||
|
Modules linked in: bonding ipv6 tg3 bnx2 shpchp amd64_edac_mod edac_core
|
||||||
|
ipmi_si
|
||||||
|
ipmi_msghandler serio_raw i2c_piix4 k8temp edac_mce_amd hpwdt microcode hpsa
|
||||||
|
cc
|
||||||
|
iss radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded:
|
||||||
|
scsi_wai
|
||||||
|
t_scan]
|
||||||
|
Pid: 935, comm: ifup-eth Not tainted 2.6.33.5-124.fc13.x86_64 #1
|
||||||
|
Call Trace:
|
||||||
|
[<ffffffff8104b54c>] warn_slowpath_common+0x77/0x8f
|
||||||
|
[<ffffffff8104b5b1>] warn_slowpath_fmt+0x3c/0x3e
|
||||||
|
[<ffffffff8114bf0b>] proc_register+0x14d/0x185
|
||||||
|
[<ffffffff8114c20c>] proc_create_data+0x87/0xa1
|
||||||
|
[<ffffffffa0211e9b>] bond_create_proc_entry+0x55/0x95 [bonding]
|
||||||
|
[<ffffffffa0215e5d>] bond_init+0x95/0xd0 [bonding]
|
||||||
|
[<ffffffff8138cd97>] register_netdevice+0xdd/0x29e
|
||||||
|
[<ffffffffa021240b>] bond_create+0x8e/0xb8 [bonding]
|
||||||
|
[<ffffffffa021c4be>] bonding_store_bonds+0xb3/0x1c1 [bonding]
|
||||||
|
[<ffffffff812aec85>] class_attr_store+0x27/0x29
|
||||||
|
[<ffffffff8115423d>] sysfs_write_file+0x10f/0x14b
|
||||||
|
[<ffffffff81101acf>] vfs_write+0xa9/0x106
|
||||||
|
[<ffffffff81101be2>] sys_write+0x45/0x69
|
||||||
|
[<ffffffff81009b02>] system_call_fastpath+0x16/0x1b
|
||||||
|
---[ end trace a677c3f7f8b16b1e ]---
|
||||||
|
bonding: Bond creation failed.
|
||||||
|
|
||||||
|
It happens because a user space writer to bond_master can try to
|
||||||
|
register an already existing bond interface name. Fix it by teaching
|
||||||
|
bond_create to check for the existance of devices with that name first
|
||||||
|
in cases where a non-NULL name parameter has been passed in
|
||||||
|
|
||||||
|
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
||||||
|
index 3b16f62..e953c6a 100644
|
||||||
|
--- a/drivers/net/bonding/bond_main.c
|
||||||
|
+++ b/drivers/net/bonding/bond_main.c
|
||||||
|
@@ -5164,6 +5164,15 @@ int bond_create(struct net *net, const char *name)
|
||||||
|
res = dev_alloc_name(bond_dev, "bond%d");
|
||||||
|
if (res < 0)
|
||||||
|
goto out;
|
||||||
|
+ } else {
|
||||||
|
+ /*
|
||||||
|
+ * If we're given a name to register
|
||||||
|
+ * we need to ensure that its not already
|
||||||
|
+ * registered
|
||||||
|
+ */
|
||||||
|
+ res = -EEXIST;
|
||||||
|
+ if (__dev_get_by_name(net, name) != NULL)
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = register_netdevice(bond_dev);
|
|
@ -0,0 +1,47 @@
|
||||||
|
Message-ID: <4C805293.1020305@cn.fujitsu.com>
|
||||||
|
Date: Fri, 03 Sep 2010 09:42:43 +0800
|
||||||
|
From: Li Zefan <lizf@cn.fujitsu.com>
|
||||||
|
To: David Miller <davem@davemloft.net>
|
||||||
|
CC: Herbert Xu <herbert@gondor.hengli.com.au>, Dave Jones <davej@redhat.com>,
|
||||||
|
netdev <netdev@vger.kernel.org>, LKML <linux-kernel@vger.kernel.org>,
|
||||||
|
Peter Zijlstra <peterz@infradead.org>, Paul Menage <menage@google.com>
|
||||||
|
Subject: [PATCH v2] cls_cgroup: Fix rcu lockdep warning
|
||||||
|
|
||||||
|
Dave reported an rcu lockdep warning on 2.6.35.4 kernel
|
||||||
|
|
||||||
|
task->cgroups and task->cgroups->subsys[i] are protected by RCU.
|
||||||
|
So we avoid accessing invalid pointers here. This might happen,
|
||||||
|
for example, when you are deref-ing those pointers while someone
|
||||||
|
move @task from one cgroup to another.
|
||||||
|
|
||||||
|
Reported-by: Dave Jones <davej@redhat.com>
|
||||||
|
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
|
||||||
|
---
|
||||||
|
include/net/cls_cgroup.h | 10 ++++++++--
|
||||||
|
1 files changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
|
||||||
|
index dd1fdb8..a4dc5b0 100644
|
||||||
|
--- a/include/net/cls_cgroup.h
|
||||||
|
+++ b/include/net/cls_cgroup.h
|
||||||
|
@@ -27,11 +27,17 @@ struct cgroup_cls_state
|
||||||
|
#ifdef CONFIG_NET_CLS_CGROUP
|
||||||
|
static inline u32 task_cls_classid(struct task_struct *p)
|
||||||
|
{
|
||||||
|
+ int classid;
|
||||||
|
+
|
||||||
|
if (in_interrupt())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- return container_of(task_subsys_state(p, net_cls_subsys_id),
|
||||||
|
- struct cgroup_cls_state, css)->classid;
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ classid = container_of(task_subsys_state(p, net_cls_subsys_id),
|
||||||
|
+ struct cgroup_cls_state, css)->classid;
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return classid;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern int net_cls_subsys_id;
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
--- linux-2.6.34.noarch.orig/kernel/power/main.c
|
||||||
|
+++ linux-2.6.34.noarch/kernel/power/main.c
|
||||||
|
@@ -45,7 +45,7 @@ int pm_notifier_call_chain(unsigned long
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If set, devices may be suspended and resumed asynchronously. */
|
||||||
|
-int pm_async_enabled = 1;
|
||||||
|
+int pm_async_enabled;
|
||||||
|
|
||||||
|
static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
|
char *buf)
|
|
@ -0,0 +1,29 @@
|
||||||
|
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
|
||||||
|
index cea0cd9..c326065 100644
|
||||||
|
--- a/arch/x86/Kconfig
|
||||||
|
+++ b/arch/x86/Kconfig
|
||||||
|
@@ -2142,3 +2142,8 @@ source "crypto/Kconfig"
|
||||||
|
source "arch/x86/kvm/Kconfig"
|
||||||
|
|
||||||
|
source "lib/Kconfig"
|
||||||
|
+
|
||||||
|
+config PCI_DEFAULT_USE_CRS
|
||||||
|
+ def_bool y
|
||||||
|
+ prompt "Use PCI Host Bridge Windows from ACPI by default?"
|
||||||
|
+ depends on ACPI
|
||||||
|
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
|
||||||
|
index 15466c0..3099406 100644
|
||||||
|
--- a/arch/x86/pci/acpi.c
|
||||||
|
+++ b/arch/x86/pci/acpi.c
|
||||||
|
@@ -16,7 +16,11 @@ struct pci_root_info {
|
||||||
|
int busnum;
|
||||||
|
};
|
||||||
|
|
||||||
|
+#ifdef CONFIG_PCI_DEFAULT_USE_CRS
|
||||||
|
static bool pci_use_crs = true;
|
||||||
|
+#else
|
||||||
|
+static bool pci_use_crs = false;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
static int __init set_use_crs(const struct dmi_system_id *id)
|
||||||
|
{
|
|
@ -0,0 +1,30 @@
|
||||||
|
This only showed up in one SDV (Montevina).
|
||||||
|
The PCIE slots don't seem to like network cards, so this is the only hope
|
||||||
|
to get networking working. It's never going upstream, but it's low impact
|
||||||
|
enough to carry just to keep those SDVs working.
|
||||||
|
|
||||||
|
--- linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c~ 2010-09-29 17:53:13.000000000 -0400
|
||||||
|
+++ linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c 2010-09-29 17:54:00.000000000 -0400
|
||||||
|
@@ -424,6 +424,12 @@ static s32 e1000_init_phy_params_ich8lan
|
||||||
|
|
||||||
|
/* Verify phy id */
|
||||||
|
switch (phy->id) {
|
||||||
|
+ case 0:
|
||||||
|
+ if (hw->adapter->pdev->device == 0x10be)
|
||||||
|
+ e_dbg("got 0 phy id, trying anyway");
|
||||||
|
+ /* Fall through to IGP03E1000 case below */
|
||||||
|
+ else
|
||||||
|
+ return -E1000_ERR_PHY;
|
||||||
|
case IGP03E1000_E_PHY_ID:
|
||||||
|
phy->type = e1000_phy_igp_3;
|
||||||
|
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
|
||||||
|
--- linux-2.6.35.noarch/drivers/net/e1000e/netdev.c~ 2010-09-29 17:54:07.000000000 -0400
|
||||||
|
+++ linux-2.6.35.noarch/drivers/net/e1000e/netdev.c 2010-09-29 17:54:29.000000000 -0400
|
||||||
|
@@ -5994,6 +5994,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci
|
||||||
|
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan },
|
||||||
|
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan },
|
||||||
|
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan },
|
||||||
|
+ { PCI_VDEVICE(INTEL, 0x10be), board_ich9lan },
|
||||||
|
|
||||||
|
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan },
|
||||||
|
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan },
|
|
@ -1,46 +0,0 @@
|
||||||
[PATCH] ext4: fix freeze deadlock under IO
|
|
||||||
|
|
||||||
Commit 6b0310fbf087ad6 caused a regression resulting in deadlocks
|
|
||||||
when freezing a filesystem which had active IO; the vfs_check_frozen
|
|
||||||
level (SB_FREEZE_WRITE) did not let the freeze-related IO syncing
|
|
||||||
through. Duh.
|
|
||||||
|
|
||||||
Changing the test to FREEZE_TRANS should let the normal freeze
|
|
||||||
syncing get through the fs, but still block any transactions from
|
|
||||||
starting once the fs is completely frozen.
|
|
||||||
|
|
||||||
I tested this by running fsstress in the background while periodically
|
|
||||||
snapshotting the fs and running fsck on the result. I ran into
|
|
||||||
occasional deadlocks, but different ones. I think this is a
|
|
||||||
fine fix for the problem at hand, and the other deadlocky things
|
|
||||||
will need more investigation.
|
|
||||||
|
|
||||||
Reported-by: Phillip Susi <psusi@cfl.rr.com>
|
|
||||||
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
||||||
index 4e8983a..a45ced9 100644
|
|
||||||
--- a/fs/ext4/super.c
|
|
||||||
+++ b/fs/ext4/super.c
|
|
||||||
@@ -241,7 +241,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
|
|
||||||
if (sb->s_flags & MS_RDONLY)
|
|
||||||
return ERR_PTR(-EROFS);
|
|
||||||
|
|
||||||
- vfs_check_frozen(sb, SB_FREEZE_WRITE);
|
|
||||||
+ vfs_check_frozen(sb, SB_FREEZE_TRANS);
|
|
||||||
/* Special case here: if the journal has aborted behind our
|
|
||||||
* backs (eg. EIO in the commit thread), then we still need to
|
|
||||||
* take the FS itself readonly cleanly. */
|
|
||||||
@@ -3491,7 +3491,7 @@ int ext4_force_commit(struct super_block *sb)
|
|
||||||
|
|
||||||
journal = EXT4_SB(sb)->s_journal;
|
|
||||||
if (journal) {
|
|
||||||
- vfs_check_frozen(sb, SB_FREEZE_WRITE);
|
|
||||||
+ vfs_check_frozen(sb, SB_FREEZE_TRANS);
|
|
||||||
ret = ext4_journal_force_commit(journal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -141,8 +141,8 @@
|
||||||
set_user_gs(regs, 0);
|
set_user_gs(regs, 0);
|
||||||
+
|
+
|
||||||
regs->fs = 0;
|
regs->fs = 0;
|
||||||
set_fs(USER_DS);
|
|
||||||
regs->ds = __USER_DS;
|
regs->ds = __USER_DS;
|
||||||
|
regs->es = __USER_DS;
|
||||||
@@ -252,6 +255,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
|
@@ -252,6 +255,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
|
||||||
regs->cs = __USER_CS;
|
regs->cs = __USER_CS;
|
||||||
regs->ip = new_ip;
|
regs->ip = new_ip;
|
||||||
|
@ -538,15 +538,16 @@
|
||||||
static void unmap_region(struct mm_struct *mm,
|
static void unmap_region(struct mm_struct *mm,
|
||||||
struct vm_area_struct *vma, struct vm_area_struct *prev,
|
struct vm_area_struct *vma, struct vm_area_struct *prev,
|
||||||
unsigned long start, unsigned long end);
|
unsigned long start, unsigned long end);
|
||||||
@@ -388,6 +401,8 @@
|
@@ -388,6 +401,9 @@
|
||||||
__vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
||||||
struct vm_area_struct *prev, struct rb_node *rb_parent)
|
|
||||||
{
|
{
|
||||||
|
struct vm_area_struct *next;
|
||||||
|
|
||||||
+ if (vma->vm_flags & VM_EXEC)
|
+ if (vma->vm_flags & VM_EXEC)
|
||||||
+ arch_add_exec_range(mm, vma->vm_end);
|
+ arch_add_exec_range(mm, vma->vm_end);
|
||||||
|
+
|
||||||
|
vma->vm_prev = prev;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
vma->vm_next = prev->vm_next;
|
next = prev->vm_next;
|
||||||
prev->vm_next = vma;
|
|
||||||
@@ -489,6 +504,8 @@
|
@@ -489,6 +504,8 @@
|
||||||
rb_erase(&vma->vm_rb, &mm->mm_rb);
|
rb_erase(&vma->vm_rb, &mm->mm_rb);
|
||||||
if (mm->mmap_cache == vma)
|
if (mm->mmap_cache == vma)
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
|
||||||
|
index 9fbc54a..435c502 100644
|
||||||
|
--- a/include/linux/rcupdate.h
|
||||||
|
+++ b/include/linux/rcupdate.h
|
||||||
|
@@ -454,7 +454,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
|
||||||
|
* Makes rcu_dereference_check() do the dirty work.
|
||||||
|
*/
|
||||||
|
#define rcu_dereference_bh(p) \
|
||||||
|
- rcu_dereference_check(p, rcu_read_lock_bh_held())
|
||||||
|
+ rcu_dereference_check(p, rcu_read_lock_bh_held() || irqs_disabled())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rcu_dereference_sched - fetch RCU-protected pointer, checking for RCU-sched
|
||||||
|
|
||||||
|
|
|
@ -1 +1,332 @@
|
||||||
nil
|
From c6c14330717f9850b4b4c054b81424b9979cd07d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jean-Francois Moine <moinejf@free.fr>
|
||||||
|
Date: Tue, 14 Dec 2010 16:15:37 -0300
|
||||||
|
Subject: [media] gspca - sonixj: Add a flag in the driver_info table
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
From: Jean-Francois Moine <moinejf@free.fr>
|
||||||
|
|
||||||
|
commit c6c14330717f9850b4b4c054b81424b9979cd07d upstream.
|
||||||
|
|
||||||
|
Signed-off-by: Jean-François Moine <moinejf@free.fr>
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/media/video/gspca/sonixj.c | 10 ++++++++--
|
||||||
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
Index: linux-2.6.35.y/drivers/media/video/gspca/sonixj.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.35.y.orig/drivers/media/video/gspca/sonixj.c
|
||||||
|
+++ linux-2.6.35.y/drivers/media/video/gspca/sonixj.c
|
||||||
|
@@ -57,6 +57,7 @@ struct sd {
|
||||||
|
u8 jpegqual; /* webcam quality */
|
||||||
|
|
||||||
|
u8 reg18;
|
||||||
|
+ u8 flags;
|
||||||
|
|
||||||
|
s8 ag_cnt;
|
||||||
|
#define AG_CNT_START 13
|
||||||
|
@@ -1777,7 +1778,8 @@ static int sd_config(struct gspca_dev *g
|
||||||
|
struct cam *cam;
|
||||||
|
|
||||||
|
sd->bridge = id->driver_info >> 16;
|
||||||
|
- sd->sensor = id->driver_info;
|
||||||
|
+ sd->sensor = id->driver_info >> 8;
|
||||||
|
+ sd->flags = id->driver_info;
|
||||||
|
|
||||||
|
cam = &gspca_dev->cam;
|
||||||
|
if (sd->sensor == SENSOR_ADCM1700) {
|
||||||
|
@@ -3001,7 +3003,11 @@ static const struct sd_desc sd_desc = {
|
||||||
|
/* -- module initialisation -- */
|
||||||
|
#define BS(bridge, sensor) \
|
||||||
|
.driver_info = (BRIDGE_ ## bridge << 16) \
|
||||||
|
- | SENSOR_ ## sensor
|
||||||
|
+ | (SENSOR_ ## sensor << 8)
|
||||||
|
+#define BSF(bridge, sensor, flags) \
|
||||||
|
+ .driver_info = (BRIDGE_ ## bridge << 16) \
|
||||||
|
+ | (SENSOR_ ## sensor << 8) \
|
||||||
|
+ | (flags)
|
||||||
|
static const __devinitdata struct usb_device_id device_table[] = {
|
||||||
|
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
|
||||||
|
{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
|
||||||
|
From b2272a49e7df37732d73988f00468ce31e1ebc92 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jean-Francois Moine <moinejf@free.fr>
|
||||||
|
Date: Tue, 14 Dec 2010 16:16:16 -0300
|
||||||
|
Subject: [media] gspca - sonixj: Set the flag for some devices
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
From: Jean-Francois Moine <moinejf@free.fr>
|
||||||
|
|
||||||
|
commit b2272a49e7df37732d73988f00468ce31e1ebc92 upstream.
|
||||||
|
|
||||||
|
The flag PDN_INV indicates that the sensor pin S_PWR_DN has not the same
|
||||||
|
value as other webcams with the same sensor. For now, only two webcams have
|
||||||
|
been so detected: the Microsoft's VX1000 and VX3000.
|
||||||
|
|
||||||
|
Signed-off-by: Jean-François Moine <moinejf@free.fr>
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/media/video/gspca/sonixj.c | 7 +++++--
|
||||||
|
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
Index: linux-2.6.35.y/drivers/media/video/gspca/sonixj.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.35.y.orig/drivers/media/video/gspca/sonixj.c
|
||||||
|
+++ linux-2.6.35.y/drivers/media/video/gspca/sonixj.c
|
||||||
|
@@ -88,6 +88,9 @@ enum {
|
||||||
|
u8 jpeg_hdr[JPEG_HDR_SZ];
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* device flags */
|
||||||
|
+#define PDN_INV 1 /* inverse pin S_PWR_DN / sn_xxx tables */
|
||||||
|
+
|
||||||
|
/* V4L2 controls supported by the driver */
|
||||||
|
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||||
|
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||||
|
@@ -3004,8 +3007,8 @@ static const __devinitdata struct usb_de
|
||||||
|
{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
|
||||||
|
{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
|
||||||
|
#endif
|
||||||
|
- {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)},
|
||||||
|
- {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)},
|
||||||
|
+ {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
|
||||||
|
+ {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
|
||||||
|
{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
|
||||||
|
{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
|
||||||
|
{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
|
||||||
|
From 615661f3948a066fd22a36fe8ea0c528b75ee373 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marcin Slusarz <marcin.slusarz@gmail.com>
|
||||||
|
Date: Sun, 22 Aug 2010 20:54:08 +0200
|
||||||
|
Subject: drm/nv50: initialize ramht_refs list for faked 0 channel
|
||||||
|
|
||||||
|
From: Marcin Slusarz <marcin.slusarz@gmail.com>
|
||||||
|
|
||||||
|
commit 615661f3948a066fd22a36fe8ea0c528b75ee373 upstream.
|
||||||
|
|
||||||
|
We need it for PFIFO_INTR_CACHE_ERROR interrupt handling,
|
||||||
|
because nouveau_fifo_swmthd looks for matching gpuobj in
|
||||||
|
ramht_refs list.
|
||||||
|
It fixes kernel panic in nouveau_gpuobj_ref_find.
|
||||||
|
|
||||||
|
Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
|
||||||
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/nouveau/nv50_instmem.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||||
|
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||||
|
@@ -141,6 +141,8 @@ nv50_instmem_init(struct drm_device *dev
|
||||||
|
chan->file_priv = (struct drm_file *)-2;
|
||||||
|
dev_priv->fifos[0] = dev_priv->fifos[127] = chan;
|
||||||
|
|
||||||
|
+ INIT_LIST_HEAD(&chan->ramht_refs);
|
||||||
|
+
|
||||||
|
/* Channel's PRAMIN object + heap */
|
||||||
|
ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0,
|
||||||
|
NULL, &chan->ramin);
|
||||||
|
|
||||||
|
commit 6f1b1e1384b23cfab30c2bc02a8f94927274c10d
|
||||||
|
Author: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||||
|
Date: Sun Jan 16 10:09:13 2011 -0300
|
||||||
|
|
||||||
|
radio-aimslab.c needs #include <linux/delay.h>
|
||||||
|
|
||||||
|
commit 2400982a2e8a8e4e95f0a0e1517bbe63cc88038f upstream.
|
||||||
|
|
||||||
|
Commit e3c92215198cb6aa00ad38db2780faa6b72e0a3f ("[media] radio-aimslab.c: Fix
|
||||||
|
gcc 4.5+ bug") removed the include, but introduced new callers of msleep():
|
||||||
|
|
||||||
|
| drivers/media/radio/radio-aimslab.c: In function ‘rt_decvol’:
|
||||||
|
| drivers/media/radio/radio-aimslab.c:76: error: implicit declaration of function ‘msleep’
|
||||||
|
|
||||||
|
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
Cc: dann frazier <dannf@debian.org>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
|
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
|
||||||
|
index 1944814..a91642c 100644
|
||||||
|
--- a/drivers/media/radio/radio-aimslab.c
|
||||||
|
+++ b/drivers/media/radio/radio-aimslab.c
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <linux/module.h> /* Modules */
|
||||||
|
#include <linux/init.h> /* Initdata */
|
||||||
|
#include <linux/ioport.h> /* request_region */
|
||||||
|
+#include <linux/delay.h> /* msleep */
|
||||||
|
#include <linux/videodev2.h> /* kernel radio structs */
|
||||||
|
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
|
||||||
|
#include <linux/io.h> /* outb, outb_p */
|
||||||
|
|
||||||
|
commit 9c198dad83c19a05a11b5a195242f3e8dcbe55f4
|
||||||
|
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Date: Thu Jan 6 08:16:04 2011 -0200
|
||||||
|
|
||||||
|
radio-aimslab.c: Fix gcc 4.5+ bug
|
||||||
|
|
||||||
|
commit e3c92215198cb6aa00ad38db2780faa6b72e0a3f upstream.
|
||||||
|
|
||||||
|
gcc 4.5+ doesn't properly evaluate some inlined expressions.
|
||||||
|
A previous patch were proposed by Andrew Morton using noinline.
|
||||||
|
However, the entire inlined function is bogus, so let's just
|
||||||
|
remove it and be happy.
|
||||||
|
|
||||||
|
Reported-by: Andrew Morton <akpm@linux-foundation.org>
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
|
||||||
|
index 5bf4985..1944814 100644
|
||||||
|
--- a/drivers/media/radio/radio-aimslab.c
|
||||||
|
+++ b/drivers/media/radio/radio-aimslab.c
|
||||||
|
@@ -31,7 +31,6 @@
|
||||||
|
#include <linux/module.h> /* Modules */
|
||||||
|
#include <linux/init.h> /* Initdata */
|
||||||
|
#include <linux/ioport.h> /* request_region */
|
||||||
|
-#include <linux/delay.h> /* udelay */
|
||||||
|
#include <linux/videodev2.h> /* kernel radio structs */
|
||||||
|
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
|
||||||
|
#include <linux/io.h> /* outb, outb_p */
|
||||||
|
@@ -71,27 +70,17 @@ static struct rtrack rtrack_card;
|
||||||
|
|
||||||
|
/* local things */
|
||||||
|
|
||||||
|
-static void sleep_delay(long n)
|
||||||
|
-{
|
||||||
|
- /* Sleep nicely for 'n' uS */
|
||||||
|
- int d = n / msecs_to_jiffies(1000);
|
||||||
|
- if (!d)
|
||||||
|
- udelay(n);
|
||||||
|
- else
|
||||||
|
- msleep(jiffies_to_msecs(d));
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void rt_decvol(struct rtrack *rt)
|
||||||
|
{
|
||||||
|
outb(0x58, rt->io); /* volume down + sigstr + on */
|
||||||
|
- sleep_delay(100000);
|
||||||
|
+ msleep(100);
|
||||||
|
outb(0xd8, rt->io); /* volume steady + sigstr + on */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rt_incvol(struct rtrack *rt)
|
||||||
|
{
|
||||||
|
outb(0x98, rt->io); /* volume up + sigstr + on */
|
||||||
|
- sleep_delay(100000);
|
||||||
|
+ msleep(100);
|
||||||
|
outb(0xd8, rt->io); /* volume steady + sigstr + on */
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -120,7 +109,7 @@ static int rt_setvol(struct rtrack *rt, int vol)
|
||||||
|
|
||||||
|
if (vol == 0) { /* volume = 0 means mute the card */
|
||||||
|
outb(0x48, rt->io); /* volume down but still "on" */
|
||||||
|
- sleep_delay(2000000); /* make sure it's totally down */
|
||||||
|
+ msleep(2000); /* make sure it's totally down */
|
||||||
|
outb(0xd0, rt->io); /* volume steady, off */
|
||||||
|
rt->curvol = 0; /* track the volume state! */
|
||||||
|
mutex_unlock(&rt->lock);
|
||||||
|
@@ -155,7 +144,7 @@ static void send_0_byte(struct rtrack *rt)
|
||||||
|
outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */
|
||||||
|
outb_p(128+64+16+8+2+1, rt->io); /* clock */
|
||||||
|
}
|
||||||
|
- sleep_delay(1000);
|
||||||
|
+ msleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_1_byte(struct rtrack *rt)
|
||||||
|
@@ -169,7 +158,7 @@ static void send_1_byte(struct rtrack *rt)
|
||||||
|
outb_p(128+64+16+8+4+2+1, rt->io); /* clock */
|
||||||
|
}
|
||||||
|
|
||||||
|
- sleep_delay(1000);
|
||||||
|
+ msleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rt_setfreq(struct rtrack *rt, unsigned long freq)
|
||||||
|
@@ -427,7 +416,7 @@ static int __init rtrack_init(void)
|
||||||
|
|
||||||
|
/* this ensures that the volume is all the way down */
|
||||||
|
outb(0x48, rt->io); /* volume down but still "on" */
|
||||||
|
- sleep_delay(2000000); /* make sure it's totally down */
|
||||||
|
+ msleep(2000); /* make sure it's totally down */
|
||||||
|
outb(0xc0, rt->io); /* steady volume, mute card */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
commit 515884e98dc4f1c99387000d420394c3bc47c0d7
|
||||||
|
Author: Dan Carpenter <error27@gmail.com>
|
||||||
|
Date: Fri Jan 7 16:41:54 2011 -0300
|
||||||
|
|
||||||
|
av7110: check for negative array offset
|
||||||
|
|
||||||
|
commit cb26a24ee9706473f31d34cc259f4dcf45cd0644 upstream.
|
||||||
|
|
||||||
|
info->num comes from the user. It's type int. If the user passes
|
||||||
|
in a negative value that would cause memory corruption.
|
||||||
|
|
||||||
|
Signed-off-by: Dan Carpenter <error27@gmail.com>
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
|
||||||
|
index 4eba35a..c38dd67 100644
|
||||||
|
--- a/drivers/media/dvb/ttpci/av7110_ca.c
|
||||||
|
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
|
||||||
|
@@ -277,7 +277,7 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
|
||||||
|
{
|
||||||
|
ca_slot_info_t *info=(ca_slot_info_t *)parg;
|
||||||
|
|
||||||
|
- if (info->num > 1)
|
||||||
|
+ if (info->num < 0 || info->num > 1)
|
||||||
|
return -EINVAL;
|
||||||
|
av7110->ci_slot[info->num].num = info->num;
|
||||||
|
av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
|
||||||
|
|
||||||
|
commit 9e5ad61f8d81da0b58535ac2cf60d36e26ca567a
|
||||||
|
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Date: Mon Oct 25 17:51:15 2010 -0300
|
||||||
|
|
||||||
|
em28xx: Fix audio input for Terratec Grabby
|
||||||
|
|
||||||
|
commit a3fa904ec79b94f0db7faed010ff94d42f7d1d47 upstream.
|
||||||
|
|
||||||
|
The audio input line was wrong. Fix it.
|
||||||
|
|
||||||
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
Signed-off-by: Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
|
||||||
|
index 3a4fd85..2fa5bb4 100644
|
||||||
|
--- a/drivers/media/video/em28xx/em28xx-cards.c
|
||||||
|
+++ b/drivers/media/video/em28xx/em28xx-cards.c
|
||||||
|
@@ -1605,11 +1605,11 @@ struct em28xx_board em28xx_boards[] = {
|
||||||
|
.input = { {
|
||||||
|
.type = EM28XX_VMUX_COMPOSITE1,
|
||||||
|
.vmux = SAA7115_COMPOSITE0,
|
||||||
|
- .amux = EM28XX_AMUX_VIDEO2,
|
||||||
|
+ .amux = EM28XX_AMUX_LINE_IN,
|
||||||
|
}, {
|
||||||
|
.type = EM28XX_VMUX_SVIDEO,
|
||||||
|
.vmux = SAA7115_SVIDEO3,
|
||||||
|
- .amux = EM28XX_AMUX_VIDEO2,
|
||||||
|
+ .amux = EM28XX_AMUX_LINE_IN,
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
[EM2860_BOARD_TERRATEC_AV350] = {
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
commit 611225f5e7f9d11c4b119fac224f1bd6903b0150
|
|
||||||
Author: Jarod Wilson <jarod@redhat.com>
|
|
||||||
Date: Sun Mar 7 17:55:43 2010 -0300
|
|
||||||
|
|
||||||
V4L/DVB: dvb: add support for kworld 340u and ub435-q to em28xx-dvb
|
|
||||||
|
|
||||||
This adds support for the KWorld PlusTV 340U and KWorld UB345-Q ATSC
|
|
||||||
sticks, which are really the same device. The sticks have an eMPIA
|
|
||||||
em2870 usb bridge chipset, an LG Electronics LGDT3304 ATSC/QAM
|
|
||||||
demodulator and an NXP TDA18271HD tuner -- early versions of the 340U
|
|
||||||
have a a TDA18271HD/C1, later models and the UB435-Q have a C2.
|
|
||||||
|
|
||||||
The stick has been tested succesfully with both VSB_8 and QAM_256 signals.
|
|
||||||
Its using lgdt3304 support added to the lgdt3305 driver by a prior patch,
|
|
||||||
rather than the current lgdt3304 driver, as its severely lacking in
|
|
||||||
functionality by comparison (see said patch for details).
|
|
||||||
|
|
||||||
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
|
||||||
Signed-off-by: Michael Krufky <mkrufky@kernellabs.com>
|
|
||||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
|
|
||||||
index 3a623aa..5c56875 100644
|
|
||||||
--- a/Documentation/video4linux/CARDLIST.em28xx
|
|
||||||
+++ b/Documentation/video4linux/CARDLIST.em28xx
|
|
||||||
@@ -72,3 +72,4 @@
|
|
||||||
73 -> Reddo DVB-C USB TV Box (em2870)
|
|
||||||
74 -> Actionmaster/LinXcel/Digitus VC211A (em2800)
|
|
||||||
75 -> Dikom DK300 (em2882)
|
|
||||||
+ 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
|
|
||||||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
|
|
||||||
index 3a4fd85..ffbe544 100644
|
|
||||||
--- a/drivers/media/video/em28xx/em28xx-cards.c
|
|
||||||
+++ b/drivers/media/video/em28xx/em28xx-cards.c
|
|
||||||
@@ -158,6 +158,22 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
|
|
||||||
{ -1, -1, -1, -1},
|
|
||||||
};
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map:
|
|
||||||
+ * EM_GPIO_0 - currently unknown
|
|
||||||
+ * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on)
|
|
||||||
+ * EM_GPIO_2 - currently unknown
|
|
||||||
+ * EM_GPIO_3 - currently unknown
|
|
||||||
+ * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset)
|
|
||||||
+ * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset)
|
|
||||||
+ * EM_GPIO_6 - currently unknown
|
|
||||||
+ * EM_GPIO_7 - currently unknown
|
|
||||||
+ */
|
|
||||||
+static struct em28xx_reg_seq kworld_a340_digital[] = {
|
|
||||||
+ {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10},
|
|
||||||
+ { -1, -1, -1, -1},
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* Pinnacle Hybrid Pro eb1a:2881 */
|
|
||||||
static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
|
|
||||||
{EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10},
|
|
||||||
@@ -1667,6 +1683,16 @@ struct em28xx_board em28xx_boards[] = {
|
|
||||||
.tuner_gpio = reddo_dvb_c_usb_box,
|
|
||||||
.has_dvb = 1,
|
|
||||||
},
|
|
||||||
+ /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
|
|
||||||
+ * initially as the KWorld PlusTV 340U, then as the UB435-Q.
|
|
||||||
+ * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */
|
|
||||||
+ [EM2870_BOARD_KWORLD_A340] = {
|
|
||||||
+ .name = "KWorld PlusTV 340U or UB435-Q (ATSC)",
|
|
||||||
+ .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */
|
|
||||||
+ .has_dvb = 1,
|
|
||||||
+ .dvb_gpio = kworld_a340_digital,
|
|
||||||
+ .tuner_gpio = default_tuner_gpio,
|
|
||||||
+ },
|
|
||||||
};
|
|
||||||
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
|
|
||||||
|
|
||||||
@@ -1788,6 +1814,8 @@ struct usb_device_id em28xx_id_table[] = {
|
|
||||||
.driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
|
|
||||||
{ USB_DEVICE(0xeb1a, 0x50a6),
|
|
||||||
.driver_info = EM2860_BOARD_GADMEI_UTV330 },
|
|
||||||
+ { USB_DEVICE(0x1b80, 0xa340),
|
|
||||||
+ .driver_info = EM2870_BOARD_KWORLD_A340 },
|
|
||||||
{ },
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
|
|
||||||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
|
|
||||||
index cf1d8c3..3ac8d30 100644
|
|
||||||
--- a/drivers/media/video/em28xx/em28xx-dvb.c
|
|
||||||
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
|
|
||||||
@@ -30,11 +30,13 @@
|
|
||||||
#include "tuner-simple.h"
|
|
||||||
|
|
||||||
#include "lgdt330x.h"
|
|
||||||
+#include "lgdt3305.h"
|
|
||||||
#include "zl10353.h"
|
|
||||||
#include "s5h1409.h"
|
|
||||||
#include "mt352.h"
|
|
||||||
#include "mt352_priv.h" /* FIXME */
|
|
||||||
#include "tda1002x.h"
|
|
||||||
+#include "tda18271.h"
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
|
|
||||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
|
|
||||||
@@ -231,6 +233,18 @@ static struct lgdt330x_config em2880_lgdt3303_dev = {
|
|
||||||
.demod_chip = LGDT3303,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static struct lgdt3305_config em2870_lgdt3304_dev = {
|
|
||||||
+ .i2c_addr = 0x0e,
|
|
||||||
+ .demod_chip = LGDT3304,
|
|
||||||
+ .spectral_inversion = 1,
|
|
||||||
+ .deny_i2c_rptr = 1,
|
|
||||||
+ .mpeg_mode = LGDT3305_MPEG_PARALLEL,
|
|
||||||
+ .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE,
|
|
||||||
+ .tpvalid_polarity = LGDT3305_TP_VALID_HIGH,
|
|
||||||
+ .vsb_if_khz = 3250,
|
|
||||||
+ .qam_if_khz = 4000,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static struct zl10353_config em28xx_zl10353_with_xc3028 = {
|
|
||||||
.demod_address = (0x1e >> 1),
|
|
||||||
.no_tuner = 1,
|
|
||||||
@@ -247,6 +261,17 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
|
|
||||||
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
|
|
||||||
};
|
|
||||||
|
|
||||||
+static struct tda18271_std_map kworld_a340_std_map = {
|
|
||||||
+ .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0,
|
|
||||||
+ .if_lvl = 1, .rfagc_top = 0x37, },
|
|
||||||
+ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1,
|
|
||||||
+ .if_lvl = 1, .rfagc_top = 0x37, },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct tda18271_config kworld_a340_config = {
|
|
||||||
+ .std_map = &kworld_a340_std_map,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
|
|
||||||
.demod_address = (0x1e >> 1),
|
|
||||||
.no_tuner = 1,
|
|
||||||
@@ -572,6 +597,14 @@ static int dvb_init(struct em28xx *dev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
+ case EM2870_BOARD_KWORLD_A340:
|
|
||||||
+ dvb->frontend = dvb_attach(lgdt3305_attach,
|
|
||||||
+ &em2870_lgdt3304_dev,
|
|
||||||
+ &dev->i2c_adap);
|
|
||||||
+ if (dvb->frontend != NULL)
|
|
||||||
+ dvb_attach(tda18271_attach, dvb->frontend, 0x60,
|
|
||||||
+ &dev->i2c_adap, &kworld_a340_config);
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
|
|
||||||
" isn't supported yet\n");
|
|
||||||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
|
|
||||||
index 6216786..1c61a6b 100644
|
|
||||||
--- a/drivers/media/video/em28xx/em28xx.h
|
|
||||||
+++ b/drivers/media/video/em28xx/em28xx.h
|
|
||||||
@@ -114,6 +114,7 @@
|
|
||||||
#define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73
|
|
||||||
#define EM2800_BOARD_VC211A 74
|
|
||||||
#define EM2882_BOARD_DIKOM_DK300 75
|
|
||||||
+#define EM2870_BOARD_KWORLD_A340 76
|
|
||||||
|
|
||||||
/* Limits minimum and default number of buffers */
|
|
||||||
#define EM28XX_MIN_BUF 4
|
|
|
@ -1,350 +0,0 @@
|
||||||
From b71e18093e2e7f240797875c50c49552722f8825 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jarod Wilson <jarod@redhat.com>
|
|
||||||
Date: Mon, 15 Feb 2010 17:13:25 -0500
|
|
||||||
Subject: [PATCH 1/2] dvb: add lgdt3304 support to lgdt3305 driver
|
|
||||||
|
|
||||||
There's a currently-unused lgdt3304 demod driver, which leaves a lot to
|
|
||||||
be desired as far as functionality. The 3304 is unsurprisingly quite
|
|
||||||
similar to the 3305, and empirical testing yeilds far better results
|
|
||||||
and more complete functionality by merging 3304 support into the 3305
|
|
||||||
driver. (For example, the current lgdt3304 driver lacks support for
|
|
||||||
signal strength, snr, ucblocks, etc., which we get w/the lgdt3305).
|
|
||||||
|
|
||||||
For the moment, not dropping the lgdt3304 driver, and its still up to
|
|
||||||
a given device's config setup to choose which demod driver to use, but
|
|
||||||
I'd suggest dropping the 3304 driver entirely.
|
|
||||||
|
|
||||||
As a follow-up to this patch, I've got another patch that adds support
|
|
||||||
for the KWorld PlusTV 340U (ATSC) em2870-based tuner stick, driving
|
|
||||||
its lgdt3304 demod via this lgdt3305 driver, which is what I used to
|
|
||||||
successfully test this patch with both VSB_8 and QAM_256 signals.
|
|
||||||
|
|
||||||
A few pieces are still a touch crude, but I think its a solid start,
|
|
||||||
as well as much cleaner and more feature-complete than the existing
|
|
||||||
lgdt3304 driver.
|
|
||||||
|
|
||||||
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
|
||||||
---
|
|
||||||
drivers/media/dvb/frontends/lgdt3305.c | 206 ++++++++++++++++++++++++++++++--
|
|
||||||
drivers/media/dvb/frontends/lgdt3305.h | 6 +
|
|
||||||
2 files changed, 203 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
|
|
||||||
index fde8c59..40695e6 100644
|
|
||||||
--- a/drivers/media/dvb/frontends/lgdt3305.c
|
|
||||||
+++ b/drivers/media/dvb/frontends/lgdt3305.c
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
/*
|
|
||||||
- * Support for LGDT3305 - VSB/QAM
|
|
||||||
+ * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
|
|
||||||
*
|
|
||||||
* Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
|
|
||||||
*
|
|
||||||
@@ -357,7 +357,10 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
|
|
||||||
case QAM_256:
|
|
||||||
agcdelay = 0x046b;
|
|
||||||
rfbw = 0x8889;
|
|
||||||
- ifbw = 0x8888;
|
|
||||||
+ if (state->cfg->demod_chip == LGDT3305)
|
|
||||||
+ ifbw = 0x8888;
|
|
||||||
+ else
|
|
||||||
+ ifbw = 0x6666;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
@@ -409,8 +412,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
|
|
||||||
lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
|
|
||||||
|
|
||||||
/* control agc function */
|
|
||||||
- lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
|
||||||
- lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
|
||||||
+ switch (state->cfg->demod_chip) {
|
|
||||||
+ case LGDT3304:
|
|
||||||
+ lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
|
|
||||||
+ lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
|
|
||||||
+ break;
|
|
||||||
+ case LGDT3305:
|
|
||||||
+ lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
|
||||||
+ lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return lgdt3305_rfagc_loop(state, param);
|
|
||||||
}
|
|
||||||
@@ -543,6 +556,11 @@ static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
|
|
||||||
enable ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int lgdt3304_sleep(struct dvb_frontend *fe)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int lgdt3305_sleep(struct dvb_frontend *fe)
|
|
||||||
{
|
|
||||||
struct lgdt3305_state *state = fe->demodulator_priv;
|
|
||||||
@@ -571,6 +589,55 @@ static int lgdt3305_sleep(struct dvb_frontend *fe)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int lgdt3304_init(struct dvb_frontend *fe)
|
|
||||||
+{
|
|
||||||
+ struct lgdt3305_state *state = fe->demodulator_priv;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ static struct lgdt3305_reg lgdt3304_init_data[] = {
|
|
||||||
+ { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
|
|
||||||
+ { .reg = 0x000d, .val = 0x02, },
|
|
||||||
+ { .reg = 0x000e, .val = 0x02, },
|
|
||||||
+ { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
|
|
||||||
+ { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
|
|
||||||
+ { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
|
|
||||||
+ { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
|
|
||||||
+ { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
|
|
||||||
+ { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
|
|
||||||
+ { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
|
|
||||||
+ { .reg = 0x0112, .val = 0x17, },
|
|
||||||
+ { .reg = 0x0113, .val = 0x15, },
|
|
||||||
+ { .reg = 0x0114, .val = 0x18, },
|
|
||||||
+ { .reg = 0x0115, .val = 0xff, },
|
|
||||||
+ { .reg = 0x0116, .val = 0x3c, },
|
|
||||||
+ { .reg = 0x0214, .val = 0x67, },
|
|
||||||
+ { .reg = 0x0424, .val = 0x8d, },
|
|
||||||
+ { .reg = 0x0427, .val = 0x12, },
|
|
||||||
+ { .reg = 0x0428, .val = 0x4f, },
|
|
||||||
+ { .reg = LGDT3305_IFBW_1, .val = 0x80, },
|
|
||||||
+ { .reg = LGDT3305_IFBW_2, .val = 0x00, },
|
|
||||||
+ { .reg = 0x030a, .val = 0x08, },
|
|
||||||
+ { .reg = 0x030b, .val = 0x9b, },
|
|
||||||
+ { .reg = 0x030d, .val = 0x00, },
|
|
||||||
+ { .reg = 0x030e, .val = 0x1c, },
|
|
||||||
+ { .reg = 0x0314, .val = 0xe1, },
|
|
||||||
+ { .reg = 0x000d, .val = 0x82, },
|
|
||||||
+ { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
|
||||||
+ { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ lg_dbg("\n");
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_write_regs(state, lgdt3304_init_data,
|
|
||||||
+ ARRAY_SIZE(lgdt3304_init_data));
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_soft_reset(state);
|
|
||||||
+fail:
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int lgdt3305_init(struct dvb_frontend *fe)
|
|
||||||
{
|
|
||||||
struct lgdt3305_state *state = fe->demodulator_priv;
|
|
||||||
@@ -639,6 +706,88 @@ fail:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int lgdt3304_set_parameters(struct dvb_frontend *fe,
|
|
||||||
+ struct dvb_frontend_parameters *param)
|
|
||||||
+{
|
|
||||||
+ struct lgdt3305_state *state = fe->demodulator_priv;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
|
|
||||||
+
|
|
||||||
+ if (fe->ops.tuner_ops.set_params) {
|
|
||||||
+ ret = fe->ops.tuner_ops.set_params(fe, param);
|
|
||||||
+ if (fe->ops.i2c_gate_ctrl)
|
|
||||||
+ fe->ops.i2c_gate_ctrl(fe, 0);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+ state->current_frequency = param->frequency;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_set_modulation(state, param);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_passband_digital_agc(state, param);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_agc_setup(state, param);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
|
|
||||||
+ switch (param->u.vsb.modulation) {
|
|
||||||
+ case VSB_8:
|
|
||||||
+ lgdt3305_write_reg(state, 0x030d, 0x00);
|
|
||||||
+#if 1
|
|
||||||
+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
|
|
||||||
+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
|
|
||||||
+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
|
|
||||||
+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
|
|
||||||
+#endif
|
|
||||||
+ break;
|
|
||||||
+ case QAM_64:
|
|
||||||
+ case QAM_256:
|
|
||||||
+ lgdt3305_write_reg(state, 0x030d, 0x14);
|
|
||||||
+#if 1
|
|
||||||
+ ret = lgdt3305_set_if(state, param);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+#endif
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+#if 0
|
|
||||||
+ /* the set_if vsb formula doesn't work for the 3304, we end up sending
|
|
||||||
+ * 0x40851e07 instead of 0x4f0cacba (which works back to 94050, rather
|
|
||||||
+ * than 3250, in the case of the kworld 340u) */
|
|
||||||
+ ret = lgdt3305_set_if(state, param);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_spectral_inversion(state, param,
|
|
||||||
+ state->cfg->spectral_inversion
|
|
||||||
+ ? 1 : 0);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ state->current_modulation = param->u.vsb.modulation;
|
|
||||||
+
|
|
||||||
+ ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
|
|
||||||
+ if (lg_fail(ret))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
|
||||||
+ ret = lgdt3305_mpeg_mode_polarity(state,
|
|
||||||
+ state->cfg->tpclk_edge,
|
|
||||||
+ state->cfg->tpvalid_polarity);
|
|
||||||
+fail:
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int lgdt3305_set_parameters(struct dvb_frontend *fe,
|
|
||||||
struct dvb_frontend_parameters *param)
|
|
||||||
{
|
|
||||||
@@ -847,6 +996,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|
||||||
switch (state->current_modulation) {
|
|
||||||
case QAM_256:
|
|
||||||
case QAM_64:
|
|
||||||
+#if 0 /* needed w/3304 to set FE_HAS_SIGNAL */
|
|
||||||
+ if (cr_lock)
|
|
||||||
+ *status |= FE_HAS_SIGNAL;
|
|
||||||
+#endif
|
|
||||||
ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
|
|
||||||
if (lg_fail(ret))
|
|
||||||
goto fail;
|
|
||||||
@@ -992,6 +1145,7 @@ static void lgdt3305_release(struct dvb_frontend *fe)
|
|
||||||
kfree(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static struct dvb_frontend_ops lgdt3304_ops;
|
|
||||||
static struct dvb_frontend_ops lgdt3305_ops;
|
|
||||||
|
|
||||||
struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|
||||||
@@ -1012,11 +1166,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|
||||||
state->cfg = config;
|
|
||||||
state->i2c_adap = i2c_adap;
|
|
||||||
|
|
||||||
- memcpy(&state->frontend.ops, &lgdt3305_ops,
|
|
||||||
- sizeof(struct dvb_frontend_ops));
|
|
||||||
+ switch (config->demod_chip) {
|
|
||||||
+ case LGDT3304:
|
|
||||||
+ memcpy(&state->frontend.ops, &lgdt3304_ops,
|
|
||||||
+ sizeof(struct dvb_frontend_ops));
|
|
||||||
+ break;
|
|
||||||
+ case LGDT3305:
|
|
||||||
+ memcpy(&state->frontend.ops, &lgdt3305_ops,
|
|
||||||
+ sizeof(struct dvb_frontend_ops));
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ goto fail;
|
|
||||||
+ }
|
|
||||||
state->frontend.demodulator_priv = state;
|
|
||||||
|
|
||||||
- /* verify that we're talking to a lg dt3305 */
|
|
||||||
+ /* verify that we're talking to a lg dt3304/5 */
|
|
||||||
ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
|
|
||||||
if ((lg_fail(ret)) | (val == 0))
|
|
||||||
goto fail;
|
|
||||||
@@ -1035,12 +1199,36 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|
||||||
|
|
||||||
return &state->frontend;
|
|
||||||
fail:
|
|
||||||
- lg_warn("unable to detect LGDT3305 hardware\n");
|
|
||||||
+ lg_warn("unable to detect %s hardware\n",
|
|
||||||
+ config->demod_chip ? "LGDT3304" : "LGDT3305");
|
|
||||||
kfree(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(lgdt3305_attach);
|
|
||||||
|
|
||||||
+static struct dvb_frontend_ops lgdt3304_ops = {
|
|
||||||
+ .info = {
|
|
||||||
+ .name = "LG Electronics LGDT3304 VSB/QAM Frontend",
|
|
||||||
+ .type = FE_ATSC,
|
|
||||||
+ .frequency_min = 54000000,
|
|
||||||
+ .frequency_max = 858000000,
|
|
||||||
+ .frequency_stepsize = 62500,
|
|
||||||
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
|
|
||||||
+ },
|
|
||||||
+ .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
|
|
||||||
+ .init = lgdt3304_init,
|
|
||||||
+ .sleep = lgdt3304_sleep,
|
|
||||||
+ .set_frontend = lgdt3304_set_parameters,
|
|
||||||
+ .get_frontend = lgdt3305_get_frontend,
|
|
||||||
+ .get_tune_settings = lgdt3305_get_tune_settings,
|
|
||||||
+ .read_status = lgdt3305_read_status,
|
|
||||||
+ .read_ber = lgdt3305_read_ber,
|
|
||||||
+ .read_signal_strength = lgdt3305_read_signal_strength,
|
|
||||||
+ .read_snr = lgdt3305_read_snr,
|
|
||||||
+ .read_ucblocks = lgdt3305_read_ucblocks,
|
|
||||||
+ .release = lgdt3305_release,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static struct dvb_frontend_ops lgdt3305_ops = {
|
|
||||||
.info = {
|
|
||||||
.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
|
|
||||||
@@ -1064,7 +1252,7 @@ static struct dvb_frontend_ops lgdt3305_ops = {
|
|
||||||
.release = lgdt3305_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
-MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
|
|
||||||
+MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
|
|
||||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
MODULE_VERSION("0.1");
|
|
||||||
diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h
|
|
||||||
index 9cb11c9..a7f30c2 100644
|
|
||||||
--- a/drivers/media/dvb/frontends/lgdt3305.h
|
|
||||||
+++ b/drivers/media/dvb/frontends/lgdt3305.h
|
|
||||||
@@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity {
|
|
||||||
LGDT3305_TP_VALID_HIGH = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
+enum lgdt_demod_chip_type {
|
|
||||||
+ LGDT3305 = 0,
|
|
||||||
+ LGDT3304 = 1,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
struct lgdt3305_config {
|
|
||||||
u8 i2c_addr;
|
|
||||||
|
|
||||||
@@ -65,6 +70,7 @@ struct lgdt3305_config {
|
|
||||||
enum lgdt3305_mpeg_mode mpeg_mode;
|
|
||||||
enum lgdt3305_tp_clock_edge tpclk_edge;
|
|
||||||
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
|
||||||
+ enum lgdt_demod_chip_type demod_chip;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
|
|
||||||
--
|
|
||||||
1.6.6
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue