]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 25 Jul 2017 00:04:49 +0000 (17:04 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 25 Jul 2017 00:04:49 +0000 (17:04 -0700)
added patches:
hid-multitouch-do-not-blindly-set-ev_key-or-ev_abs-bits.patch
md-don-t-use-flush_signals-in-userspace-processes.patch
md-fix-deadlock-between-mddev_suspend-and-md_write_start.patch
mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch
pci-msi-ignore-affinity-if-pre-post-vector-count-is-more-than-min_vecs.patch
pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch
pci-rockchip-use-normal-register-bank-for-config-accessors.patch
pci-vmd-move-srcu-cleanup-after-bus-child-device-removal.patch
pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch
usb-cdc-acm-add-device-id-for-quirky-printer.patch
usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch
usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch
usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch
usb-xhci-fix-spinlock-recursion-for-usb2-test-mode.patch
xen-x86-fix-cpu-hotplug.patch
xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch
xhci-fix-20000ms-port-resume-timeout.patch
xhci-fix-memleak-in-xhci_run.patch
xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch

20 files changed:
queue-4.12/hid-multitouch-do-not-blindly-set-ev_key-or-ev_abs-bits.patch [new file with mode: 0644]
queue-4.12/md-don-t-use-flush_signals-in-userspace-processes.patch [new file with mode: 0644]
queue-4.12/md-fix-deadlock-between-mddev_suspend-and-md_write_start.patch [new file with mode: 0644]
queue-4.12/mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch [new file with mode: 0644]
queue-4.12/pci-msi-ignore-affinity-if-pre-post-vector-count-is-more-than-min_vecs.patch [new file with mode: 0644]
queue-4.12/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch [new file with mode: 0644]
queue-4.12/pci-rockchip-use-normal-register-bank-for-config-accessors.patch [new file with mode: 0644]
queue-4.12/pci-vmd-move-srcu-cleanup-after-bus-child-device-removal.patch [new file with mode: 0644]
queue-4.12/pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch [new file with mode: 0644]
queue-4.12/series
queue-4.12/usb-cdc-acm-add-device-id-for-quirky-printer.patch [new file with mode: 0644]
queue-4.12/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch [new file with mode: 0644]
queue-4.12/usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch [new file with mode: 0644]
queue-4.12/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch [new file with mode: 0644]
queue-4.12/usb-xhci-fix-spinlock-recursion-for-usb2-test-mode.patch [new file with mode: 0644]
queue-4.12/xen-x86-fix-cpu-hotplug.patch [new file with mode: 0644]
queue-4.12/xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch [new file with mode: 0644]
queue-4.12/xhci-fix-20000ms-port-resume-timeout.patch [new file with mode: 0644]
queue-4.12/xhci-fix-memleak-in-xhci_run.patch [new file with mode: 0644]
queue-4.12/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch [new file with mode: 0644]

diff --git a/queue-4.12/hid-multitouch-do-not-blindly-set-ev_key-or-ev_abs-bits.patch b/queue-4.12/hid-multitouch-do-not-blindly-set-ev_key-or-ev_abs-bits.patch
new file mode 100644 (file)
index 0000000..4c68cd1
--- /dev/null
@@ -0,0 +1,61 @@
+From 4cf56a89c696e66d10612b43b7e95852611e76c2 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Tue, 11 Jul 2017 10:02:18 -0700
+Subject: HID: multitouch: do not blindly set EV_KEY or EV_ABS bits
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 4cf56a89c696e66d10612b43b7e95852611e76c2 upstream.
+
+Now that input core insists on having dev->absinfo when device claims to
+generate EV_ABS in its dev->evbit, we should not be blindly setting that
+bit.
+
+The code in question might have been needed before input_set_abs_params()
+started setting EV_ABS in device's evbit, but not anymore, and is now
+breaking devices such as SMART SPNL-6075 Touchscreen.
+
+Fixes: 6ecfe51b4082 ("Input: refuse to register absolute devices ...")
+Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
+Tested-by: Matthias Fend <Matthias.Fend@wolfvision.net>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-multitouch.c |   16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -595,16 +595,6 @@ static int mt_touch_input_mapping(struct
+       return 0;
+ }
+-static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+-              struct hid_field *field, struct hid_usage *usage,
+-              unsigned long **bit, int *max)
+-{
+-      if (usage->type == EV_KEY || usage->type == EV_ABS)
+-              set_bit(usage->type, hi->input->evbit);
+-
+-      return -1;
+-}
+-
+ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
+ {
+       __s32 quirks = td->mtclass.quirks;
+@@ -905,8 +895,10 @@ static int mt_input_mapped(struct hid_de
+               return 0;
+       if (field->application == HID_DG_TOUCHSCREEN ||
+-          field->application == HID_DG_TOUCHPAD)
+-              return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
++          field->application == HID_DG_TOUCHPAD) {
++              /* We own these mappings, tell hid-input to ignore them */
++              return -1;
++      }
+       /* let hid-core decide for the others */
+       return 0;
diff --git a/queue-4.12/md-don-t-use-flush_signals-in-userspace-processes.patch b/queue-4.12/md-don-t-use-flush_signals-in-userspace-processes.patch
new file mode 100644 (file)
index 0000000..184d855
--- /dev/null
@@ -0,0 +1,72 @@
+From f9c79bc05a2a91f4fba8bfd653579e066714b1ec Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 7 Jun 2017 19:05:31 -0400
+Subject: md: don't use flush_signals in userspace processes
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit f9c79bc05a2a91f4fba8bfd653579e066714b1ec upstream.
+
+The function flush_signals clears all pending signals for the process. It
+may be used by kernel threads when we need to prepare a kernel thread for
+responding to signals. However using this function for an userspaces
+processes is incorrect - clearing signals without the program expecting it
+can cause misbehavior.
+
+The raid1 and raid5 code uses flush_signals in its request routine because
+it wants to prepare for an interruptible wait. This patch drops
+flush_signals and uses sigprocmask instead to block all signals (including
+SIGKILL) around the schedule() call. The signals are not lost, but the
+schedule() call won't respond to them.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Shaohua Li <shli@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/raid1.c |    5 ++++-
+ drivers/md/raid5.c |    5 ++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1335,7 +1335,7 @@ static void raid1_write_request(struct m
+                */
+               DEFINE_WAIT(w);
+               for (;;) {
+-                      flush_signals(current);
++                      sigset_t full, old;
+                       prepare_to_wait(&conf->wait_barrier,
+                                       &w, TASK_INTERRUPTIBLE);
+                       if (bio_end_sector(bio) <= mddev->suspend_lo ||
+@@ -1345,7 +1345,10 @@ static void raid1_write_request(struct m
+                                    bio->bi_iter.bi_sector,
+                                    bio_end_sector(bio))))
+                               break;
++                      sigfillset(&full);
++                      sigprocmask(SIG_BLOCK, &full, &old);
+                       schedule();
++                      sigprocmask(SIG_SETMASK, &old, NULL);
+               }
+               finish_wait(&conf->wait_barrier, &w);
+       }
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -5693,12 +5693,15 @@ static void raid5_make_request(struct md
+                                * userspace, we want an interruptible
+                                * wait.
+                                */
+-                              flush_signals(current);
+                               prepare_to_wait(&conf->wait_for_overlap,
+                                               &w, TASK_INTERRUPTIBLE);
+                               if (logical_sector >= mddev->suspend_lo &&
+                                   logical_sector < mddev->suspend_hi) {
++                                      sigset_t full, old;
++                                      sigfillset(&full);
++                                      sigprocmask(SIG_BLOCK, &full, &old);
+                                       schedule();
++                                      sigprocmask(SIG_SETMASK, &old, NULL);
+                                       do_prepare = true;
+                               }
+                               goto retry;
diff --git a/queue-4.12/md-fix-deadlock-between-mddev_suspend-and-md_write_start.patch b/queue-4.12/md-fix-deadlock-between-mddev_suspend-and-md_write_start.patch
new file mode 100644 (file)
index 0000000..8ce32ab
--- /dev/null
@@ -0,0 +1,420 @@
+From cc27b0c78c79680d128dbac79de0d40556d041bb Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.com>
+Date: Mon, 5 Jun 2017 16:49:39 +1000
+Subject: md: fix deadlock between mddev_suspend() and md_write_start()
+
+From: NeilBrown <neilb@suse.com>
+
+commit cc27b0c78c79680d128dbac79de0d40556d041bb upstream.
+
+If mddev_suspend() races with md_write_start() we can deadlock
+with mddev_suspend() waiting for the request that is currently
+in md_write_start() to complete the ->make_request() call,
+and md_write_start() waiting for the metadata to be updated
+to mark the array as 'dirty'.
+As metadata updates done by md_check_recovery() only happen then
+the mddev_lock() can be claimed, and as mddev_suspend() is often
+called with the lock held, these threads wait indefinitely for each
+other.
+
+We fix this by having md_write_start() abort if mddev_suspend()
+is happening, and ->make_request() aborts if md_write_start()
+aborted.
+md_make_request() can detect this abort, decrease the ->active_io
+count, and wait for mddev_suspend().
+
+Reported-by: Nix <nix@esperi.org.uk>
+Fix: 68866e425be2(MD: no sync IO while suspended)
+Signed-off-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Shaohua Li <shli@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/faulty.c    |    5 +++--
+ drivers/md/linear.c    |    7 ++++---
+ drivers/md/md.c        |   22 +++++++++++++++++-----
+ drivers/md/md.h        |    4 ++--
+ drivers/md/multipath.c |    8 ++++----
+ drivers/md/raid0.c     |    7 ++++---
+ drivers/md/raid1.c     |   11 +++++++----
+ drivers/md/raid10.c    |   10 ++++++----
+ drivers/md/raid5.c     |   17 +++++++++--------
+ 9 files changed, 56 insertions(+), 35 deletions(-)
+
+--- a/drivers/md/faulty.c
++++ b/drivers/md/faulty.c
+@@ -170,7 +170,7 @@ static void add_sector(struct faulty_con
+               conf->nfaults = n+1;
+ }
+-static void faulty_make_request(struct mddev *mddev, struct bio *bio)
++static bool faulty_make_request(struct mddev *mddev, struct bio *bio)
+ {
+       struct faulty_conf *conf = mddev->private;
+       int failit = 0;
+@@ -182,7 +182,7 @@ static void faulty_make_request(struct m
+                        * just fail immediately
+                        */
+                       bio_io_error(bio);
+-                      return;
++                      return true;
+               }
+               if (check_sector(conf, bio->bi_iter.bi_sector,
+@@ -224,6 +224,7 @@ static void faulty_make_request(struct m
+               bio->bi_bdev = conf->rdev->bdev;
+       generic_make_request(bio);
++      return true;
+ }
+ static void faulty_status(struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/linear.c
++++ b/drivers/md/linear.c
+@@ -245,7 +245,7 @@ static void linear_free(struct mddev *md
+       kfree(conf);
+ }
+-static void linear_make_request(struct mddev *mddev, struct bio *bio)
++static bool linear_make_request(struct mddev *mddev, struct bio *bio)
+ {
+       char b[BDEVNAME_SIZE];
+       struct dev_info *tmp_dev;
+@@ -254,7 +254,7 @@ static void linear_make_request(struct m
+       if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+               md_flush_request(mddev, bio);
+-              return;
++              return true;
+       }
+       tmp_dev = which_dev(mddev, bio_sector);
+@@ -292,7 +292,7 @@ static void linear_make_request(struct m
+               mddev_check_write_zeroes(mddev, bio);
+               generic_make_request(bio);
+       }
+-      return;
++      return true;
+ out_of_bounds:
+       pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %s: %llu sectors, offset %llu\n",
+@@ -302,6 +302,7 @@ out_of_bounds:
+              (unsigned long long)tmp_dev->rdev->sectors,
+              (unsigned long long)start_sector);
+       bio_io_error(bio);
++      return true;
+ }
+ static void linear_status (struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -277,7 +277,7 @@ static blk_qc_t md_make_request(struct r
+               bio_endio(bio);
+               return BLK_QC_T_NONE;
+       }
+-      smp_rmb(); /* Ensure implications of  'active' are visible */
++check_suspended:
+       rcu_read_lock();
+       if (mddev->suspended) {
+               DEFINE_WAIT(__wait);
+@@ -302,7 +302,11 @@ static blk_qc_t md_make_request(struct r
+       sectors = bio_sectors(bio);
+       /* bio could be mergeable after passing to underlayer */
+       bio->bi_opf &= ~REQ_NOMERGE;
+-      mddev->pers->make_request(mddev, bio);
++      if (!mddev->pers->make_request(mddev, bio)) {
++              atomic_dec(&mddev->active_io);
++              wake_up(&mddev->sb_wait);
++              goto check_suspended;
++      }
+       cpu = part_stat_lock();
+       part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+@@ -327,6 +331,7 @@ void mddev_suspend(struct mddev *mddev)
+       if (mddev->suspended++)
+               return;
+       synchronize_rcu();
++      wake_up(&mddev->sb_wait);
+       wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
+       mddev->pers->quiesce(mddev, 1);
+@@ -7950,12 +7955,14 @@ EXPORT_SYMBOL(md_done_sync);
+  * If we need to update some array metadata (e.g. 'active' flag
+  * in superblock) before writing, schedule a superblock update
+  * and wait for it to complete.
++ * A return value of 'false' means that the write wasn't recorded
++ * and cannot proceed as the array is being suspend.
+  */
+-void md_write_start(struct mddev *mddev, struct bio *bi)
++bool md_write_start(struct mddev *mddev, struct bio *bi)
+ {
+       int did_change = 0;
+       if (bio_data_dir(bi) != WRITE)
+-              return;
++              return true;
+       BUG_ON(mddev->ro == 1);
+       if (mddev->ro == 2) {
+@@ -7987,7 +7994,12 @@ void md_write_start(struct mddev *mddev,
+       if (did_change)
+               sysfs_notify_dirent_safe(mddev->sysfs_state);
+       wait_event(mddev->sb_wait,
+-                 !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
++                 !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) && !mddev->suspended);
++      if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
++              percpu_ref_put(&mddev->writes_pending);
++              return false;
++      }
++      return true;
+ }
+ EXPORT_SYMBOL(md_write_start);
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -510,7 +510,7 @@ struct md_personality
+       int level;
+       struct list_head list;
+       struct module *owner;
+-      void (*make_request)(struct mddev *mddev, struct bio *bio);
++      bool (*make_request)(struct mddev *mddev, struct bio *bio);
+       int (*run)(struct mddev *mddev);
+       void (*free)(struct mddev *mddev, void *priv);
+       void (*status)(struct seq_file *seq, struct mddev *mddev);
+@@ -649,7 +649,7 @@ extern void md_wakeup_thread(struct md_t
+ extern void md_check_recovery(struct mddev *mddev);
+ extern void md_reap_sync_thread(struct mddev *mddev);
+ extern int mddev_init_writes_pending(struct mddev *mddev);
+-extern void md_write_start(struct mddev *mddev, struct bio *bi);
++extern bool md_write_start(struct mddev *mddev, struct bio *bi);
+ extern void md_write_inc(struct mddev *mddev, struct bio *bi);
+ extern void md_write_end(struct mddev *mddev);
+ extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -106,7 +106,7 @@ static void multipath_end_request(struct
+       rdev_dec_pending(rdev, conf->mddev);
+ }
+-static void multipath_make_request(struct mddev *mddev, struct bio * bio)
++static bool multipath_make_request(struct mddev *mddev, struct bio * bio)
+ {
+       struct mpconf *conf = mddev->private;
+       struct multipath_bh * mp_bh;
+@@ -114,7 +114,7 @@ static void multipath_make_request(struc
+       if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+               md_flush_request(mddev, bio);
+-              return;
++              return true;
+       }
+       mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
+@@ -126,7 +126,7 @@ static void multipath_make_request(struc
+       if (mp_bh->path < 0) {
+               bio_io_error(bio);
+               mempool_free(mp_bh, conf->pool);
+-              return;
++              return true;
+       }
+       multipath = conf->multipaths + mp_bh->path;
+@@ -141,7 +141,7 @@ static void multipath_make_request(struc
+       mddev_check_writesame(mddev, &mp_bh->bio);
+       mddev_check_write_zeroes(mddev, &mp_bh->bio);
+       generic_make_request(&mp_bh->bio);
+-      return;
++      return true;
+ }
+ static void multipath_status(struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/raid0.c
++++ b/drivers/md/raid0.c
+@@ -548,7 +548,7 @@ static void raid0_handle_discard(struct
+       bio_endio(bio);
+ }
+-static void raid0_make_request(struct mddev *mddev, struct bio *bio)
++static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
+ {
+       struct strip_zone *zone;
+       struct md_rdev *tmp_dev;
+@@ -559,12 +559,12 @@ static void raid0_make_request(struct md
+       if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+               md_flush_request(mddev, bio);
+-              return;
++              return true;
+       }
+       if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
+               raid0_handle_discard(mddev, bio);
+-              return;
++              return true;
+       }
+       bio_sector = bio->bi_iter.bi_sector;
+@@ -599,6 +599,7 @@ static void raid0_make_request(struct md
+       mddev_check_writesame(mddev, bio);
+       mddev_check_write_zeroes(mddev, bio);
+       generic_make_request(bio);
++      return true;
+ }
+ static void raid0_status(struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1321,7 +1321,6 @@ static void raid1_write_request(struct m
+        * Continue immediately if no resync is active currently.
+        */
+-      md_write_start(mddev, bio); /* wait on superblock update early */
+       if ((bio_end_sector(bio) > mddev->suspend_lo &&
+           bio->bi_iter.bi_sector < mddev->suspend_hi) ||
+@@ -1553,13 +1552,13 @@ static void raid1_write_request(struct m
+       wake_up(&conf->wait_barrier);
+ }
+-static void raid1_make_request(struct mddev *mddev, struct bio *bio)
++static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
+ {
+       sector_t sectors;
+       if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+               md_flush_request(mddev, bio);
+-              return;
++              return true;
+       }
+       /*
+@@ -1574,8 +1573,12 @@ static void raid1_make_request(struct md
+       if (bio_data_dir(bio) == READ)
+               raid1_read_request(mddev, bio, sectors, NULL);
+-      else
++      else {
++              if (!md_write_start(mddev,bio))
++                      return false;
+               raid1_write_request(mddev, bio, sectors);
++      }
++      return true;
+ }
+ static void raid1_status(struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1303,8 +1303,6 @@ static void raid10_write_request(struct
+       sector_t sectors;
+       int max_sectors;
+-      md_write_start(mddev, bio);
+-
+       /*
+        * Register the new request and wait if the reconstruction
+        * thread has put up a bar for new requests.
+@@ -1525,7 +1523,7 @@ static void __make_request(struct mddev
+               raid10_write_request(mddev, bio, r10_bio);
+ }
+-static void raid10_make_request(struct mddev *mddev, struct bio *bio)
++static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
+ {
+       struct r10conf *conf = mddev->private;
+       sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask);
+@@ -1534,9 +1532,12 @@ static void raid10_make_request(struct m
+       if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+               md_flush_request(mddev, bio);
+-              return;
++              return true;
+       }
++      if (!md_write_start(mddev, bio))
++              return false;
++
+       /*
+        * If this request crosses a chunk boundary, we need to split
+        * it.
+@@ -1553,6 +1554,7 @@ static void raid10_make_request(struct m
+       /* In case raid10d snuck in to freeze_array */
+       wake_up(&conf->wait_barrier);
++      return true;
+ }
+ static void raid10_status(struct seq_file *seq, struct mddev *mddev)
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -5479,7 +5479,6 @@ static void make_discard_request(struct
+       last_sector = bi->bi_iter.bi_sector + (bi->bi_iter.bi_size>>9);
+       bi->bi_next = NULL;
+-      md_write_start(mddev, bi);
+       stripe_sectors = conf->chunk_sectors *
+               (conf->raid_disks - conf->max_degraded);
+@@ -5549,11 +5548,10 @@ static void make_discard_request(struct
+               release_stripe_plug(mddev, sh);
+       }
+-      md_write_end(mddev);
+       bio_endio(bi);
+ }
+-static void raid5_make_request(struct mddev *mddev, struct bio * bi)
++static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
+ {
+       struct r5conf *conf = mddev->private;
+       int dd_idx;
+@@ -5569,10 +5567,10 @@ static void raid5_make_request(struct md
+               int ret = r5l_handle_flush_request(conf->log, bi);
+               if (ret == 0)
+-                      return;
++                      return true;
+               if (ret == -ENODEV) {
+                       md_flush_request(mddev, bi);
+-                      return;
++                      return true;
+               }
+               /* ret == -EAGAIN, fallback */
+               /*
+@@ -5582,6 +5580,8 @@ static void raid5_make_request(struct md
+               do_flush = bi->bi_opf & REQ_PREFLUSH;
+       }
++      if (!md_write_start(mddev, bi))
++              return false;
+       /*
+        * If array is degraded, better not do chunk aligned read because
+        * later we might have to read it again in order to reconstruct
+@@ -5591,18 +5591,18 @@ static void raid5_make_request(struct md
+           mddev->reshape_position == MaxSector) {
+               bi = chunk_aligned_read(mddev, bi);
+               if (!bi)
+-                      return;
++                      return true;
+       }
+       if (unlikely(bio_op(bi) == REQ_OP_DISCARD)) {
+               make_discard_request(mddev, bi);
+-              return;
++              md_write_end(mddev);
++              return true;
+       }
+       logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+       last_sector = bio_end_sector(bi);
+       bi->bi_next = NULL;
+-      md_write_start(mddev, bi);
+       prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
+       for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+@@ -5743,6 +5743,7 @@ static void raid5_make_request(struct md
+       if (rw == WRITE)
+               md_write_end(mddev);
+       bio_endio(bi);
++      return true;
+ }
+ static sector_t raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks);
diff --git a/queue-4.12/mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch b/queue-4.12/mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch
new file mode 100644 (file)
index 0000000..d8707e3
--- /dev/null
@@ -0,0 +1,167 @@
+From d90b336f3f652ff0441e631a06236f785581c8f7 Mon Sep 17 00:00:00 2001
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+Date: Fri, 21 Apr 2017 13:28:37 -0300
+Subject: [media] mxl111sf: Fix driver to use heap allocate buffers for USB messages
+
+From: Devin Heitmueller <dheitmueller@kernellabs.com>
+
+commit d90b336f3f652ff0441e631a06236f785581c8f7 upstream.
+
+The recent changes in 4.9 to mandate USB buffers be heap allocated
+broke this driver, which was allocating the buffers on the stack.
+This resulted in the device failing at initialization.
+
+Introduce dedicated send/receive buffers as part of the state
+structure, and add a mutex to protect access to them.
+
+Note: we also had to tweak the API to mxl111sf_ctrl_msg to pass
+the pointer to the state struct rather than the device, since
+we need it inside the function to access the buffers and the
+mutex.  This patch adjusts the callers to match the API change.
+
+Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
+Reported-by: Doug Lung <dlung0@gmail.com>
+Cc: Michael Ira Krufky <mkrufky@linuxtv.org>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c |    4 +--
+ drivers/media/usb/dvb-usb-v2/mxl111sf.c     |   32 ++++++++++++++++------------
+ drivers/media/usb/dvb-usb-v2/mxl111sf.h     |    8 ++++++-
+ 3 files changed, 28 insertions(+), 16 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
+@@ -316,7 +316,7 @@ fail:
+ static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
+                                 u8 index, u8 *wdata)
+ {
+-      int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
++      int ret = mxl111sf_ctrl_msg(state, wdata[0],
+                                   &wdata[1], 25, NULL, 0);
+       mxl_fail(ret);
+@@ -326,7 +326,7 @@ static int mxl111sf_i2c_send_data(struct
+ static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
+                                u8 index, u8 *wdata, u8 *rdata)
+ {
+-      int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
++      int ret = mxl111sf_ctrl_msg(state, wdata[0],
+                                   &wdata[1], 25, rdata, 24);
+       mxl_fail(ret);
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+@@ -24,9 +24,6 @@
+ #include "lgdt3305.h"
+ #include "lg2160.h"
+-/* Max transfer size done by I2C transfer functions */
+-#define MAX_XFER_SIZE  64
+-
+ int dvb_usb_mxl111sf_debug;
+ module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
+@@ -55,27 +52,34 @@ MODULE_PARM_DESC(rfswitch, "force rf swi
+ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
++int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
+                     u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+ {
++      struct dvb_usb_device *d = state->d;
+       int wo = (rbuf == NULL || rlen == 0); /* write-only */
+       int ret;
+-      u8 sndbuf[MAX_XFER_SIZE];
+-      if (1 + wlen > sizeof(sndbuf)) {
++      if (1 + wlen > MXL_MAX_XFER_SIZE) {
+               pr_warn("%s: len=%d is too big!\n", __func__, wlen);
+               return -EOPNOTSUPP;
+       }
+       pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+-      memset(sndbuf, 0, 1+wlen);
++      mutex_lock(&state->msg_lock);
++      memset(state->sndbuf, 0, 1+wlen);
++      memset(state->rcvbuf, 0, rlen);
++
++      state->sndbuf[0] = cmd;
++      memcpy(&state->sndbuf[1], wbuf, wlen);
++
++      ret = (wo) ? dvb_usbv2_generic_write(d, state->sndbuf, 1+wlen) :
++              dvb_usbv2_generic_rw(d, state->sndbuf, 1+wlen, state->rcvbuf,
++                                   rlen);
+-      sndbuf[0] = cmd;
+-      memcpy(&sndbuf[1], wbuf, wlen);
++      memcpy(rbuf, state->rcvbuf, rlen);
++      mutex_unlock(&state->msg_lock);
+-      ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) :
+-              dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen);
+       mxl_fail(ret);
+       return ret;
+@@ -91,7 +95,7 @@ int mxl111sf_read_reg(struct mxl111sf_st
+       u8 buf[2];
+       int ret;
+-      ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
++      ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+       if (mxl_fail(ret)) {
+               mxl_debug("error reading reg: 0x%02x", addr);
+               goto fail;
+@@ -117,7 +121,7 @@ int mxl111sf_write_reg(struct mxl111sf_s
+       pr_debug("W: (0x%02x, 0x%02x)\n", addr, data);
+-      ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
++      ret = mxl111sf_ctrl_msg(state, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+       if (mxl_fail(ret))
+               pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+       return ret;
+@@ -926,6 +930,8 @@ static int mxl111sf_init(struct dvb_usb_
+                 .len = sizeof(eeprom), .buf = eeprom },
+       };
++      mutex_init(&state->msg_lock);
++
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               pr_err("failed to get chip info during probe");
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+@@ -19,6 +19,9 @@
+ #include <media/tveeprom.h>
+ #include <media/media-entity.h>
++/* Max transfer size done by I2C transfer functions */
++#define MXL_MAX_XFER_SIZE  64
++
+ #define MXL_EP1_REG_READ     1
+ #define MXL_EP2_REG_WRITE    2
+ #define MXL_EP3_INTERRUPT    3
+@@ -86,6 +89,9 @@ struct mxl111sf_state {
+       struct mutex fe_lock;
+       u8 num_frontends;
+       struct mxl111sf_adap_state adap_state[3];
++      u8 sndbuf[MXL_MAX_XFER_SIZE];
++      u8 rcvbuf[MXL_MAX_XFER_SIZE];
++      struct mutex msg_lock;
+ #ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       struct media_entity tuner;
+       struct media_pad tuner_pads[2];
+@@ -108,7 +114,7 @@ int mxl111sf_ctrl_program_regs(struct mx
+ /* needed for hardware i2c functions in mxl111sf-i2c.c:
+  * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
+-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
++int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
+                     u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
+ #define mxl_printk(kern, fmt, arg...) \
diff --git a/queue-4.12/pci-msi-ignore-affinity-if-pre-post-vector-count-is-more-than-min_vecs.patch b/queue-4.12/pci-msi-ignore-affinity-if-pre-post-vector-count-is-more-than-min_vecs.patch
new file mode 100644 (file)
index 0000000..5ffd646
--- /dev/null
@@ -0,0 +1,123 @@
+From 6f9a22bc5775d231ab8fbe2c2f3c88e45e3e7c28 Mon Sep 17 00:00:00 2001
+From: Michael Hernandez <michael.hernandez@cavium.com>
+Date: Thu, 18 May 2017 10:47:47 -0700
+Subject: PCI/MSI: Ignore affinity if pre/post vector count is more than min_vecs
+
+From: Michael Hernandez <michael.hernandez@cavium.com>
+
+commit 6f9a22bc5775d231ab8fbe2c2f3c88e45e3e7c28 upstream.
+
+min_vecs is the minimum amount of vectors needed to operate in MSI-X mode
+which may just include the vectors that don't need affinity.
+
+Disabling affinity settings causes the qla2xxx driver scsi_add_host() to fail
+when blk_mq is enabled as the blk_mq_pci_map_queues() expects affinity masks
+on each vector.
+
+Fixes: dfef358bd1be ("PCI/MSI: Don't apply affinity if there aren't enough vectors left")
+Signed-off-by: Michael Hernandez <michael.hernandez@cavium.com>
+Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/msi.c         |   14 ++------------
+ include/linux/interrupt.h |    4 ++--
+ kernel/irq/affinity.c     |   13 ++++++++++++-
+ 3 files changed, 16 insertions(+), 15 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -1058,7 +1058,7 @@ static int __pci_enable_msi_range(struct
+       for (;;) {
+               if (affd) {
+-                      nvec = irq_calc_affinity_vectors(nvec, affd);
++                      nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
+                       if (nvec < minvec)
+                               return -ENOSPC;
+               }
+@@ -1097,7 +1097,7 @@ static int __pci_enable_msix_range(struc
+       for (;;) {
+               if (affd) {
+-                      nvec = irq_calc_affinity_vectors(nvec, affd);
++                      nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
+                       if (nvec < minvec)
+                               return -ENOSPC;
+               }
+@@ -1165,16 +1165,6 @@ int pci_alloc_irq_vectors_affinity(struc
+       if (flags & PCI_IRQ_AFFINITY) {
+               if (!affd)
+                       affd = &msi_default_affd;
+-
+-              if (affd->pre_vectors + affd->post_vectors > min_vecs)
+-                      return -EINVAL;
+-
+-              /*
+-               * If there aren't any vectors left after applying the pre/post
+-               * vectors don't bother with assigning affinity.
+-               */
+-              if (affd->pre_vectors + affd->post_vectors == min_vecs)
+-                      affd = NULL;
+       } else {
+               if (WARN_ON(affd))
+                       affd = NULL;
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -291,7 +291,7 @@ extern int
+ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
+ struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
+-int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd);
++int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd);
+ #else /* CONFIG_SMP */
+@@ -331,7 +331,7 @@ irq_create_affinity_masks(int nvec, cons
+ }
+ static inline int
+-irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
++irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd)
+ {
+       return maxvec;
+ }
+--- a/kernel/irq/affinity.c
++++ b/kernel/irq/affinity.c
+@@ -66,6 +66,13 @@ irq_create_affinity_masks(int nvecs, con
+       struct cpumask *masks;
+       cpumask_var_t nmsk;
++      /*
++       * If there aren't any vectors left after applying the pre/post
++       * vectors don't bother with assigning affinity.
++       */
++      if (!affv)
++              return NULL;
++
+       if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
+               return NULL;
+@@ -140,15 +147,19 @@ out:
+ /**
+  * irq_calc_affinity_vectors - Calculate the optimal number of vectors
++ * @minvec:   The minimum number of vectors available
+  * @maxvec:   The maximum number of vectors available
+  * @affd:     Description of the affinity requirements
+  */
+-int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
++int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd)
+ {
+       int resv = affd->pre_vectors + affd->post_vectors;
+       int vecs = maxvec - resv;
+       int cpus;
++      if (resv > minvec)
++              return 0;
++
+       /* Stabilize the cpumasks */
+       get_online_cpus();
+       cpus = cpumask_weight(cpu_online_mask);
diff --git a/queue-4.12/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch b/queue-4.12/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch
new file mode 100644 (file)
index 0000000..6e0054f
--- /dev/null
@@ -0,0 +1,93 @@
+From e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 Mon Sep 17 00:00:00 2001
+From: Chen Yu <yu.c.chen@intel.com>
+Date: Thu, 25 May 2017 16:49:07 +0800
+Subject: PCI/PM: Restore the status of PCI devices across hibernation
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+commit e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 upstream.
+
+Currently we saw a lot of "No irq handler" errors during hibernation, which
+caused the system hang finally:
+
+  ata4.00: qc timeout (cmd 0xec)
+  ata4.00: failed to IDENTIFY (I/O error, err_mask=0x4)
+  ata4.00: revalidation failed (errno=-5)
+  ata4: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
+  do_IRQ: 31.151 No irq handler for vector
+
+According to above logs, there is an interrupt triggered and it is
+dispatched to CPU31 with a vector number 151, but there is no handler for
+it, thus this IRQ will not get acked and will cause an IRQ flood which
+kills the system.  To be more specific, the 31.151 is an interrupt from the
+AHCI host controller.
+
+After some investigation, the reason why this issue is triggered is because
+the thaw_noirq() function does not restore the MSI/MSI-X settings across
+hibernation.
+
+The scenario is illustrated below:
+
+  1. Before hibernation, IRQ 34 is the handler for the AHCI device, which
+     is bound to CPU31.
+
+  2. Hibernation starts, the AHCI device is put into low power state.
+
+  3. All the nonboot CPUs are put offline, so IRQ 34 has to be migrated to
+     the last alive one - CPU0.
+
+  4. After the snapshot has been created, all the nonboot CPUs are brought
+     up again; IRQ 34 remains bound to CPU0.
+
+  5. AHCI devices are put into D0.
+
+  6. The snapshot is written to the disk.
+
+The issue is triggered in step 6.  The AHCI interrupt should be delivered
+to CPU0, however it is delivered to the original CPU31 instead, which
+causes the "No irq handler" issue.
+
+Ying Huang has provided a clue that, in step 3 it is possible that writing
+to the register might not take effect as the PCI devices have been
+suspended.
+
+In step 3, the IRQ 34 affinity should be modified from CPU31 to CPU0, but
+in fact it is not.  In __pci_write_msi_msg(), if the device is already in
+low power state, the low level MSI message entry will not be updated but
+cached.  During the device restore process after a normal suspend/resume,
+pci_restore_msi_state() writes the cached MSI back to the hardware.
+
+But this is not the case for hibernation.  pci_restore_msi_state() is not
+currently called in pci_pm_thaw_noirq(), although pci_save_state() has
+saved the necessary PCI cached information in pci_pm_freeze_noirq().
+
+Restore the PCI status for the device during hibernation.  Otherwise the
+status might be lost across hibernation (for example, settings for MSI,
+MSI-X, ATS, ACS, IOV, etc.), which might cause problems during hibernation.
+
+Suggested-by: Ying Huang <ying.huang@intel.com>
+Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+[bhelgaas: changelog]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Len Brown <len.brown@intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Rui Zhang <rui.zhang@intel.com>
+Cc: Ying Huang <ying.huang@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-driver.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -964,6 +964,7 @@ static int pci_pm_thaw_noirq(struct devi
+               return pci_legacy_resume_early(dev);
+       pci_update_current_state(pci_dev, PCI_D0);
++      pci_restore_state(pci_dev);
+       if (drv && drv->pm && drv->pm->thaw_noirq)
+               error = drv->pm->thaw_noirq(dev);
diff --git a/queue-4.12/pci-rockchip-use-normal-register-bank-for-config-accessors.patch b/queue-4.12/pci-rockchip-use-normal-register-bank-for-config-accessors.patch
new file mode 100644 (file)
index 0000000..12a2b46
--- /dev/null
@@ -0,0 +1,87 @@
+From dc8cca5ef25ac4cb0dfc37467521a759767ff361 Mon Sep 17 00:00:00 2001
+From: Shawn Lin <shawn.lin@rock-chips.com>
+Date: Mon, 3 Jul 2017 17:21:02 +0800
+Subject: PCI: rockchip: Use normal register bank for config accessors
+
+From: Shawn Lin <shawn.lin@rock-chips.com>
+
+commit dc8cca5ef25ac4cb0dfc37467521a759767ff361 upstream.
+
+Rockchip's RC has two banks of registers for the root port: a normal bank
+that is strictly compatible with the PCIe spec, and a privileged bank that
+can be used to change RO bits of root port registers.
+
+When probing the RC driver, we use the privileged bank to do some basic
+setup work as some RO bits are hw-inited to wrong value.  But we didn't
+change to the normal bank after probing the driver.
+
+This leads to a serious problem when the PME code tries to clear the PME
+status by writing PCI_EXP_RTSTA_PME to the register of PCI_EXP_RTSTA.  Per
+PCIe 3.0 spec, section 7.8.14, the PME status bit is RW1C.  So the PME code
+is doing the right thing to clear the PME status but we find the RC doesn't
+clear it but actually setting it to one.  So finally the system trap in
+pcie_pme_work_fn() as PCI_EXP_RTSTA_PME is true now forever.  This issue
+can be reproduced by booting kernel with pci=nomsi.
+
+Use the normal register bank for the PCI config accessors.  The privileged
+bank is used only internally by this driver.
+
+Fixes: e77f847d ("PCI: rockchip: Add Rockchip PCIe controller support")
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Jeffy Chen <jeffy.chen@rock-chips.com>
+Cc: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/host/pcie-rockchip.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/host/pcie-rockchip.c
++++ b/drivers/pci/host/pcie-rockchip.c
+@@ -139,6 +139,7 @@
+                PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
+                PCIE_CORE_INT_MMVC)
++#define PCIE_RC_CONFIG_NORMAL_BASE    0x800000
+ #define PCIE_RC_CONFIG_BASE           0xa00000
+ #define PCIE_RC_CONFIG_RID_CCR                (PCIE_RC_CONFIG_BASE + 0x08)
+ #define   PCIE_RC_CONFIG_SCC_SHIFT            16
+@@ -295,7 +296,9 @@ static int rockchip_pcie_valid_device(st
+ static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
+                                    int where, int size, u32 *val)
+ {
+-      void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
++      void __iomem *addr;
++
++      addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where;
+       if (!IS_ALIGNED((uintptr_t)addr, size)) {
+               *val = 0;
+@@ -319,11 +322,13 @@ static int rockchip_pcie_wr_own_conf(str
+                                    int where, int size, u32 val)
+ {
+       u32 mask, tmp, offset;
++      void __iomem *addr;
+       offset = where & ~0x3;
++      addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset;
+       if (size == 4) {
+-              writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
++              writel(val, addr);
+               return PCIBIOS_SUCCESSFUL;
+       }
+@@ -334,9 +339,9 @@ static int rockchip_pcie_wr_own_conf(str
+        * corrupt RW1C bits in adjacent registers.  But the hardware
+        * doesn't support smaller writes.
+        */
+-      tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
++      tmp = readl(addr) & mask;
+       tmp |= val << ((where & 0x3) * 8);
+-      writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
++      writel(tmp, addr);
+       return PCIBIOS_SUCCESSFUL;
+ }
diff --git a/queue-4.12/pci-vmd-move-srcu-cleanup-after-bus-child-device-removal.patch b/queue-4.12/pci-vmd-move-srcu-cleanup-after-bus-child-device-removal.patch
new file mode 100644 (file)
index 0000000..87fb25f
--- /dev/null
@@ -0,0 +1,36 @@
+From 0cb259c47a4df466d641c1f07ae3eccaa9ba3ccb Mon Sep 17 00:00:00 2001
+From: Jon Derrick <jonathan.derrick@intel.com>
+Date: Thu, 22 Jun 2017 09:15:42 -0600
+Subject: PCI: vmd: Move SRCU cleanup after bus, child device removal
+
+From: Jon Derrick <jonathan.derrick@intel.com>
+
+commit 0cb259c47a4df466d641c1f07ae3eccaa9ba3ccb upstream.
+
+Recent __call_srcu() changes have exposed that we need to cleanup SRCU
+structures after pci_stop_root_bus() calls into vmd_msi_free().
+
+Fixes: 3906b91844d6 ("PCI: vmd: Use SRCU as a local RCU to prevent delaying global RCU")
+Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/host/vmd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/host/vmd.c
++++ b/drivers/pci/host/vmd.c
+@@ -733,10 +733,10 @@ static void vmd_remove(struct pci_dev *d
+       struct vmd_dev *vmd = pci_get_drvdata(dev);
+       vmd_detach_resources(vmd);
+-      vmd_cleanup_srcu(vmd);
+       sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
+       pci_stop_root_bus(vmd->bus);
+       pci_remove_root_bus(vmd->bus);
++      vmd_cleanup_srcu(vmd);
+       vmd_teardown_dma_ops(vmd);
+       irq_domain_remove(vmd->irq_domain);
+ }
diff --git a/queue-4.12/pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch b/queue-4.12/pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch
new file mode 100644 (file)
index 0000000..20c9182
--- /dev/null
@@ -0,0 +1,84 @@
+From 13cfc732160f7bc7e596128ce34cda361c556966 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Fri, 19 Aug 2016 16:30:25 +0800
+Subject: PCI: Work around poweroff & suspend-to-RAM issue on Macbook Pro 11
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+commit 13cfc732160f7bc7e596128ce34cda361c556966 upstream.
+
+Neither soft poweroff (transition to ACPI power state S5) nor
+suspend-to-RAM (transition to state S3) works on the Macbook Pro 11,4 and
+11,5.
+
+The problem is related to the [mem 0x7fa00000-0x7fbfffff] space.  When we
+use that space, e.g., by assigning it to the 00:1c.0 Root Port, the ACPI
+Power Management 1 Control Register (PM1_CNT) at [io 0x1804] doesn't work
+anymore.
+
+Linux does a soft poweroff (transition to S5) by writing to PM1_CNT.  The
+theory about why this doesn't work is:
+
+  - The write to PM1_CNT causes an SMI
+  - The BIOS SMI handler depends on something in
+    [mem 0x7fa00000-0x7fbfffff]
+  - When Linux assigns [mem 0x7fa00000-0x7fbfffff] to the 00:1c.0 Port, it
+    covers up whatever the SMI handler uses, so the SMI handler no longer
+    works correctly
+
+Reserve the [mem 0x7fa00000-0x7fbfffff] space so we don't assign it to
+anything.
+
+This is voodoo programming, since we don't know what the real conflict is,
+but we've failed to find the root cause.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=103211
+Tested-by: thejoe@gmail.com
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Rafael J. Wysocki <rafael@kernel.org>
+Cc: Lukas Wunner <lukas@wunner.de>
+Cc: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/pci/fixup.c |   32 ++++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -571,3 +571,35 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IN
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
++
++/*
++ * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff]
++ *
++ * Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to
++ * the 00:1c.0 Root Port, causes a conflict with [io 0x1804], which is used
++ * for soft poweroff and suspend-to-RAM.
++ *
++ * As far as we know, this is related to the address space, not to the Root
++ * Port itself.  Attaching the quirk to the Root Port is a convenience, but
++ * it could probably also be a standalone DMI quirk.
++ *
++ * https://bugzilla.kernel.org/show_bug.cgi?id=103211
++ */
++static void quirk_apple_mbp_poweroff(struct pci_dev *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct resource *res;
++
++      if ((!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,4") &&
++           !dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,5")) ||
++          pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x1c, 0))
++              return;
++
++      res = request_mem_region(0x7fa00000, 0x200000,
++                               "MacBook Pro poweroff workaround");
++      if (res)
++              dev_info(dev, "claimed %s %pR\n", res->name, res);
++      else
++              dev_info(dev, "can't work around MacBook Pro poweroff issue\n");
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff);
index 9e9a9c3698fa87fcee5202acfc34eda9f08bf817..331ab05847357badbe6ffdebed29160649e83c0f 100644 (file)
@@ -55,3 +55,22 @@ powerpc-fix-emulation-of-mfocrf-in-emulate_step.patch
 powerpc-asm-mark-cr0-as-clobbered-in-mftb.patch
 powerpc-mm-radix-properly-clear-process-table-entry.patch
 powerpc-perf-fix-sdar_mode-value-for-continous-sampling-on-power9.patch
+xen-x86-fix-cpu-hotplug.patch
+pci-vmd-move-srcu-cleanup-after-bus-child-device-removal.patch
+pci-work-around-poweroff-suspend-to-ram-issue-on-macbook-pro-11.patch
+pci-rockchip-use-normal-register-bank-for-config-accessors.patch
+pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch
+pci-msi-ignore-affinity-if-pre-post-vector-count-is-more-than-min_vecs.patch
+usb-xhci-fix-spinlock-recursion-for-usb2-test-mode.patch
+xhci-fix-memleak-in-xhci_run.patch
+xhci-fix-20000ms-port-resume-timeout.patch
+xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch
+xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch
+mxl111sf-fix-driver-to-use-heap-allocate-buffers-for-usb-messages.patch
+usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch
+usb-cdc-acm-add-device-id-for-quirky-printer.patch
+usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch
+usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch
+hid-multitouch-do-not-blindly-set-ev_key-or-ev_abs-bits.patch
+md-don-t-use-flush_signals-in-userspace-processes.patch
+md-fix-deadlock-between-mddev_suspend-and-md_write_start.patch
diff --git a/queue-4.12/usb-cdc-acm-add-device-id-for-quirky-printer.patch b/queue-4.12/usb-cdc-acm-add-device-id-for-quirky-printer.patch
new file mode 100644 (file)
index 0000000..b18a7bd
--- /dev/null
@@ -0,0 +1,33 @@
+From fe855789d605590e57f9cd968d85ecce46f5c3fd Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Wed, 12 Jul 2017 15:08:39 +0200
+Subject: USB: cdc-acm: add device-id for quirky printer
+
+From: Johan Hovold <johan@kernel.org>
+
+commit fe855789d605590e57f9cd968d85ecce46f5c3fd upstream.
+
+Add device-id entry for DATECS FP-2000 fiscal printer needing the
+NO_UNION_NORMAL quirk.
+
+Reported-by: Anton Avramov <lukav@lukav.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1829,6 +1829,9 @@ static const struct usb_device_id acm_id
+       { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */
+       .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+       },
++      { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
++      .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
++      },
+       { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
+       .driver_info = CLEAR_HALT_CONDITIONS,
diff --git a/queue-4.12/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch b/queue-4.12/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch
new file mode 100644 (file)
index 0000000..92053b4
--- /dev/null
@@ -0,0 +1,37 @@
+From 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 19 Jul 2017 16:16:54 +0900
+Subject: usb: renesas_usbhs: fix usbhsc_resume() for !USBHSF_RUNTIME_PWCTRL
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce upstream.
+
+This patch fixes an issue that some registers may be not initialized
+after resume if the USBHSF_RUNTIME_PWCTRL is not set. Otherwise,
+if a cable is not connected, the driver will not enable INTENB0.VBSE
+after resume. And then, the driver cannot detect the VBUS.
+
+Fixes: ca8a282a5373 ("usb: gadget: renesas_usbhs: add suspend/resume support")
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/renesas_usbhs/common.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/renesas_usbhs/common.c
++++ b/drivers/usb/renesas_usbhs/common.c
+@@ -752,8 +752,10 @@ static int usbhsc_resume(struct device *
+       struct usbhs_priv *priv = dev_get_drvdata(dev);
+       struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+-      if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
++      if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
+               usbhsc_power_ctrl(priv, 1);
++              usbhs_mod_autonomy_mode(priv);
++      }
+       usbhs_platform_call(priv, phy_reset, pdev);
diff --git a/queue-4.12/usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch b/queue-4.12/usb-renesas_usbhs-gadget-disable-all-eps-when-the-driver-stops.patch
new file mode 100644 (file)
index 0000000..06ec1a8
--- /dev/null
@@ -0,0 +1,121 @@
+From b8b9c974afee685789fcbb191b52d1790be3608c Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 19 Jul 2017 16:16:55 +0900
+Subject: usb: renesas_usbhs: gadget: disable all eps when the driver stops
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit b8b9c974afee685789fcbb191b52d1790be3608c upstream.
+
+A gadget driver will not disable eps immediately when ->disconnect()
+is called. But, since this driver assumes all eps stop after
+the ->disconnect(), unexpected behavior happens (especially in system
+suspend).
+So, this patch disables all eps in usbhsg_try_stop(). After disabling
+eps by renesas_usbhs driver, since some functions will be called by
+both a gadget and renesas_usbhs driver, renesas_usbhs driver should
+protect uep->pipe. To protect uep->pipe easily, this patch adds a new
+lock in struct usbhsg_uep.
+
+Fixes: 2f98382dc ("usb: renesas_usbhs: Add Renesas USBHS Gadget")
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/renesas_usbhs/mod_gadget.c |   31 ++++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/renesas_usbhs/mod_gadget.c
++++ b/drivers/usb/renesas_usbhs/mod_gadget.c
+@@ -37,6 +37,7 @@ struct usbhsg_gpriv;
+ struct usbhsg_uep {
+       struct usb_ep            ep;
+       struct usbhs_pipe       *pipe;
++      spinlock_t              lock;   /* protect the pipe */
+       char ep_name[EP_NAME_SIZE];
+@@ -636,10 +637,16 @@ usbhsg_ep_enable_end:
+ static int usbhsg_ep_disable(struct usb_ep *ep)
+ {
+       struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+-      struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
++      struct usbhs_pipe *pipe;
++      unsigned long flags;
++      int ret = 0;
+-      if (!pipe)
+-              return -EINVAL;
++      spin_lock_irqsave(&uep->lock, flags);
++      pipe = usbhsg_uep_to_pipe(uep);
++      if (!pipe) {
++              ret = -EINVAL;
++              goto out;
++      }
+       usbhsg_pipe_disable(uep);
+       usbhs_pipe_free(pipe);
+@@ -647,6 +654,9 @@ static int usbhsg_ep_disable(struct usb_
+       uep->pipe->mod_private  = NULL;
+       uep->pipe               = NULL;
++out:
++      spin_unlock_irqrestore(&uep->lock, flags);
++
+       return 0;
+ }
+@@ -696,8 +706,11 @@ static int usbhsg_ep_dequeue(struct usb_
+ {
+       struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+       struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
+-      struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
++      struct usbhs_pipe *pipe;
++      unsigned long flags;
++      spin_lock_irqsave(&uep->lock, flags);
++      pipe = usbhsg_uep_to_pipe(uep);
+       if (pipe)
+               usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+@@ -706,6 +719,7 @@ static int usbhsg_ep_dequeue(struct usb_
+        * even if the pipe is NULL.
+        */
+       usbhsg_queue_pop(uep, ureq, -ECONNRESET);
++      spin_unlock_irqrestore(&uep->lock, flags);
+       return 0;
+ }
+@@ -852,10 +866,10 @@ static int usbhsg_try_stop(struct usbhs_
+ {
+       struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+       struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+-      struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
++      struct usbhsg_uep *uep;
+       struct device *dev = usbhs_priv_to_dev(priv);
+       unsigned long flags;
+-      int ret = 0;
++      int ret = 0, i;
+       /********************  spin lock ********************/
+       usbhs_lock(priv, flags);
+@@ -887,7 +901,9 @@ static int usbhsg_try_stop(struct usbhs_
+       usbhs_sys_set_test_mode(priv, 0);
+       usbhs_sys_function_ctrl(priv, 0);
+-      usbhsg_ep_disable(&dcp->ep);
++      /* disable all eps */
++      usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
++              usbhsg_ep_disable(&uep->ep);
+       dev_dbg(dev, "stop gadget\n");
+@@ -1069,6 +1085,7 @@ int usbhs_mod_gadget_probe(struct usbhs_
+               ret = -ENOMEM;
+               goto usbhs_mod_gadget_probe_err_gpriv;
+       }
++      spin_lock_init(&uep->lock);
+       gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
+       dev_info(dev, "%stransceiver found\n",
diff --git a/queue-4.12/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch b/queue-4.12/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..43fc569
--- /dev/null
@@ -0,0 +1,44 @@
+From 446230f52a5bef593554510302465eabab45a372 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Thu, 6 Jul 2017 16:06:32 +0100
+Subject: usb: storage: return on error to avoid a null pointer dereference
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit 446230f52a5bef593554510302465eabab45a372 upstream.
+
+When us->extra is null the driver is not initialized, however, a
+later call to osd200_scsi_to_ata is made that dereferences
+us->extra, causing a null pointer dereference.  The code
+currently detects and reports that the driver is not initialized;
+add a return to avoid the subsequent dereference issue in this
+check.
+
+Thanks to Alan Stern for pointing out that srb->result needs setting
+to DID_ERROR << 16
+
+Detected by CoverityScan, CID#100308 ("Dereference after null check")
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/storage/isd200.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/storage/isd200.c
++++ b/drivers/usb/storage/isd200.c
+@@ -1529,8 +1529,11 @@ static void isd200_ata_command(struct sc
+       /* Make sure driver was initialized */
+-      if (us->extra == NULL)
++      if (us->extra == NULL) {
+               usb_stor_dbg(us, "ERROR Driver not initialized\n");
++              srb->result = DID_ERROR << 16;
++              return;
++      }
+       scsi_set_resid(srb, 0);
+       /* scsi_bufflen might change in protocol translation to ata */
diff --git a/queue-4.12/usb-xhci-fix-spinlock-recursion-for-usb2-test-mode.patch b/queue-4.12/usb-xhci-fix-spinlock-recursion-for-usb2-test-mode.patch
new file mode 100644 (file)
index 0000000..4213284
--- /dev/null
@@ -0,0 +1,39 @@
+From 576d55460e7f209139545a348746c2fcadf61bc3 Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@nxp.com>
+Date: Thu, 20 Jul 2017 14:48:30 +0300
+Subject: usb: xhci: fix spinlock recursion for USB2 test mode
+
+From: Peter Chen <peter.chen@nxp.com>
+
+commit 576d55460e7f209139545a348746c2fcadf61bc3 upstream.
+
+Both xhci_hub_control and xhci_disable_slot tries to hold spinlock, the
+spinlock recursion occurs when enters USB2 test mode. Fix it by unlock
+spinlock before calling xhci_disable_slot.
+
+Fixes: 0f1d832ed1fb ("usb: xhci: Add port test modes support for usb2")
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -603,12 +603,14 @@ static int xhci_enter_test_mode(struct x
+       /* Disable all Device Slots */
+       xhci_dbg(xhci, "Disable all slots\n");
++      spin_unlock_irqrestore(&xhci->lock, *flags);
+       for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+               retval = xhci_disable_slot(xhci, NULL, i);
+               if (retval)
+                       xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
+                                i, retval);
+       }
++      spin_lock_irqsave(&xhci->lock, *flags);
+       /* Put all ports to the Disable state by clear PP */
+       xhci_dbg(xhci, "Disable all port (PP = 0)\n");
+       /* Power off USB3 ports*/
diff --git a/queue-4.12/xen-x86-fix-cpu-hotplug.patch b/queue-4.12/xen-x86-fix-cpu-hotplug.patch
new file mode 100644 (file)
index 0000000..d0e94dc
--- /dev/null
@@ -0,0 +1,47 @@
+From c185ddec54657c145a0c2055e4b87918da24974f Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+Date: Wed, 5 Jul 2017 16:05:20 +0200
+Subject: xen/x86: fix cpu hotplug
+
+From: Juergen Gross <jgross@suse.com>
+
+commit c185ddec54657c145a0c2055e4b87918da24974f upstream.
+
+Commit dc6416f1d711eb4c1726e845d653235dcaae12e1 ("xen/x86: Call
+cpu_startup_entry(CPUHP_AP_ONLINE_IDLE) from xen_play_dead()")
+introduced an error leading to a stack overflow of the idle task when
+a cpu was brought offline/online many times: by calling
+cpu_startup_entry() instead of returning at the end of xen_play_dead()
+do_idle() would be entered again and again.
+
+Don't use cpu_startup_entry(), but cpuhp_online_idle() instead allowing
+to return from xen_play_dead().
+
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/xen/smp_pv.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/xen/smp_pv.c
++++ b/arch/x86/xen/smp_pv.c
+@@ -19,6 +19,7 @@
+ #include <linux/irq_work.h>
+ #include <linux/tick.h>
+ #include <linux/nmi.h>
++#include <linux/cpuhotplug.h>
+ #include <asm/paravirt.h>
+ #include <asm/desc.h>
+@@ -417,7 +418,7 @@ static void xen_pv_play_dead(void) /* us
+        */
+       tick_nohz_idle_enter();
+-      cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
++      cpuhp_online_idle(CPUHP_AP_ONLINE_IDLE);
+ }
+ #else /* !CONFIG_HOTPLUG_CPU */
diff --git a/queue-4.12/xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch b/queue-4.12/xhci-bad-ethernet-performance-plugged-in-asm1042a-host.patch
new file mode 100644 (file)
index 0000000..c4b58b4
--- /dev/null
@@ -0,0 +1,172 @@
+From 9da5a1092b13468839b1a864b126cacfb72ad016 Mon Sep 17 00:00:00 2001
+From: Jiahau Chang <jiahau@gmail.com>
+Date: Thu, 20 Jul 2017 14:48:27 +0300
+Subject: xhci: Bad Ethernet performance plugged in ASM1042A host
+
+From: Jiahau Chang <jiahau@gmail.com>
+
+commit 9da5a1092b13468839b1a864b126cacfb72ad016 upstream.
+
+When USB Ethernet is plugged in ASMEDIA ASM1042A xHCI host, bad
+performance was manifesting in Web browser use (like download
+large file such as ISO image). It is known limitation of
+ASM1042A that is not compatible with driver scheduling,
+As a workaround we can modify flow control handling of ASM1042A.
+The register we modify is changes the behavior
+
+[use quirk bit 28, usleep_range 40-60us, empty non-pci function -Mathias]
+Signed-off-by: Jiahau Chang <Lars_chang@asmedia.com.tw>
+Signed-off-by: Ian Pilcher <arequipeno@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/pci-quirks.c |   54 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/pci-quirks.h |    2 +
+ drivers/usb/host/xhci-pci.c   |    6 ++++
+ drivers/usb/host/xhci.c       |    6 ++++
+ drivers/usb/host/xhci.h       |    1 
+ 5 files changed, 69 insertions(+)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -77,6 +77,16 @@
+ #define USB_INTEL_USB3_PSSEN   0xD8
+ #define USB_INTEL_USB3PRM      0xDC
++/* ASMEDIA quirk use */
++#define ASMT_DATA_WRITE0_REG  0xF8
++#define ASMT_DATA_WRITE1_REG  0xFC
++#define ASMT_CONTROL_REG      0xE0
++#define ASMT_CONTROL_WRITE_BIT        0x02
++#define ASMT_WRITEREG_CMD     0x10423
++#define ASMT_FLOWCTL_ADDR     0xFA30
++#define ASMT_FLOWCTL_DATA     0xBA
++#define ASMT_PSEUDO_DATA      0
++
+ /*
+  * amd_chipset_gen values represent AMD different chipset generations
+  */
+@@ -412,6 +422,50 @@ void usb_amd_quirk_pll_disable(void)
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
++static int usb_asmedia_wait_write(struct pci_dev *pdev)
++{
++      unsigned long retry_count;
++      unsigned char value;
++
++      for (retry_count = 1000; retry_count > 0; --retry_count) {
++
++              pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
++
++              if (value == 0xff) {
++                      dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
++                      return -EIO;
++              }
++
++              if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
++                      return 0;
++
++              usleep_range(40, 60);
++      }
++
++      dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
++      return -ETIMEDOUT;
++}
++
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
++{
++      if (usb_asmedia_wait_write(pdev) != 0)
++              return;
++
++      /* send command and address to device */
++      pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
++      pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
++      pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++
++      if (usb_asmedia_wait_write(pdev) != 0)
++              return;
++
++      /* send data to device */
++      pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
++      pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
++      pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++}
++EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
++
+ void usb_amd_quirk_pll_enable(void)
+ {
+       usb_amd_quirk_pll(0);
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -11,6 +11,7 @@ bool usb_amd_prefetch_quirk(void);
+ void usb_amd_dev_put(void);
+ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
+ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ void sb800_prefetch(struct device *dev, int on);
+@@ -18,6 +19,7 @@ void sb800_prefetch(struct device *dev,
+ struct pci_dev;
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
++static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
+ static inline void usb_amd_dev_put(void) {}
+ static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+ static inline void sb800_prefetch(struct device *dev, int on) {}
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -59,6 +59,8 @@
+ #define PCI_DEVICE_ID_AMD_PROMONTORYA_2                       0x43bb
+ #define PCI_DEVICE_ID_AMD_PROMONTORYA_1                       0x43bc
++#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI              0x1142
++
+ static const char hcd_name[] = "xhci_hcd";
+ static struct hc_driver __read_mostly xhci_pci_hc_driver;
+@@ -217,6 +219,10 @@ static void xhci_pci_quirks(struct devic
+                       pdev->device == 0x1142)
+               xhci->quirks |= XHCI_TRUST_TX_LENGTH;
++      if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
++              pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
++              xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL;
++
+       if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
+               xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -198,6 +198,9 @@ int xhci_reset(struct xhci_hcd *xhci)
+       if (ret)
+               return ret;
++      if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
++              usb_asmedia_modifyflowcontrol(to_pci_dev(xhci_to_hcd(xhci)->self.controller));
++
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                        "Wait for controller to be ready for doorbell rings");
+       /*
+@@ -1087,6 +1090,9 @@ int xhci_resume(struct xhci_hcd *xhci, b
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running)
+               compliance_mode_recovery_timer_init(xhci);
++      if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
++              usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
++
+       /* Re-enable port polling. */
+       xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+       set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1820,6 +1820,7 @@ struct xhci_hcd {
+ #define XHCI_BROKEN_PORT_PED  (1 << 25)
+ #define XHCI_LIMIT_ENDPOINT_INTERVAL_7        (1 << 26)
+ #define XHCI_U2_DISABLE_WAKE  (1 << 27)
++#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL       (1 << 28)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
diff --git a/queue-4.12/xhci-fix-20000ms-port-resume-timeout.patch b/queue-4.12/xhci-fix-20000ms-port-resume-timeout.patch
new file mode 100644 (file)
index 0000000..7b987f7
--- /dev/null
@@ -0,0 +1,41 @@
+From a54408d0a004757789863d74e29c2297edae0b4d Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 20 Jul 2017 14:48:29 +0300
+Subject: xhci: fix 20000ms port resume timeout
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit a54408d0a004757789863d74e29c2297edae0b4d upstream.
+
+A uncleared PLC (port link change) bit will prevent furuther port event
+interrupts for that port. Leaving it uncleared caused get_port_status()
+to timeout after 20000ms while waiting to get the final port event
+interrupt for resume -> U0 state change.
+
+This is a targeted fix for a specific case where we get a port resume event
+racing with xhci resume. The port event interrupt handler notices xHC is
+not yet running and bails out early, leaving PLC uncleared.
+
+The whole xhci port resuming needs more attention, but while working on it
+it anyways makes sense to always ensure PLC is cleared in get_port_status
+before setting a new link state and waiting for its completion.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -899,6 +899,9 @@ static u32 xhci_get_port_status(struct u
+                       clear_bit(wIndex, &bus_state->resuming_ports);
+                       set_bit(wIndex, &bus_state->rexit_ports);
++
++                      xhci_test_and_clear_bit(xhci, port_array, wIndex,
++                                              PORT_PLC);
+                       xhci_set_link_state(xhci, port_array, wIndex,
+                                       XDEV_U0);
diff --git a/queue-4.12/xhci-fix-memleak-in-xhci_run.patch b/queue-4.12/xhci-fix-memleak-in-xhci_run.patch
new file mode 100644 (file)
index 0000000..fc3d421
--- /dev/null
@@ -0,0 +1,54 @@
+From d6f5f071f1e13cadecf8aef1faa7e5d6fbc9f33b Mon Sep 17 00:00:00 2001
+From: Shu Wang <shuwang@redhat.com>
+Date: Thu, 20 Jul 2017 14:48:31 +0300
+Subject: xhci: fix memleak in xhci_run()
+
+From: Shu Wang <shuwang@redhat.com>
+
+commit d6f5f071f1e13cadecf8aef1faa7e5d6fbc9f33b upstream.
+
+Found this issue by kmemleak.
+xhci_run() did not check return val and free command for
+xhci_queue_vendor_command()
+
+unreferenced object 0xffff88011c0be500 (size 64):
+  comm "kworker/0:1", pid 58, jiffies 4294670908 (age 50.420s)
+  hex dump (first 32 bytes):
+  backtrace:
+    [<ffffffff8176166a>] kmemleak_alloc+0x4a/0xa0
+    [<ffffffff8121801a>] kmem_cache_alloc_trace+0xca/0x1d0
+    [<ffffffff81576bf4>] xhci_alloc_command+0x44/0x130
+    [<ffffffff8156f1cc>] xhci_run+0x4cc/0x630
+    [<ffffffff8153b84b>] usb_add_hcd+0x3bb/0x950
+    [<ffffffff8154eac8>] usb_hcd_pci_probe+0x188/0x500
+    [<ffffffff815851ac>] xhci_pci_probe+0x2c/0x220
+    [<ffffffff813d2ca5>] local_pci_probe+0x45/0xa0
+    [<ffffffff810a54e4>] work_for_cpu_fn+0x14/0x20
+    [<ffffffff810a8409>] process_one_work+0x149/0x360
+    [<ffffffff810a8d08>] worker_thread+0x1d8/0x3c0
+    [<ffffffff810ae7d9>] kthread+0x109/0x140
+    [<ffffffff8176d585>] ret_from_fork+0x25/0x30
+    [<ffffffffffffffff>] 0xffffffffffffffff
+
+Signed-off-by: Shu Wang <shuwang@redhat.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -622,8 +622,10 @@ int xhci_run(struct usb_hcd *hcd)
+               if (!command)
+                       return -ENOMEM;
+-              xhci_queue_vendor_command(xhci, command, 0, 0, 0,
++              ret = xhci_queue_vendor_command(xhci, command, 0, 0, 0,
+                               TRB_TYPE(TRB_NEC_GET_FW));
++              if (ret)
++                      xhci_free_command(xhci, command);
+       }
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "Finished xhci_run for USB2 roothub");
diff --git a/queue-4.12/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch b/queue-4.12/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch
new file mode 100644 (file)
index 0000000..c9094dd
--- /dev/null
@@ -0,0 +1,51 @@
+From 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 20 Jul 2017 14:48:26 +0300
+Subject: xhci: Fix NULL pointer dereference when cleaning up streams for removed host
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 upstream.
+
+This off by one in stream_id indexing caused NULL pointer dereference and
+soft lockup on machines with USB attached SCSI devices connected to a
+hotpluggable xhci controller.
+
+The code that cleans up pending URBs for dead hosts tried to dereference
+a stream ring at the invalid stream_id 0.
+ep->stream_info->stream_rings[0] doesn't point to a ring.
+
+Start looping stream_id from 1 like in all the other places in the driver,
+and check that the ring exists before trying to kill URBs on it.
+
+Reported-by: rocko r <rockorequin@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -845,13 +845,16 @@ static void xhci_kill_endpoint_urbs(stru
+                       (ep->ep_state & EP_GETTING_NO_STREAMS)) {
+               int stream_id;
+-              for (stream_id = 0; stream_id < ep->stream_info->num_streams;
++              for (stream_id = 1; stream_id < ep->stream_info->num_streams;
+                               stream_id++) {
++                      ring = ep->stream_info->stream_rings[stream_id];
++                      if (!ring)
++                              continue;
++
+                       xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+                                       "Killing URBs for slot ID %u, ep index %u, stream %u",
+-                                      slot_id, ep_index, stream_id + 1);
+-                      xhci_kill_ring_urbs(xhci,
+-                                      ep->stream_info->stream_rings[stream_id]);
++                                      slot_id, ep_index, stream_id);
++                      xhci_kill_ring_urbs(xhci, ring);
+               }
+       } else {
+               ring = ep->ring;