Gentoo Archives: gentoo-commits

From: "Tom Wijsman (tomwij)" <tomwij@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] linux-patches r2356 - genpatches-2.6/trunk/3.9
Date: Mon, 29 Apr 2013 17:10:16
Message-Id: 20130429171011.2644A2171D@flycatcher.gentoo.org
1 Author: tomwij
2 Date: 2013-04-29 17:10:10 +0000 (Mon, 29 Apr 2013)
3 New Revision: 2356
4
5 Added:
6 genpatches-2.6/trunk/3.9/1700_enable-thinkpad-micled.patch
7 genpatches-2.6/trunk/3.9/2400_kcopy-patch-for-infiniband-driver.patch
8 genpatches-2.6/trunk/3.9/2700_ThinkPad-30-brightness-control-fix.patch
9 genpatches-2.6/trunk/3.9/2900_dev-root-proc-mount-fix.patch
10 Modified:
11 genpatches-2.6/trunk/3.9/0000_README
12 Log:
13 Linux patch 3.9.0.
14
15 Modified: genpatches-2.6/trunk/3.9/0000_README
16 ===================================================================
17 --- genpatches-2.6/trunk/3.9/0000_README 2013-04-26 21:46:44 UTC (rev 2355)
18 +++ genpatches-2.6/trunk/3.9/0000_README 2013-04-29 17:10:10 UTC (rev 2356)
19 @@ -39,6 +39,26 @@
20
21 Individual Patch Descriptions:
22 --------------------------------------------------------------------------
23 +Patch: 1700_enable-thinkpad-micled.patch
24 +From: https://bugs.gentoo.org/show_bug.cgi?id=449248
25 +Desc: Enable mic mute led in thinkpads
26 +
27 +Patch: 1800_memcg-OOM-revert-ZFS-deadlock.patch
28 +From: https://bugs.gentoo.org/show_bug.cgi?id=462066
29 +Desc: Revert memcg patches that prevent OOM with too many dirty pages.
30 +
31 +Patch: 2400_kcopy-patch-for-infiniband-driver.patch
32 +From: Alexey Shvetsov <alexxy@g.o>
33 +Desc: Zero copy for infiniband psm userspace driver
34 +
35 +Patch: 2700_ThinkPad-30-brightness-control-fix.patch
36 +From: Seth Forshee <seth.forshee@×××××××××.com>
37 +Desc: ACPI: Disable Windows 8 compatibility for some Lenovo ThinkPads
38 +
39 +Patch: 2900_dev-root-proc-mount-fix.patch
40 +From: https://bugs.gentoo.org/show_bug.cgi?id=438380
41 +Desc: Ensure that /dev/root doesn't appear in /proc/mounts when bootint without an initramfs.
42 +
43 Patch: 4200_fbcondecor-0.9.6.patch
44 From: http://dev.gentoo.org/~spock
45 Desc: Bootsplash successor by Michal Januszewski ported by Jeremy (bug #452574)
46
47 Added: genpatches-2.6/trunk/3.9/1700_enable-thinkpad-micled.patch
48 ===================================================================
49 --- genpatches-2.6/trunk/3.9/1700_enable-thinkpad-micled.patch (rev 0)
50 +++ genpatches-2.6/trunk/3.9/1700_enable-thinkpad-micled.patch 2013-04-29 17:10:10 UTC (rev 2356)
51 @@ -0,0 +1,23 @@
52 +--- a/drivers/platform/x86/thinkpad_acpi.c 2013-02-06 08:46:53.546168051 -0500
53 ++++ b/drivers/platform/x86/thinkpad_acpi.c 2013-02-06 08:52:16.846933455 -0500
54 +@@ -5056,8 +5056,10 @@ static const char * const tpacpi_led_nam
55 + "tpacpi::unknown_led2",
56 + "tpacpi::unknown_led3",
57 + "tpacpi::thinkvantage",
58 ++ "tpacpi::unknown_led4",
59 ++ "tpacpi::micmute",
60 + };
61 +-#define TPACPI_SAFE_LEDS 0x1081U
62 ++#define TPACPI_SAFE_LEDS 0x5081U
63 +
64 + static inline bool tpacpi_is_led_restricted(const unsigned int led)
65 + {
66 +@@ -5280,7 +5282,7 @@ static const struct tpacpi_quirk led_use
67 + { /* Lenovo */
68 + .vendor = PCI_VENDOR_ID_LENOVO,
69 + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
70 +- .quirks = 0x1fffU,
71 ++ .quirks = 0x5fffU,
72 + },
73 + { /* IBM ThinkPads with no EC version string */
74 + .vendor = PCI_VENDOR_ID_IBM,
75
76 Added: genpatches-2.6/trunk/3.9/2400_kcopy-patch-for-infiniband-driver.patch
77 ===================================================================
78 --- genpatches-2.6/trunk/3.9/2400_kcopy-patch-for-infiniband-driver.patch (rev 0)
79 +++ genpatches-2.6/trunk/3.9/2400_kcopy-patch-for-infiniband-driver.patch 2013-04-29 17:10:10 UTC (rev 2356)
80 @@ -0,0 +1,731 @@
81 +From 1f52075d672a9bdd0069b3ea68be266ef5c229bd Mon Sep 17 00:00:00 2001
82 +From: Alexey Shvetsov <alexxy@g.o>
83 +Date: Tue, 17 Jan 2012 21:08:49 +0400
84 +Subject: [PATCH] [kcopy] Add kcopy driver
85 +
86 +Add kcopy driver from qlogic to implement zero copy for infiniband psm
87 +userspace driver
88 +
89 +Signed-off-by: Alexey Shvetsov <alexxy@g.o>
90 +---
91 + drivers/char/Kconfig | 2 +
92 + drivers/char/Makefile | 2 +
93 + drivers/char/kcopy/Kconfig | 17 ++
94 + drivers/char/kcopy/Makefile | 4 +
95 + drivers/char/kcopy/kcopy.c | 646 +++++++++++++++++++++++++++++++++++++++++++
96 + 5 files changed, 671 insertions(+)
97 + create mode 100644 drivers/char/kcopy/Kconfig
98 + create mode 100644 drivers/char/kcopy/Makefile
99 + create mode 100644 drivers/char/kcopy/kcopy.c
100 +
101 +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
102 +index ee94686..5b81449 100644
103 +--- a/drivers/char/Kconfig
104 ++++ b/drivers/char/Kconfig
105 +@@ -6,6 +6,8 @@ menu "Character devices"
106 +
107 + source "drivers/tty/Kconfig"
108 +
109 ++source "drivers/char/kcopy/Kconfig"
110 ++
111 + config DEVKMEM
112 + bool "/dev/kmem virtual device support"
113 + default y
114 +diff --git a/drivers/char/Makefile b/drivers/char/Makefile
115 +index 0dc5d7c..be519d6 100644
116 +--- a/drivers/char/Makefile
117 ++++ b/drivers/char/Makefile
118 +@@ -62,3 +62,5 @@
119 + js-rtc-y = rtc.o
120 +
121 + obj-$(CONFIG_TILE_SROM) += tile-srom.o
122 ++
123 ++obj-$(CONFIG_KCOPY) += kcopy/
124 +diff --git a/drivers/char/kcopy/Kconfig b/drivers/char/kcopy/Kconfig
125 +new file mode 100644
126 +index 0000000..453ae52
127 +--- /dev/null
128 ++++ b/drivers/char/kcopy/Kconfig
129 +@@ -0,0 +1,17 @@
130 ++#
131 ++# KCopy character device configuration
132 ++#
133 ++
134 ++menu "KCopy"
135 ++
136 ++config KCOPY
137 ++ tristate "Memory-to-memory copies using kernel assist"
138 ++ default m
139 ++ ---help---
140 ++ High-performance inter-process memory copies. Can often save a
141 ++ memory copy to shared memory in the application. Useful at least
142 ++ for MPI applications where the point-to-point nature of vmsplice
143 ++ and pipes can be a limiting factor in performance.
144 ++
145 ++endmenu
146 ++
147 +diff --git a/drivers/char/kcopy/Makefile b/drivers/char/kcopy/Makefile
148 +new file mode 100644
149 +index 0000000..9cb269b
150 +--- /dev/null
151 ++++ b/drivers/char/kcopy/Makefile
152 +@@ -0,0 +1,4 @@
153 ++#
154 ++# Makefile for the kernel character device drivers.
155 ++#
156 ++obj-$(CONFIG_KCOPY) += kcopy.o
157 +diff --git a/drivers/char/kcopy/kcopy.c b/drivers/char/kcopy/kcopy.c
158 +new file mode 100644
159 +index 0000000..a9f915c
160 +--- /dev/null
161 ++++ b/drivers/char/kcopy/kcopy.c
162 +@@ -0,0 +1,646 @@
163 ++#include <linux/module.h>
164 ++#include <linux/fs.h>
165 ++#include <linux/cdev.h>
166 ++#include <linux/device.h>
167 ++#include <linux/mutex.h>
168 ++#include <linux/mman.h>
169 ++#include <linux/highmem.h>
170 ++#include <linux/spinlock.h>
171 ++#include <linux/sched.h>
172 ++#include <linux/rbtree.h>
173 ++#include <linux/rcupdate.h>
174 ++#include <linux/uaccess.h>
175 ++#include <linux/slab.h>
176 ++
177 ++MODULE_LICENSE("GPL");
178 ++MODULE_AUTHOR("Arthur Jones <arthur.jones@××××××.com>");
179 ++MODULE_DESCRIPTION("QLogic kcopy driver");
180 ++
181 ++#define KCOPY_ABI 1
182 ++#define KCOPY_MAX_MINORS 64
183 ++
184 ++struct kcopy_device {
185 ++ struct cdev cdev;
186 ++ struct class *class;
187 ++ struct device *devp[KCOPY_MAX_MINORS];
188 ++ dev_t dev;
189 ++
190 ++ struct kcopy_file *kf[KCOPY_MAX_MINORS];
191 ++ struct mutex open_lock;
192 ++};
193 ++
194 ++static struct kcopy_device kcopy_dev;
195 ++
196 ++/* per file data / one of these is shared per minor */
197 ++struct kcopy_file {
198 ++ int count;
199 ++
200 ++ /* pid indexed */
201 ++ struct rb_root live_map_tree;
202 ++
203 ++ struct mutex map_lock;
204 ++};
205 ++
206 ++struct kcopy_map_entry {
207 ++ int count;
208 ++ struct task_struct *task;
209 ++ pid_t pid;
210 ++ struct kcopy_file *file; /* file backpointer */
211 ++
212 ++ struct list_head list; /* free map list */
213 ++ struct rb_node node; /* live map tree */
214 ++};
215 ++
216 ++#define KCOPY_GET_SYSCALL 1
217 ++#define KCOPY_PUT_SYSCALL 2
218 ++#define KCOPY_ABI_SYSCALL 3
219 ++
220 ++struct kcopy_syscall {
221 ++ __u32 tag;
222 ++ pid_t pid;
223 ++ __u64 n;
224 ++ __u64 src;
225 ++ __u64 dst;
226 ++};
227 ++
228 ++static const void __user *kcopy_syscall_src(const struct kcopy_syscall *ks)
229 ++{
230 ++ return (const void __user *) (unsigned long) ks->src;
231 ++}
232 ++
233 ++static void __user *kcopy_syscall_dst(const struct kcopy_syscall *ks)
234 ++{
235 ++ return (void __user *) (unsigned long) ks->dst;
236 ++}
237 ++
238 ++static unsigned long kcopy_syscall_n(const struct kcopy_syscall *ks)
239 ++{
240 ++ return (unsigned long) ks->n;
241 ++}
242 ++
243 ++static struct kcopy_map_entry *kcopy_create_entry(struct kcopy_file *file)
244 ++{
245 ++ struct kcopy_map_entry *kme =
246 ++ kmalloc(sizeof(struct kcopy_map_entry), GFP_KERNEL);
247 ++
248 ++ if (!kme)
249 ++ return NULL;
250 ++
251 ++ kme->count = 1;
252 ++ kme->file = file;
253 ++ kme->task = current;
254 ++ kme->pid = current->tgid;
255 ++ INIT_LIST_HEAD(&kme->list);
256 ++
257 ++ return kme;
258 ++}
259 ++
260 ++static struct kcopy_map_entry *
261 ++kcopy_lookup_pid(struct rb_root *root, pid_t pid)
262 ++{
263 ++ struct rb_node *node = root->rb_node;
264 ++
265 ++ while (node) {
266 ++ struct kcopy_map_entry *kme =
267 ++ container_of(node, struct kcopy_map_entry, node);
268 ++
269 ++ if (pid < kme->pid)
270 ++ node = node->rb_left;
271 ++ else if (pid > kme->pid)
272 ++ node = node->rb_right;
273 ++ else
274 ++ return kme;
275 ++ }
276 ++
277 ++ return NULL;
278 ++}
279 ++
280 ++static int kcopy_insert(struct rb_root *root, struct kcopy_map_entry *kme)
281 ++{
282 ++ struct rb_node **new = &(root->rb_node);
283 ++ struct rb_node *parent = NULL;
284 ++
285 ++ while (*new) {
286 ++ struct kcopy_map_entry *tkme =
287 ++ container_of(*new, struct kcopy_map_entry, node);
288 ++
289 ++ parent = *new;
290 ++ if (kme->pid < tkme->pid)
291 ++ new = &((*new)->rb_left);
292 ++ else if (kme->pid > tkme->pid)
293 ++ new = &((*new)->rb_right);
294 ++ else {
295 ++ printk(KERN_INFO "!!! debugging: bad rb tree !!!\n");
296 ++ return -EINVAL;
297 ++ }
298 ++ }
299 ++
300 ++ rb_link_node(&kme->node, parent, new);
301 ++ rb_insert_color(&kme->node, root);
302 ++
303 ++ return 0;
304 ++}
305 ++
306 ++static int kcopy_open(struct inode *inode, struct file *filp)
307 ++{
308 ++ int ret;
309 ++ const int minor = iminor(inode);
310 ++ struct kcopy_file *kf = NULL;
311 ++ struct kcopy_map_entry *kme;
312 ++ struct kcopy_map_entry *okme;
313 ++
314 ++ if (minor < 0 || minor >= KCOPY_MAX_MINORS)
315 ++ return -ENODEV;
316 ++
317 ++ mutex_lock(&kcopy_dev.open_lock);
318 ++
319 ++ if (!kcopy_dev.kf[minor]) {
320 ++ kf = kmalloc(sizeof(struct kcopy_file), GFP_KERNEL);
321 ++
322 ++ if (!kf) {
323 ++ ret = -ENOMEM;
324 ++ goto bail;
325 ++ }
326 ++
327 ++ kf->count = 1;
328 ++ kf->live_map_tree = RB_ROOT;
329 ++ mutex_init(&kf->map_lock);
330 ++ kcopy_dev.kf[minor] = kf;
331 ++ } else {
332 ++ if (filp->f_flags & O_EXCL) {
333 ++ ret = -EBUSY;
334 ++ goto bail;
335 ++ }
336 ++ kcopy_dev.kf[minor]->count++;
337 ++ }
338 ++
339 ++ kme = kcopy_create_entry(kcopy_dev.kf[minor]);
340 ++ if (!kme) {
341 ++ ret = -ENOMEM;
342 ++ goto err_free_kf;
343 ++ }
344 ++
345 ++ kf = kcopy_dev.kf[minor];
346 ++
347 ++ mutex_lock(&kf->map_lock);
348 ++
349 ++ okme = kcopy_lookup_pid(&kf->live_map_tree, kme->pid);
350 ++ if (okme) {
351 ++ /* pid already exists... */
352 ++ okme->count++;
353 ++ kfree(kme);
354 ++ kme = okme;
355 ++ } else
356 ++ ret = kcopy_insert(&kf->live_map_tree, kme);
357 ++
358 ++ mutex_unlock(&kf->map_lock);
359 ++
360 ++ filp->private_data = kme;
361 ++
362 ++ ret = 0;
363 ++ goto bail;
364 ++
365 ++err_free_kf:
366 ++ if (kf) {
367 ++ kcopy_dev.kf[minor] = NULL;
368 ++ kfree(kf);
369 ++ }
370 ++bail:
371 ++ mutex_unlock(&kcopy_dev.open_lock);
372 ++ return ret;
373 ++}
374 ++
375 ++static int kcopy_flush(struct file *filp, fl_owner_t id)
376 ++{
377 ++ struct kcopy_map_entry *kme = filp->private_data;
378 ++ struct kcopy_file *kf = kme->file;
379 ++
380 ++ if (file_count(filp) == 1) {
381 ++ mutex_lock(&kf->map_lock);
382 ++ kme->count--;
383 ++
384 ++ if (!kme->count) {
385 ++ rb_erase(&kme->node, &kf->live_map_tree);
386 ++ kfree(kme);
387 ++ }
388 ++ mutex_unlock(&kf->map_lock);
389 ++ }
390 ++
391 ++ return 0;
392 ++}
393 ++
394 ++static int kcopy_release(struct inode *inode, struct file *filp)
395 ++{
396 ++ const int minor = iminor(inode);
397 ++
398 ++ mutex_lock(&kcopy_dev.open_lock);
399 ++ kcopy_dev.kf[minor]->count--;
400 ++ if (!kcopy_dev.kf[minor]->count) {
401 ++ kfree(kcopy_dev.kf[minor]);
402 ++ kcopy_dev.kf[minor] = NULL;
403 ++ }
404 ++ mutex_unlock(&kcopy_dev.open_lock);
405 ++
406 ++ return 0;
407 ++}
408 ++
409 ++static void kcopy_put_pages(struct page **pages, int npages)
410 ++{
411 ++ int j;
412 ++
413 ++ for (j = 0; j < npages; j++)
414 ++ put_page(pages[j]);
415 ++}
416 ++
417 ++static int kcopy_validate_task(struct task_struct *p)
418 ++{
419 ++ return p && (uid_eq(current_euid(), task_euid(p)) || uid_eq(current_euid(), task_uid(p)));
420 ++}
421 ++
422 ++static int kcopy_get_pages(struct kcopy_file *kf, pid_t pid,
423 ++ struct page **pages, void __user *addr,
424 ++ int write, size_t npages)
425 ++{
426 ++ int err;
427 ++ struct mm_struct *mm;
428 ++ struct kcopy_map_entry *rkme;
429 ++
430 ++ mutex_lock(&kf->map_lock);
431 ++
432 ++ rkme = kcopy_lookup_pid(&kf->live_map_tree, pid);
433 ++ if (!rkme || !kcopy_validate_task(rkme->task)) {
434 ++ err = -EINVAL;
435 ++ goto bail_unlock;
436 ++ }
437 ++
438 ++ mm = get_task_mm(rkme->task);
439 ++ if (unlikely(!mm)) {
440 ++ err = -ENOMEM;
441 ++ goto bail_unlock;
442 ++ }
443 ++
444 ++ down_read(&mm->mmap_sem);
445 ++ err = get_user_pages(rkme->task, mm,
446 ++ (unsigned long) addr, npages, write, 0,
447 ++ pages, NULL);
448 ++
449 ++ if (err < npages && err > 0) {
450 ++ kcopy_put_pages(pages, err);
451 ++ err = -ENOMEM;
452 ++ } else if (err == npages)
453 ++ err = 0;
454 ++
455 ++ up_read(&mm->mmap_sem);
456 ++
457 ++ mmput(mm);
458 ++
459 ++bail_unlock:
460 ++ mutex_unlock(&kf->map_lock);
461 ++
462 ++ return err;
463 ++}
464 ++
465 ++static unsigned long kcopy_copy_pages_from_user(void __user *src,
466 ++ struct page **dpages,
467 ++ unsigned doff,
468 ++ unsigned long n)
469 ++{
470 ++ struct page *dpage = *dpages;
471 ++ char *daddr = kmap(dpage);
472 ++ int ret = 0;
473 ++
474 ++ while (1) {
475 ++ const unsigned long nleft = PAGE_SIZE - doff;
476 ++ const unsigned long nc = (n < nleft) ? n : nleft;
477 ++
478 ++ /* if (copy_from_user(daddr + doff, src, nc)) { */
479 ++ if (__copy_from_user_nocache(daddr + doff, src, nc)) {
480 ++ ret = -EFAULT;
481 ++ goto bail;
482 ++ }
483 ++
484 ++ n -= nc;
485 ++ if (n == 0)
486 ++ break;
487 ++
488 ++ doff += nc;
489 ++ doff &= ~PAGE_MASK;
490 ++ if (doff == 0) {
491 ++ kunmap(dpage);
492 ++ dpages++;
493 ++ dpage = *dpages;
494 ++ daddr = kmap(dpage);
495 ++ }
496 ++
497 ++ src += nc;
498 ++ }
499 ++
500 ++bail:
501 ++ kunmap(dpage);
502 ++
503 ++ return ret;
504 ++}
505 ++
506 ++static unsigned long kcopy_copy_pages_to_user(void __user *dst,
507 ++ struct page **spages,
508 ++ unsigned soff,
509 ++ unsigned long n)
510 ++{
511 ++ struct page *spage = *spages;
512 ++ const char *saddr = kmap(spage);
513 ++ int ret = 0;
514 ++
515 ++ while (1) {
516 ++ const unsigned long nleft = PAGE_SIZE - soff;
517 ++ const unsigned long nc = (n < nleft) ? n : nleft;
518 ++
519 ++ if (copy_to_user(dst, saddr + soff, nc)) {
520 ++ ret = -EFAULT;
521 ++ goto bail;
522 ++ }
523 ++
524 ++ n -= nc;
525 ++ if (n == 0)
526 ++ break;
527 ++
528 ++ soff += nc;
529 ++ soff &= ~PAGE_MASK;
530 ++ if (soff == 0) {
531 ++ kunmap(spage);
532 ++ spages++;
533 ++ spage = *spages;
534 ++ saddr = kmap(spage);
535 ++ }
536 ++
537 ++ dst += nc;
538 ++ }
539 ++
540 ++bail:
541 ++ kunmap(spage);
542 ++
543 ++ return ret;
544 ++}
545 ++
546 ++static unsigned long kcopy_copy_to_user(void __user *dst,
547 ++ struct kcopy_file *kf, pid_t pid,
548 ++ void __user *src,
549 ++ unsigned long n)
550 ++{
551 ++ struct page **pages;
552 ++ const int pages_len = PAGE_SIZE / sizeof(struct page *);
553 ++ int ret = 0;
554 ++
555 ++ pages = (struct page **) __get_free_page(GFP_KERNEL);
556 ++ if (!pages) {
557 ++ ret = -ENOMEM;
558 ++ goto bail;
559 ++ }
560 ++
561 ++ while (n) {
562 ++ const unsigned long soff = (unsigned long) src & ~PAGE_MASK;
563 ++ const unsigned long spages_left =
564 ++ (soff + n + PAGE_SIZE - 1) >> PAGE_SHIFT;
565 ++ const unsigned long spages_cp =
566 ++ min_t(unsigned long, spages_left, pages_len);
567 ++ const unsigned long sbytes =
568 ++ PAGE_SIZE - soff + (spages_cp - 1) * PAGE_SIZE;
569 ++ const unsigned long nbytes = min_t(unsigned long, sbytes, n);
570 ++
571 ++ ret = kcopy_get_pages(kf, pid, pages, src, 0, spages_cp);
572 ++ if (unlikely(ret))
573 ++ goto bail_free;
574 ++
575 ++ ret = kcopy_copy_pages_to_user(dst, pages, soff, nbytes);
576 ++ kcopy_put_pages(pages, spages_cp);
577 ++ if (ret)
578 ++ goto bail_free;
579 ++ dst = (char *) dst + nbytes;
580 ++ src = (char *) src + nbytes;
581 ++
582 ++ n -= nbytes;
583 ++ }
584 ++
585 ++bail_free:
586 ++ free_page((unsigned long) pages);
587 ++bail:
588 ++ return ret;
589 ++}
590 ++
591 ++static unsigned long kcopy_copy_from_user(const void __user *src,
592 ++ struct kcopy_file *kf, pid_t pid,
593 ++ void __user *dst,
594 ++ unsigned long n)
595 ++{
596 ++ struct page **pages;
597 ++ const int pages_len = PAGE_SIZE / sizeof(struct page *);
598 ++ int ret = 0;
599 ++
600 ++ pages = (struct page **) __get_free_page(GFP_KERNEL);
601 ++ if (!pages) {
602 ++ ret = -ENOMEM;
603 ++ goto bail;
604 ++ }
605 ++
606 ++ while (n) {
607 ++ const unsigned long doff = (unsigned long) dst & ~PAGE_MASK;
608 ++ const unsigned long dpages_left =
609 ++ (doff + n + PAGE_SIZE - 1) >> PAGE_SHIFT;
610 ++ const unsigned long dpages_cp =
611 ++ min_t(unsigned long, dpages_left, pages_len);
612 ++ const unsigned long dbytes =
613 ++ PAGE_SIZE - doff + (dpages_cp - 1) * PAGE_SIZE;
614 ++ const unsigned long nbytes = min_t(unsigned long, dbytes, n);
615 ++
616 ++ ret = kcopy_get_pages(kf, pid, pages, dst, 1, dpages_cp);
617 ++ if (unlikely(ret))
618 ++ goto bail_free;
619 ++
620 ++ ret = kcopy_copy_pages_from_user((void __user *) src,
621 ++ pages, doff, nbytes);
622 ++ kcopy_put_pages(pages, dpages_cp);
623 ++ if (ret)
624 ++ goto bail_free;
625 ++
626 ++ dst = (char *) dst + nbytes;
627 ++ src = (char *) src + nbytes;
628 ++
629 ++ n -= nbytes;
630 ++ }
631 ++
632 ++bail_free:
633 ++ free_page((unsigned long) pages);
634 ++bail:
635 ++ return ret;
636 ++}
637 ++
638 ++static int kcopy_do_get(struct kcopy_map_entry *kme, pid_t pid,
639 ++ const void __user *src, void __user *dst,
640 ++ unsigned long n)
641 ++{
642 ++ struct kcopy_file *kf = kme->file;
643 ++ int ret = 0;
644 ++
645 ++ if (n == 0) {
646 ++ ret = -EINVAL;
647 ++ goto bail;
648 ++ }
649 ++
650 ++ ret = kcopy_copy_to_user(dst, kf, pid, (void __user *) src, n);
651 ++
652 ++bail:
653 ++ return ret;
654 ++}
655 ++
656 ++static int kcopy_do_put(struct kcopy_map_entry *kme, const void __user *src,
657 ++ pid_t pid, void __user *dst,
658 ++ unsigned long n)
659 ++{
660 ++ struct kcopy_file *kf = kme->file;
661 ++ int ret = 0;
662 ++
663 ++ if (n == 0) {
664 ++ ret = -EINVAL;
665 ++ goto bail;
666 ++ }
667 ++
668 ++ ret = kcopy_copy_from_user(src, kf, pid, (void __user *) dst, n);
669 ++
670 ++bail:
671 ++ return ret;
672 ++}
673 ++
674 ++static int kcopy_do_abi(u32 __user *dst)
675 ++{
676 ++ u32 val = KCOPY_ABI;
677 ++ int err;
678 ++
679 ++ err = put_user(val, dst);
680 ++ if (err)
681 ++ return -EFAULT;
682 ++
683 ++ return 0;
684 ++}
685 ++
686 ++ssize_t kcopy_write(struct file *filp, const char __user *data, size_t cnt,
687 ++ loff_t *o)
688 ++{
689 ++ struct kcopy_map_entry *kme = filp->private_data;
690 ++ struct kcopy_syscall ks;
691 ++ int err = 0;
692 ++ const void __user *src;
693 ++ void __user *dst;
694 ++ unsigned long n;
695 ++
696 ++ if (cnt != sizeof(struct kcopy_syscall)) {
697 ++ err = -EINVAL;
698 ++ goto bail;
699 ++ }
700 ++
701 ++ err = copy_from_user(&ks, data, cnt);
702 ++ if (unlikely(err))
703 ++ goto bail;
704 ++
705 ++ src = kcopy_syscall_src(&ks);
706 ++ dst = kcopy_syscall_dst(&ks);
707 ++ n = kcopy_syscall_n(&ks);
708 ++ if (ks.tag == KCOPY_GET_SYSCALL)
709 ++ err = kcopy_do_get(kme, ks.pid, src, dst, n);
710 ++ else if (ks.tag == KCOPY_PUT_SYSCALL)
711 ++ err = kcopy_do_put(kme, src, ks.pid, dst, n);
712 ++ else if (ks.tag == KCOPY_ABI_SYSCALL)
713 ++ err = kcopy_do_abi(dst);
714 ++ else
715 ++ err = -EINVAL;
716 ++
717 ++bail:
718 ++ return err ? err : cnt;
719 ++}
720 ++
721 ++static const struct file_operations kcopy_fops = {
722 ++ .owner = THIS_MODULE,
723 ++ .open = kcopy_open,
724 ++ .release = kcopy_release,
725 ++ .flush = kcopy_flush,
726 ++ .write = kcopy_write,
727 ++};
728 ++
729 ++static int __init kcopy_init(void)
730 ++{
731 ++ int ret;
732 ++ const char *name = "kcopy";
733 ++ int i;
734 ++ int ninit = 0;
735 ++
736 ++ mutex_init(&kcopy_dev.open_lock);
737 ++
738 ++ ret = alloc_chrdev_region(&kcopy_dev.dev, 0, KCOPY_MAX_MINORS, name);
739 ++ if (ret)
740 ++ goto bail;
741 ++
742 ++ kcopy_dev.class = class_create(THIS_MODULE, (char *) name);
743 ++
744 ++ if (IS_ERR(kcopy_dev.class)) {
745 ++ ret = PTR_ERR(kcopy_dev.class);
746 ++ printk(KERN_ERR "kcopy: Could not create "
747 ++ "device class (err %d)\n", -ret);
748 ++ goto bail_chrdev;
749 ++ }
750 ++
751 ++ cdev_init(&kcopy_dev.cdev, &kcopy_fops);
752 ++ ret = cdev_add(&kcopy_dev.cdev, kcopy_dev.dev, KCOPY_MAX_MINORS);
753 ++ if (ret < 0) {
754 ++ printk(KERN_ERR "kcopy: Could not add cdev (err %d)\n",
755 ++ -ret);
756 ++ goto bail_class;
757 ++ }
758 ++
759 ++ for (i = 0; i < KCOPY_MAX_MINORS; i++) {
760 ++ char devname[8];
761 ++ const int minor = MINOR(kcopy_dev.dev) + i;
762 ++ const dev_t dev = MKDEV(MAJOR(kcopy_dev.dev), minor);
763 ++
764 ++ snprintf(devname, sizeof(devname), "kcopy%02d", i);
765 ++ kcopy_dev.devp[i] =
766 ++ device_create(kcopy_dev.class, NULL,
767 ++ dev, NULL, devname);
768 ++
769 ++ if (IS_ERR(kcopy_dev.devp[i])) {
770 ++ ret = PTR_ERR(kcopy_dev.devp[i]);
771 ++ printk(KERN_ERR "kcopy: Could not create "
772 ++ "devp %d (err %d)\n", i, -ret);
773 ++ goto bail_cdev_add;
774 ++ }
775 ++
776 ++ ninit++;
777 ++ }
778 ++
779 ++ ret = 0;
780 ++ goto bail;
781 ++
782 ++bail_cdev_add:
783 ++ for (i = 0; i < ninit; i++)
784 ++ device_unregister(kcopy_dev.devp[i]);
785 ++
786 ++ cdev_del(&kcopy_dev.cdev);
787 ++bail_class:
788 ++ class_destroy(kcopy_dev.class);
789 ++bail_chrdev:
790 ++ unregister_chrdev_region(kcopy_dev.dev, KCOPY_MAX_MINORS);
791 ++bail:
792 ++ return ret;
793 ++}
794 ++
795 ++static void __exit kcopy_fini(void)
796 ++{
797 ++ int i;
798 ++
799 ++ for (i = 0; i < KCOPY_MAX_MINORS; i++)
800 ++ device_unregister(kcopy_dev.devp[i]);
801 ++
802 ++ cdev_del(&kcopy_dev.cdev);
803 ++ class_destroy(kcopy_dev.class);
804 ++ unregister_chrdev_region(kcopy_dev.dev, KCOPY_MAX_MINORS);
805 ++}
806 ++
807 ++module_init(kcopy_init);
808 ++module_exit(kcopy_fini);
809 +--
810 +1.7.10
811 +
812
813 Added: genpatches-2.6/trunk/3.9/2700_ThinkPad-30-brightness-control-fix.patch
814 ===================================================================
815 --- genpatches-2.6/trunk/3.9/2700_ThinkPad-30-brightness-control-fix.patch (rev 0)
816 +++ genpatches-2.6/trunk/3.9/2700_ThinkPad-30-brightness-control-fix.patch 2013-04-29 17:10:10 UTC (rev 2356)
817 @@ -0,0 +1,81 @@
818 +diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
819 +index cb96296..6c242ed 100644
820 +--- a/drivers/acpi/blacklist.c
821 ++++ b/drivers/acpi/blacklist.c
822 +@@ -193,6 +193,13 @@ static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
823 + return 0;
824 + }
825 +
826 ++static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
827 ++{
828 ++ printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
829 ++ acpi_osi_setup("!Windows 2012");
830 ++ return 0;
831 ++}
832 ++
833 + static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
834 + {
835 + .callback = dmi_disable_osi_vista,
836 +@@ -269,6 +276,61 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
837 + },
838 +
839 + /*
840 ++ * The following Lenovo models have a broken workaround in the
841 ++ * acpi_video backlight implementation to meet the Windows 8
842 ++ * requirement of 101 backlight levels. Reverting to pre-Win8
843 ++ * behavior fixes the problem.
844 ++ */
845 ++ {
846 ++ .callback = dmi_disable_osi_win8,
847 ++ .ident = "Lenovo ThinkPad L430",
848 ++ .matches = {
849 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
850 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L430"),
851 ++ },
852 ++ },
853 ++ {
854 ++ .callback = dmi_disable_osi_win8,
855 ++ .ident = "Lenovo ThinkPad T430s",
856 ++ .matches = {
857 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
858 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
859 ++ },
860 ++ },
861 ++ {
862 ++ .callback = dmi_disable_osi_win8,
863 ++ .ident = "Lenovo ThinkPad T530",
864 ++ .matches = {
865 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
866 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"),
867 ++ },
868 ++ },
869 ++ {
870 ++ .callback = dmi_disable_osi_win8,
871 ++ .ident = "Lenovo ThinkPad W530",
872 ++ .matches = {
873 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
874 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
875 ++ },
876 ++ },
877 ++ {
878 ++ .callback = dmi_disable_osi_win8,
879 ++ .ident = "Lenovo ThinkPad X1 Carbon",
880 ++ .matches = {
881 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
882 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
883 ++ },
884 ++ },
885 ++ {
886 ++ .callback = dmi_disable_osi_win8,
887 ++ .ident = "Lenovo ThinkPad X230",
888 ++ .matches = {
889 ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
890 ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
891 ++ },
892 ++ },
893 ++
894 ++ /*
895 + * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
896 + * Linux ignores it, except for the machines enumerated below.
897 + */
898 +
899
900 Added: genpatches-2.6/trunk/3.9/2900_dev-root-proc-mount-fix.patch
901 ===================================================================
902 --- genpatches-2.6/trunk/3.9/2900_dev-root-proc-mount-fix.patch (rev 0)
903 +++ genpatches-2.6/trunk/3.9/2900_dev-root-proc-mount-fix.patch 2013-04-29 17:10:10 UTC (rev 2356)
904 @@ -0,0 +1,29 @@
905 +--- a/init/do_mounts.c 2013-01-25 19:11:11.609802424 -0500
906 ++++ b/init/do_mounts.c 2013-01-25 19:14:20.606053568 -0500
907 +@@ -461,7 +461,10 @@ void __init change_floppy(char *fmt, ...
908 + va_start(args, fmt);
909 + vsprintf(buf, fmt, args);
910 + va_end(args);
911 +- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
912 ++ if (saved_root_name[0])
913 ++ fd = sys_open(saved_root_name, O_RDWR | O_NDELAY, 0);
914 ++ else
915 ++ fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
916 + if (fd >= 0) {
917 + sys_ioctl(fd, FDEJECT, 0);
918 + sys_close(fd);
919 +@@ -505,7 +508,13 @@ void __init mount_root(void)
920 + #endif
921 + #ifdef CONFIG_BLOCK
922 + create_dev("/dev/root", ROOT_DEV);
923 +- mount_block_root("/dev/root", root_mountflags);
924 ++ if (saved_root_name[0]) {
925 ++ create_dev(saved_root_name, ROOT_DEV);
926 ++ mount_block_root(saved_root_name, root_mountflags);
927 ++ } else {
928 ++ create_dev("/dev/root", ROOT_DEV);
929 ++ mount_block_root("/dev/root", root_mountflags);
930 ++ }
931 + #endif
932 + }
933 +