]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.1 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 1 Nov 2011 19:41:35 +0000 (12:41 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 1 Nov 2011 19:41:35 +0000 (12:41 -0700)
20 files changed:
queue-3.1/alsa-hda-add-new-revision-for-alc662.patch [new file with mode: 0644]
queue-3.1/alsa-hda-keep-eapd-turned-on-for-old-conexant-chips.patch [new file with mode: 0644]
queue-3.1/alsa-hda-remove-bad-code-for-idt-92hd83-family-patch.patch [new file with mode: 0644]
queue-3.1/epoll-fix-spurious-lockdep-warnings.patch [new file with mode: 0644]
queue-3.1/ipr-always-initiate-hard-reset-in-kdump-kernel.patch [new file with mode: 0644]
queue-3.1/isci-fix-missed-unlock-in-apc_agent_timeout.patch [new file with mode: 0644]
queue-3.1/isci-fix-support-for-large-smp-requests.patch [new file with mode: 0644]
queue-3.1/leds-save-the-delay-values-after-a-successful-call-to-blink_set.patch [new file with mode: 0644]
queue-3.1/leds-turn-the-blink_timer-off-before-starting-to-blink.patch [new file with mode: 0644]
queue-3.1/libsas-set-sas_address-and-device-type-of-rphy.patch [new file with mode: 0644]
queue-3.1/megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch [new file with mode: 0644]
queue-3.1/series
queue-3.1/target-fix-report-target-port-groups-handling-with-small-allocation-length.patch [new file with mode: 0644]
queue-3.1/target-fix-transport_cmd_finish_abort-queue-removal-bug.patch [new file with mode: 0644]
queue-3.1/target-prevent-cmd-se_queue_node-double-add.patch [new file with mode: 0644]
queue-3.1/target-prevent-transport_free_cmd_intr-processing-in-core_tmr_drain_cmd_list.patch [new file with mode: 0644]
queue-3.1/target-prevent-transport_send_task_abort-when-check_condition-status.patch [new file with mode: 0644]
queue-3.1/target-re-org-of-core_tmr_lun_reset.patch [new file with mode: 0644]
queue-3.1/x86-fix-compilation-bug-in-kprobes-twobyte_is_boostable.patch [new file with mode: 0644]
queue-3.1/x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch [new file with mode: 0644]

diff --git a/queue-3.1/alsa-hda-add-new-revision-for-alc662.patch b/queue-3.1/alsa-hda-add-new-revision-for-alc662.patch
new file mode 100644 (file)
index 0000000..a3782b8
--- /dev/null
@@ -0,0 +1,34 @@
+From cc667a72d471e79fd8e5e291ea115923cf44dca0 Mon Sep 17 00:00:00 2001
+From: David Henningsson <david.henningsson@canonical.com>
+Date: Tue, 18 Oct 2011 14:07:51 +0200
+Subject: ALSA: HDA: Add new revision for ALC662
+
+From: David Henningsson <david.henningsson@canonical.com>
+
+commit cc667a72d471e79fd8e5e291ea115923cf44dca0 upstream.
+
+The revision 0x100300 was found for ALC662. It seems to work well
+with patch_alc662.
+
+BugLink: http://bugs.launchpad.net/bugs/877373
+Tested-by: Shengyao Xue <Shengyao.xue@canonical.com>
+Signed-off-by: David Henningsson <david.henningsson@canonical.com>
+Acked-by: Kailang Yang <kailang@realtek.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_realtek.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -5421,6 +5421,8 @@ static const struct hda_codec_preset snd
+         .patch = patch_alc882 },
+       { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
+         .patch = patch_alc662 },
++      { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
++        .patch = patch_alc662 },
+       { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
+       { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
+       { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
diff --git a/queue-3.1/alsa-hda-keep-eapd-turned-on-for-old-conexant-chips.patch b/queue-3.1/alsa-hda-keep-eapd-turned-on-for-old-conexant-chips.patch
new file mode 100644 (file)
index 0000000..e7ab1d7
--- /dev/null
@@ -0,0 +1,123 @@
+From 254f296840b64b034a4c850d45dbde7c040f0819 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 14 Oct 2011 15:22:34 +0200
+Subject: ALSA: hda - Keep EAPD turned on for old Conexant chips
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 254f296840b64b034a4c850d45dbde7c040f0819 upstream.
+
+In the old Conexant chips (5045, 5047, 5051 and 5066), a single EAPD
+may handle both headphone and speaker outputs while it's assigned only
+to one of them.  Turning off dynamically leads to the unexpected silent
+output in such a configuration with the auto-mute function.
+
+Since it's difficult to know how the EAPD is handled in the actual h/w
+implementation, better to keep EAPD on while running for such codecs.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_conexant.c |   43 ++++++++++++++++++++---------------------
+ 1 file changed, 22 insertions(+), 21 deletions(-)
+
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -136,6 +136,7 @@ struct conexant_spec {
+       unsigned int thinkpad:1;
+       unsigned int hp_laptop:1;
+       unsigned int asus:1;
++      unsigned int pin_eapd_ctrls:1;
+       unsigned int adc_switching:1;
+@@ -3473,12 +3474,14 @@ static void cx_auto_turn_eapd(struct hda
+ static void do_automute(struct hda_codec *codec, int num_pins,
+                       hda_nid_t *pins, bool on)
+ {
++      struct conexant_spec *spec = codec->spec;
+       int i;
+       for (i = 0; i < num_pins; i++)
+               snd_hda_codec_write(codec, pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   on ? PIN_OUT : 0);
+-      cx_auto_turn_eapd(codec, num_pins, pins, on);
++      if (spec->pin_eapd_ctrls)
++              cx_auto_turn_eapd(codec, num_pins, pins, on);
+ }
+ static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
+@@ -3503,9 +3506,12 @@ static void cx_auto_update_speakers(stru
+       int on = 1;
+       /* turn on HP EAPD when HP jacks are present */
+-      if (spec->auto_mute)
+-              on = spec->hp_present;
+-      cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
++      if (spec->pin_eapd_ctrls) {
++              if (spec->auto_mute)
++                      on = spec->hp_present;
++              cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
++      }
++
+       /* mute speakers in auto-mode if HP or LO jacks are plugged */
+       if (spec->auto_mute)
+               on = !(spec->hp_present ||
+@@ -3932,20 +3938,10 @@ static void cx_auto_parse_beep(struct hd
+ #define cx_auto_parse_beep(codec)
+ #endif
+-static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+-{
+-      int i;
+-      for (i = 0; i < nums; i++)
+-              if (list[i] == nid)
+-                      return true;
+-      return false;
+-}
+-
+-/* parse extra-EAPD that aren't assigned to any pins */
++/* parse EAPDs */
+ static void cx_auto_parse_eapd(struct hda_codec *codec)
+ {
+       struct conexant_spec *spec = codec->spec;
+-      struct auto_pin_cfg *cfg = &spec->autocfg;
+       hda_nid_t nid, end_nid;
+       end_nid = codec->start_nid + codec->num_nodes;
+@@ -3954,14 +3950,18 @@ static void cx_auto_parse_eapd(struct hd
+                       continue;
+               if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
+                       continue;
+-              if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
+-                  found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
+-                  found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs))
+-                      continue;
+               spec->eapds[spec->num_eapds++] = nid;
+               if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
+                       break;
+       }
++
++      /* NOTE: below is a wild guess; if we have more than two EAPDs,
++       * it's a new chip, where EAPDs are supposed to be associated to
++       * pins, and we can control EAPD per pin.
++       * OTOH, if only one or two EAPDs are found, it's an old chip,
++       * thus it might control over all pins.
++       */
++      spec->pin_eapd_ctrls = spec->num_eapds > 2;
+ }
+ static int cx_auto_parse_auto_config(struct hda_codec *codec)
+@@ -4067,8 +4067,9 @@ static void cx_auto_init_output(struct h
+               }
+       }
+       cx_auto_update_speakers(codec);
+-      /* turn on/off extra EAPDs, too */
+-      cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
++      /* turn on all EAPDs if no individual EAPD control is available */
++      if (!spec->pin_eapd_ctrls)
++              cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+ }
+ static void cx_auto_init_input(struct hda_codec *codec)
diff --git a/queue-3.1/alsa-hda-remove-bad-code-for-idt-92hd83-family-patch.patch b/queue-3.1/alsa-hda-remove-bad-code-for-idt-92hd83-family-patch.patch
new file mode 100644 (file)
index 0000000..4bd9abe
--- /dev/null
@@ -0,0 +1,59 @@
+From 6c5c04e509b7000617b09d4301f0b9b6d171d1e6 Mon Sep 17 00:00:00 2001
+From: Charles Chin <Charles.Chin@idt.com>
+Date: Thu, 13 Oct 2011 07:54:09 +0200
+Subject: ALSA: hda - Remove bad code for IDT 92HD83 family patch
+
+From: Charles Chin <Charles.Chin@idt.com>
+
+commit 6c5c04e509b7000617b09d4301f0b9b6d171d1e6 upstream.
+
+The purpose of this patch is to remove a section of "bad" code that
+assigns the last DAC to ports E or F in order to support notebooks
+with docking in earlier days, around ALSA 1.0.19 - 21.  This is not
+necessary now and actually breaks some configurations that use these
+ports as other devices.  This have been tested on several different
+configurations to make sure that it is working for different combinations.
+
+Signed-off-by: Charles Chin <Charles.Chin@idt.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_sigmatel.c |   18 ------------------
+ 1 file changed, 18 deletions(-)
+
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -5585,9 +5585,7 @@ static void stac92hd8x_fill_auto_spec(st
+ static int patch_stac92hd83xxx(struct hda_codec *codec)
+ {
+       struct sigmatel_spec *spec;
+-      hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
+       int err;
+-      int num_dacs;
+       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+@@ -5689,22 +5687,6 @@ again:
+               return err;
+       }
+-      /* docking output support */
+-      num_dacs = snd_hda_get_connections(codec, 0xF,
+-                              conn, STAC92HD83_DAC_COUNT + 1) - 1;
+-      /* skip non-DAC connections */
+-      while (num_dacs >= 0 &&
+-                      (get_wcaps_type(get_wcaps(codec, conn[num_dacs]))
+-                                      != AC_WID_AUD_OUT))
+-              num_dacs--;
+-      /* set port E and F to select the last DAC */
+-      if (num_dacs >= 0) {
+-              snd_hda_codec_write_cache(codec, 0xE, 0,
+-                      AC_VERB_SET_CONNECT_SEL, num_dacs);
+-              snd_hda_codec_write_cache(codec, 0xF, 0,
+-                      AC_VERB_SET_CONNECT_SEL, num_dacs);
+-      }
+-
+       codec->proc_widget_hook = stac92hd_proc_hook;
+       return 0;
diff --git a/queue-3.1/epoll-fix-spurious-lockdep-warnings.patch b/queue-3.1/epoll-fix-spurious-lockdep-warnings.patch
new file mode 100644 (file)
index 0000000..51e63bc
--- /dev/null
@@ -0,0 +1,137 @@
+From d8805e633e054c816c47cb6e727c81f156d9253d Mon Sep 17 00:00:00 2001
+From: Nelson Elhage <nelhage@nelhage.com>
+Date: Mon, 31 Oct 2011 17:13:14 -0700
+Subject: epoll: fix spurious lockdep warnings
+
+From: Nelson Elhage <nelhage@nelhage.com>
+
+commit d8805e633e054c816c47cb6e727c81f156d9253d upstream.
+
+epoll can acquire recursively acquire ep->mtx on multiple "struct
+eventpoll"s at once in the case where one epoll fd is monitoring another
+epoll fd.  This is perfectly OK, since we're careful about the lock
+ordering, but it causes spurious lockdep warnings.  Annotate the recursion
+using mutex_lock_nested, and add a comment explaining the nesting rules
+for good measure.
+
+Recent versions of systemd are triggering this, and it can also be
+demonstrated with the following trivial test program:
+
+--------------------8<--------------------
+
+int main(void) {
+   int e1, e2;
+   struct epoll_event evt = {
+       .events = EPOLLIN
+   };
+
+   e1 = epoll_create1(0);
+   e2 = epoll_create1(0);
+   epoll_ctl(e1, EPOLL_CTL_ADD, e2, &evt);
+   return 0;
+}
+--------------------8<--------------------
+
+Reported-by: Paul Bolle <pebolle@tiscali.nl>
+Tested-by: Paul Bolle <pebolle@tiscali.nl>
+Signed-off-by: Nelson Elhage <nelhage@nelhage.com>
+Acked-by: Jason Baron <jbaron@redhat.com>
+Cc: Dave Jones <davej@redhat.com>
+Cc: Davide Libenzi <davidel@xmailserver.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/eventpoll.c |   25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -70,6 +70,15 @@
+  * simultaneous inserts (A into B and B into A) from racing and
+  * constructing a cycle without either insert observing that it is
+  * going to.
++ * It is necessary to acquire multiple "ep->mtx"es at once in the
++ * case when one epoll fd is added to another. In this case, we
++ * always acquire the locks in the order of nesting (i.e. after
++ * epoll_ctl(e1, EPOLL_CTL_ADD, e2), e1->mtx will always be acquired
++ * before e2->mtx). Since we disallow cycles of epoll file
++ * descriptors, this ensures that the mutexes are well-ordered. In
++ * order to communicate this nesting to lockdep, when walking a tree
++ * of epoll file descriptors, we use the current recursion depth as
++ * the lockdep subkey.
+  * It is possible to drop the "ep->mtx" and to use the global
+  * mutex "epmutex" (together with "ep->lock") to have it working,
+  * but having "ep->mtx" will make the interface more scalable.
+@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struc
+  * @ep: Pointer to the epoll private data structure.
+  * @sproc: Pointer to the scan callback.
+  * @priv: Private opaque data passed to the @sproc callback.
++ * @depth: The current depth of recursive f_op->poll calls.
+  *
+  * Returns: The same integer error code returned by the @sproc callback.
+  */
+ static int ep_scan_ready_list(struct eventpoll *ep,
+                             int (*sproc)(struct eventpoll *,
+                                          struct list_head *, void *),
+-                            void *priv)
++                            void *priv,
++                            int depth)
+ {
+       int error, pwake = 0;
+       unsigned long flags;
+@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eve
+        * We need to lock this because we could be hit by
+        * eventpoll_release_file() and epoll_ctl().
+        */
+-      mutex_lock(&ep->mtx);
++      mutex_lock_nested(&ep->mtx, depth);
+       /*
+        * Steal the ready list, and re-init the original one to the
+@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct ev
+ static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests)
+ {
+-      return ep_scan_ready_list(priv, ep_read_events_proc, NULL);
++      return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1);
+ }
+ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
+@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file
+               ep = epi->ep;
+               list_del_init(&epi->fllink);
+-              mutex_lock(&ep->mtx);
++              mutex_lock_nested(&ep->mtx, 0);
+               ep_remove(ep, epi);
+               mutex_unlock(&ep->mtx);
+       }
+@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpo
+       esed.maxevents = maxevents;
+       esed.events = events;
+-      return ep_scan_ready_list(ep, ep_send_events_proc, &esed);
++      return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0);
+ }
+ static inline struct timespec ep_set_mstimeout(long ms)
+@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv
+       struct rb_node *rbp;
+       struct epitem *epi;
+-      mutex_lock(&ep->mtx);
++      mutex_lock_nested(&ep->mtx, call_nests + 1);
+       for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
+               epi = rb_entry(rbp, struct epitem, rbn);
+               if (unlikely(is_file_epoll(epi->ffd.file))) {
+@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in
+       }
+-      mutex_lock(&ep->mtx);
++      mutex_lock_nested(&ep->mtx, 0);
+       /*
+        * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
diff --git a/queue-3.1/ipr-always-initiate-hard-reset-in-kdump-kernel.patch b/queue-3.1/ipr-always-initiate-hard-reset-in-kdump-kernel.patch
new file mode 100644 (file)
index 0000000..30a4559
--- /dev/null
@@ -0,0 +1,38 @@
+From 5d7c20b7fa5c6ca19e871b4050e321c99d32bd43 Mon Sep 17 00:00:00 2001
+From: Anton Blanchard <anton@samba.org>
+Date: Mon, 1 Aug 2011 19:43:45 +1000
+Subject: [SCSI] ipr: Always initiate hard reset in kdump kernel
+
+From: Anton Blanchard <anton@samba.org>
+
+commit 5d7c20b7fa5c6ca19e871b4050e321c99d32bd43 upstream.
+
+During kdump testing I noticed timeouts when initialising each IPR
+adapter. While the driver has logic to detect an adapter in an
+indeterminate state, it wasn't triggering and each adapter went
+through a 5 minute timeout before finally going operational.
+
+Some analysis showed the needs_hard_reset flag wasn't getting set.
+We can check the reset_devices kernel parameter which is set by
+kdump and force a full reset. This fixes the problem.
+
+Signed-off-by: Anton Blanchard <anton@samba.org>
+Acked-by: Brian King <brking@linux.vnet.ibm.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/ipr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -8812,7 +8812,7 @@ static int __devinit ipr_probe_ioa(struc
+       uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg32);
+       if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
+               ioa_cfg->needs_hard_reset = 1;
+-      if (interrupts & IPR_PCII_ERROR_INTERRUPTS)
++      if ((interrupts & IPR_PCII_ERROR_INTERRUPTS) || reset_devices)
+               ioa_cfg->needs_hard_reset = 1;
+       if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
+               ioa_cfg->ioa_unit_checked = 1;
diff --git a/queue-3.1/isci-fix-missed-unlock-in-apc_agent_timeout.patch b/queue-3.1/isci-fix-missed-unlock-in-apc_agent_timeout.patch
new file mode 100644 (file)
index 0000000..6029ed3
--- /dev/null
@@ -0,0 +1,33 @@
+From 983d3fdd332742167d0482c06fd29cf4b8a687c0 Mon Sep 17 00:00:00 2001
+From: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
+Date: Wed, 28 Sep 2011 18:35:32 -0700
+Subject: [SCSI] isci: fix missed unlock in apc_agent_timeout()
+
+From: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
+
+commit 983d3fdd332742167d0482c06fd29cf4b8a687c0 upstream.
+
+Needed to jump to scic_lock unlock.
+
+Also spotted by coccicheck.
+
+Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/isci/port_config.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/isci/port_config.c
++++ b/drivers/scsi/isci/port_config.c
+@@ -678,7 +678,7 @@ static void apc_agent_timeout(unsigned l
+       configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
+       if (!configure_phy_mask)
+-              return;
++              goto done;
+       for (index = 0; index < SCI_MAX_PHYS; index++) {
+               if ((configure_phy_mask & (1 << index)) == 0)
diff --git a/queue-3.1/isci-fix-support-for-large-smp-requests.patch b/queue-3.1/isci-fix-support-for-large-smp-requests.patch
new file mode 100644 (file)
index 0000000..9796e53
--- /dev/null
@@ -0,0 +1,146 @@
+From 54b5e3a4bfa3452bc10cd4da672099ccc46b8c09 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 28 Sep 2011 18:35:27 -0700
+Subject: [SCSI] isci: fix support for large smp requests
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 54b5e3a4bfa3452bc10cd4da672099ccc46b8c09 upstream.
+
+Kill the local smp response buffer.
+
+Besides being unnecessary, it is too small (currently truncates
+responses to 60 bytes).  The mid-layer will have already allocated a
+sufficiently sized buffer, just kmap and copy into it directly.
+
+Reported-by: Derick Marks <derick.w.marks@intel.com>
+Tested-by: Derick Marks <derick.w.marks@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/isci/isci.h    |    2 -
+ drivers/scsi/isci/request.c |   49 +++++++++++++++++---------------------------
+ drivers/scsi/isci/request.h |    3 --
+ drivers/scsi/isci/sas.h     |    2 -
+ 4 files changed, 21 insertions(+), 35 deletions(-)
+
+--- a/drivers/scsi/isci/isci.h
++++ b/drivers/scsi/isci/isci.h
+@@ -97,7 +97,7 @@
+ #define SCU_MAX_COMPLETION_QUEUE_SHIFT          (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
+ #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
+-#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024)
++#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE   (1024U)
+ #define SCU_INVALID_FRAME_INDEX             (0xFFFF)
+ #define SCU_IO_REQUEST_MAX_SGE_SIZE         (0x00FFFFFF)
+--- a/drivers/scsi/isci/request.c
++++ b/drivers/scsi/isci/request.c
+@@ -1490,29 +1490,30 @@ sci_io_request_frame_handler(struct isci
+               return SCI_SUCCESS;
+       case SCI_REQ_SMP_WAIT_RESP: {
+-              struct smp_resp *rsp_hdr = &ireq->smp.rsp;
+-              void *frame_header;
++              struct sas_task *task = isci_request_access_task(ireq);
++              struct scatterlist *sg = &task->smp_task.smp_resp;
++              void *frame_header, *kaddr;
++              u8 *rsp;
+               sci_unsolicited_frame_control_get_header(&ihost->uf_control,
+-                                                            frame_index,
+-                                                            &frame_header);
+-
+-              /* byte swap the header. */
+-              word_cnt = SMP_RESP_HDR_SZ / sizeof(u32);
+-              sci_swab32_cpy(rsp_hdr, frame_header, word_cnt);
++                                                       frame_index,
++                                                       &frame_header);
++              kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
++              rsp = kaddr + sg->offset;
++              sci_swab32_cpy(rsp, frame_header, 1);
+-              if (rsp_hdr->frame_type == SMP_RESPONSE) {
++              if (rsp[0] == SMP_RESPONSE) {
+                       void *smp_resp;
+                       sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
+-                                                                    frame_index,
+-                                                                    &smp_resp);
+-
+-                      word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) /
+-                              sizeof(u32);
++                                                               frame_index,
++                                                               &smp_resp);
+-                      sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ,
+-                                     smp_resp, word_cnt);
++                      word_cnt = (sg->length/4)-1;
++                      if (word_cnt > 0)
++                              word_cnt = min_t(unsigned int, word_cnt,
++                                               SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4);
++                      sci_swab32_cpy(rsp + 4, smp_resp, word_cnt);
+                       ireq->scu_status = SCU_TASK_DONE_GOOD;
+                       ireq->sci_status = SCI_SUCCESS;
+@@ -1528,12 +1529,13 @@ sci_io_request_frame_handler(struct isci
+                               __func__,
+                               ireq,
+                               frame_index,
+-                              rsp_hdr->frame_type);
++                              rsp[0]);
+                       ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR;
+                       ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
+                       sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+               }
++              kunmap_atomic(kaddr, KM_IRQ0);
+               sci_controller_release_frame(ihost, frame_index);
+@@ -2603,18 +2605,7 @@ static void isci_request_io_request_comp
+                       status   = SAM_STAT_GOOD;
+                       set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+-                      if (task->task_proto == SAS_PROTOCOL_SMP) {
+-                              void *rsp = &request->smp.rsp;
+-
+-                              dev_dbg(&ihost->pdev->dev,
+-                                      "%s: SMP protocol completion\n",
+-                                      __func__);
+-
+-                              sg_copy_from_buffer(
+-                                      &task->smp_task.smp_resp, 1,
+-                                      rsp, sizeof(struct smp_resp));
+-                      } else if (completion_status
+-                                 == SCI_IO_SUCCESS_IO_DONE_EARLY) {
++                      if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
+                               /* This was an SSP / STP / SATA transfer.
+                                * There is a possibility that less data than
+--- a/drivers/scsi/isci/request.h
++++ b/drivers/scsi/isci/request.h
+@@ -174,9 +174,6 @@ struct isci_request {
+                       };
+               } ssp;
+               struct {
+-                      struct smp_resp rsp;
+-              } smp;
+-              struct {
+                       struct isci_stp_request req;
+                       struct host_to_dev_fis cmd;
+                       struct dev_to_host_fis rsp;
+--- a/drivers/scsi/isci/sas.h
++++ b/drivers/scsi/isci/sas.h
+@@ -204,8 +204,6 @@ struct smp_req {
+       u8 req_data[0];
+ }  __packed;
+-#define SMP_RESP_HDR_SZ       4
+-
+ /*
+  * struct sci_sas_address - This structure depicts how a SAS address is
+  *    represented by SCI.
diff --git a/queue-3.1/leds-save-the-delay-values-after-a-successful-call-to-blink_set.patch b/queue-3.1/leds-save-the-delay-values-after-a-successful-call-to-blink_set.patch
new file mode 100644 (file)
index 0000000..6f1b5bd
--- /dev/null
@@ -0,0 +1,71 @@
+From 6123b0e274503a0d3588e84fbe07c9aa01bfaf5d Mon Sep 17 00:00:00 2001
+From: Antonio Ospite <ospite@studenti.unina.it>
+Date: Mon, 31 Oct 2011 17:12:19 -0700
+Subject: leds: save the delay values after a successful call to blink_set()
+
+From: Antonio Ospite <ospite@studenti.unina.it>
+
+commit 6123b0e274503a0d3588e84fbe07c9aa01bfaf5d upstream.
+
+When calling the hardware blinking function implemented by blink_set(),
+the delay_on and delay_off values are not preserved across calls.
+
+Fix that and make the "timer" trigger work as expected when hardware
+blinking is available.
+
+BEFORE the fix:
+  $ cd /sys/class/leds/someled
+  $ echo timer > trigger
+  $ cat delay_on delay_off
+  0
+  0
+  $ echo 100 > delay_on
+  $ cat delay_on delay_off
+  0
+  0
+  $ echo 100 > delay_off
+  $ cat delay_on delay_off
+  0
+  0
+
+AFTER the fix:
+  $ cd /sys/class/leds/someled
+  $ echo timer > trigger
+  $ cat delay_on delay_off
+  0
+  0
+  $ echo 100 > delay_on
+  $ cat delay_on delay_off
+  100
+  0
+  $ echo 100 > delay_off
+  $ cat delay_on delay_off
+  100
+  100
+
+Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
+Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
+Cc: Richard Purdie <rpurdie@rpsys.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/leds/led-class.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -268,8 +268,11 @@ void led_blink_set(struct led_classdev *
+                  unsigned long *delay_off)
+ {
+       if (led_cdev->blink_set &&
+-          !led_cdev->blink_set(led_cdev, delay_on, delay_off))
++          !led_cdev->blink_set(led_cdev, delay_on, delay_off)) {
++              led_cdev->blink_delay_on = *delay_on;
++              led_cdev->blink_delay_off = *delay_off;
+               return;
++      }
+       /* blink with 1 Hz as default if nothing specified */
+       if (!*delay_on && !*delay_off)
diff --git a/queue-3.1/leds-turn-the-blink_timer-off-before-starting-to-blink.patch b/queue-3.1/leds-turn-the-blink_timer-off-before-starting-to-blink.patch
new file mode 100644 (file)
index 0000000..8014a09
--- /dev/null
@@ -0,0 +1,46 @@
+From 488bc35bf40df89d37486c1826b178a2fba36ce7 Mon Sep 17 00:00:00 2001
+From: Antonio Ospite <ospite@studenti.unina.it>
+Date: Mon, 31 Oct 2011 17:12:22 -0700
+Subject: leds: turn the blink_timer off before starting to blink
+
+From: Antonio Ospite <ospite@studenti.unina.it>
+
+commit 488bc35bf40df89d37486c1826b178a2fba36ce7 upstream.
+
+Depending on the implementation of the hardware blinking function in
+blink_set(), the led can support hardware blinking for some values of
+delay_on and delay_off and fall-back to software blinking for some other
+values.
+
+Turning off the blink_timer unconditionally before starting to blink
+make sure that a sequence like:
+
+  OFF
+  hardware blinking
+  software blinking
+  hardware blinking
+
+does not leave the software blinking timer active.
+
+Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
+Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
+Cc: Richard Purdie <rpurdie@rpsys.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/leds/led-class.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -267,6 +267,8 @@ void led_blink_set(struct led_classdev *
+                  unsigned long *delay_on,
+                  unsigned long *delay_off)
+ {
++      del_timer_sync(&led_cdev->blink_timer);
++
+       if (led_cdev->blink_set &&
+           !led_cdev->blink_set(led_cdev, delay_on, delay_off)) {
+               led_cdev->blink_delay_on = *delay_on;
diff --git a/queue-3.1/libsas-set-sas_address-and-device-type-of-rphy.patch b/queue-3.1/libsas-set-sas_address-and-device-type-of-rphy.patch
new file mode 100644 (file)
index 0000000..3690afc
--- /dev/null
@@ -0,0 +1,32 @@
+From bb041a0e9c31229071b6e56e1d0d8374af0d2038 Mon Sep 17 00:00:00 2001
+From: Jack Wang <jack_wang@usish.com>
+Date: Fri, 23 Sep 2011 14:32:32 +0800
+Subject: [SCSI] libsas: set sas_address and device type of rphy
+
+From: Jack Wang <jack_wang@usish.com>
+
+commit bb041a0e9c31229071b6e56e1d0d8374af0d2038 upstream.
+
+Libsas forget to set the sas_address and device type of rphy lead to file
+under /sys/class/sas_x show wrong value, fix that.
+
+Signed-off-by: Jack Wang <jack_wang@usish.com>
+Tested-by: Crystal Yu <crystal_yu@usish.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/libsas/sas_expander.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/scsi/libsas/sas_expander.c
++++ b/drivers/scsi/libsas/sas_expander.c
+@@ -199,6 +199,8 @@ static void sas_set_ex_phy(struct domain
+       phy->virtual = dr->virtual;
+       phy->last_da_index = -1;
++      phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
++      phy->phy->identify.device_type = phy->attached_dev_type;
+       phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
+       phy->phy->identify.target_port_protocols = phy->attached_tproto;
+       phy->phy->identify.phy_identifier = phy_id;
diff --git a/queue-3.1/megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch b/queue-3.1/megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch
new file mode 100644 (file)
index 0000000..0d48755
--- /dev/null
@@ -0,0 +1,45 @@
+From f575c5d3ebdca3b0482847d8fcba971767754a9e Mon Sep 17 00:00:00 2001
+From: adam radford <aradford@gmail.com>
+Date: Thu, 13 Oct 2011 16:01:12 -0700
+Subject: [SCSI] megaraid_sas: Fix instance access in megasas_reset_timer
+
+From: adam radford <aradford@gmail.com>
+
+commit f575c5d3ebdca3b0482847d8fcba971767754a9e upstream.
+
+The following patch for megaraid_sas will fix a potential bad pointer access
+in megasas_reset_timer(), when a MegaRAID 9265/9285 or 9360/9380 gets a
+timeout.  megasas_build_io_fusion() sets SCp.ptr to be a struct
+megasas_cmd_fusion *, but then megasas_reset_timer() was casting SCp.ptr to be
+a struct megasas_cmd *, then trying to access cmd->instance, which is invalid.
+
+Just loading instance from scmd->device->host->hostdata in
+megasas_reset_timer() fixes the issue.
+
+Signed-off-by: Adam Radford <aradford@gmail.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1907,7 +1907,6 @@ static int megasas_generic_reset(struct
+ static enum
+ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+ {
+-      struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+       struct megasas_instance *instance;
+       unsigned long flags;
+@@ -1916,7 +1915,7 @@ blk_eh_timer_return megasas_reset_timer(
+               return BLK_EH_NOT_HANDLED;
+       }
+-      instance = cmd->instance;
++      instance = (struct megasas_instance *)scmd->device->host->hostdata;
+       if (!(instance->flag & MEGASAS_FW_BUSY)) {
+               /* FW is busy, throttle IO */
+               spin_lock_irqsave(instance->host->host_lock, flags);
index 3f0d2746a4221f48095387451870db2ed1c87732..30332d886de6ea9bf92c4aeff564c53b70a76f55 100644 (file)
@@ -28,3 +28,22 @@ drm-radeon-kms-fix-i2c-mask-definitions.patch
 mmc-core-fix-hangs-related-to-insert-remove-of-cards.patch
 mmc-core-ext_csd.raw_-used-in-comparison-but-never-set.patch
 pci-quirk-mmc-always-check-for-lower-base-frequency-quirk-for-ricoh-1180-e823.patch
+megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch
+ipr-always-initiate-hard-reset-in-kdump-kernel.patch
+libsas-set-sas_address-and-device-type-of-rphy.patch
+isci-fix-support-for-large-smp-requests.patch
+isci-fix-missed-unlock-in-apc_agent_timeout.patch
+alsa-hda-remove-bad-code-for-idt-92hd83-family-patch.patch
+alsa-hda-keep-eapd-turned-on-for-old-conexant-chips.patch
+alsa-hda-add-new-revision-for-alc662.patch
+target-prevent-cmd-se_queue_node-double-add.patch
+target-fix-transport_cmd_finish_abort-queue-removal-bug.patch
+target-prevent-transport_send_task_abort-when-check_condition-status.patch
+target-prevent-transport_free_cmd_intr-processing-in-core_tmr_drain_cmd_list.patch
+target-fix-report-target-port-groups-handling-with-small-allocation-length.patch
+x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch
+x86-fix-compilation-bug-in-kprobes-twobyte_is_boostable.patch
+epoll-fix-spurious-lockdep-warnings.patch
+leds-save-the-delay-values-after-a-successful-call-to-blink_set.patch
+leds-turn-the-blink_timer-off-before-starting-to-blink.patch
+target-re-org-of-core_tmr_lun_reset.patch
diff --git a/queue-3.1/target-fix-report-target-port-groups-handling-with-small-allocation-length.patch b/queue-3.1/target-fix-report-target-port-groups-handling-with-small-allocation-length.patch
new file mode 100644 (file)
index 0000000..9e3f2c0
--- /dev/null
@@ -0,0 +1,65 @@
+From 6b20fa9aaf0c2f69ee6f9648e20ab2be0206705e Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Tue, 18 Oct 2011 23:48:04 -0700
+Subject: target: Fix REPORT TARGET PORT GROUPS handling with small allocation length
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 6b20fa9aaf0c2f69ee6f9648e20ab2be0206705e upstream.
+
+This patch fixes a bug with the handling of REPORT TARGET PORT GROUPS
+containing a smaller allocation length than the payload requires causing
+memory writes beyond the end of the buffer.  This patch checks for the
+minimum 4 byte length for the response payload length, and also checks
+upon each loop of T10_ALUA(su_dev)->tg_pt_gps_list to ensure the Target
+port group and Target port descriptor list is able to fit into the
+remaining allocation length.
+
+If the response payload exceeds the allocation length length, then rd_len
+is still increments to indicate to the initiator that the payload has
+been truncated.
+
+Reported-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_alua.c |   20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/target/target_core_alua.c
++++ b/drivers/target/target_core_alua.c
+@@ -68,6 +68,15 @@ int core_emulate_report_target_port_grou
+       unsigned char *buf;
+       u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
+                                   Target port group descriptor */
++      /*
++       * Need at least 4 bytes of response data or else we can't
++       * even fit the return data length.
++       */
++      if (cmd->data_length < 4) {
++              pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
++                      " too small\n", cmd->data_length);
++              return -EINVAL;
++      }
+       buf = transport_kmap_first_data_page(cmd);
+@@ -75,6 +84,17 @@ int core_emulate_report_target_port_grou
+       list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
+                       tg_pt_gp_list) {
+               /*
++               * Check if the Target port group and Target port descriptor list
++               * based on tg_pt_gp_members count will fit into the response payload.
++               * Otherwise, bump rd_len to let the initiator know we have exceeded
++               * the allocation length and the response is truncated.
++               */
++              if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) >
++                   cmd->data_length) {
++                      rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4);
++                      continue;
++              }
++              /*
+                * PREF: Preferred target port bit, determine if this
+                * bit should be set for port group.
+                */
diff --git a/queue-3.1/target-fix-transport_cmd_finish_abort-queue-removal-bug.patch b/queue-3.1/target-fix-transport_cmd_finish_abort-queue-removal-bug.patch
new file mode 100644 (file)
index 0000000..7b2376e
--- /dev/null
@@ -0,0 +1,42 @@
+From 77039d1eafbbc192df71ee84b157b8973766737d Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Thu, 29 Sep 2011 01:01:35 -0700
+Subject: target: Fix transport_cmd_finish_abort queue removal bug
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 77039d1eafbbc192df71ee84b157b8973766737d upstream.
+
+This patch fixes a bug in LUN_RESET operation with transport_cmd_finish_abort()
+where transport_remove_cmd_from_queue() was incorrectly being called, causing
+descriptors with t_state == TRANSPORT_FREE_CMD_INTR to be incorrectly removed
+from qobj->qobj_list during process context release.  This change ensures the
+descriptor is only removed via transport_remove_cmd_from_queue() when doing a
+direct release via transport_generic_remove().
+
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_transport.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -594,13 +594,14 @@ check_lun:
+ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
+ {
+-      transport_remove_cmd_from_queue(cmd, &cmd->se_dev->dev_queue_obj);
+       transport_lun_remove_cmd(cmd);
+       if (transport_cmd_check_stop_to_fabric(cmd))
+               return;
+-      if (remove)
++      if (remove) {
++              transport_remove_cmd_from_queue(cmd, &cmd->se_dev->dev_queue_obj);
+               transport_generic_remove(cmd, 0);
++      }
+ }
+ void transport_cmd_finish_abort_tmr(struct se_cmd *cmd)
diff --git a/queue-3.1/target-prevent-cmd-se_queue_node-double-add.patch b/queue-3.1/target-prevent-cmd-se_queue_node-double-add.patch
new file mode 100644 (file)
index 0000000..07760d1
--- /dev/null
@@ -0,0 +1,140 @@
+From 79a7fef26431830e22e282053d050af790117db8 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Wed, 28 Sep 2011 22:12:07 -0700
+Subject: target: Prevent cmd->se_queue_node double add
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit 79a7fef26431830e22e282053d050af790117db8 upstream.
+
+This patch addresses a bug with the lio-core-2.6.git conversion of
+transport_add_cmd_to_queue() to use a single embedded list_head, instead
+of individual struct se_queue_req allocations allowing a single se_cmd to
+be added to the queue mulitple times.  This was changed in the following:
+
+commit 2a9e4d5ca5d99f4c600578d6285d45142e7e5208
+Author: Andy Grover <agrover@redhat.com>
+Date:   Tue Apr 26 17:45:51 2011 -0700
+
+    target: Embed qr in struct se_cmd
+
+The problem is that some target code still assumes performing multiple
+adds is allowed via transport_add_cmd_to_queue(), which ends up causing
+list corruption in qobj->qobj_list code.  This patch addresses this
+by removing an existing struct se_cmd from the list before the add, and
+removes an unnecessary list walk in transport_remove_cmd_from_queue()
+
+It also changes cmd->t_transport_queue_active to use explict sets intead
+of increment/decrement to prevent confusion during exception path handling.
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Cc: Andy Grover <agrover@redhat.com>
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_tmr.c       |    2 +-
+ drivers/target/target_core_transport.c |   31 +++++++++++++++----------------
+ 2 files changed, 16 insertions(+), 17 deletions(-)
+
+--- a/drivers/target/target_core_tmr.c
++++ b/drivers/target/target_core_tmr.c
+@@ -340,7 +340,7 @@ int core_tmr_lun_reset(
+               atomic_dec(&cmd->t_transport_queue_active);
+               atomic_dec(&qobj->queue_cnt);
+-              list_del(&cmd->se_queue_node);
++              list_del_init(&cmd->se_queue_node);
+               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+               pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -621,8 +621,6 @@ static void transport_add_cmd_to_queue(
+       struct se_queue_obj *qobj = &dev->dev_queue_obj;
+       unsigned long flags;
+-      INIT_LIST_HEAD(&cmd->se_queue_node);
+-
+       if (t_state) {
+               spin_lock_irqsave(&cmd->t_state_lock, flags);
+               cmd->t_state = t_state;
+@@ -631,15 +629,21 @@ static void transport_add_cmd_to_queue(
+       }
+       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
++
++      /* If the cmd is already on the list, remove it before we add it */
++      if (!list_empty(&cmd->se_queue_node))
++              list_del(&cmd->se_queue_node);
++      else
++              atomic_inc(&qobj->queue_cnt);
++
+       if (cmd->se_cmd_flags & SCF_EMULATE_QUEUE_FULL) {
+               cmd->se_cmd_flags &= ~SCF_EMULATE_QUEUE_FULL;
+               list_add(&cmd->se_queue_node, &qobj->qobj_list);
+       } else
+               list_add_tail(&cmd->se_queue_node, &qobj->qobj_list);
+-      atomic_inc(&cmd->t_transport_queue_active);
++      atomic_set(&cmd->t_transport_queue_active, 1);
+       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+-      atomic_inc(&qobj->queue_cnt);
+       wake_up_interruptible(&qobj->thread_wq);
+ }
+@@ -656,9 +660,9 @@ transport_get_cmd_from_queue(struct se_q
+       }
+       cmd = list_first_entry(&qobj->qobj_list, struct se_cmd, se_queue_node);
+-      atomic_dec(&cmd->t_transport_queue_active);
++      atomic_set(&cmd->t_transport_queue_active, 0);
+-      list_del(&cmd->se_queue_node);
++      list_del_init(&cmd->se_queue_node);
+       atomic_dec(&qobj->queue_cnt);
+       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+@@ -668,7 +672,6 @@ transport_get_cmd_from_queue(struct se_q
+ static void transport_remove_cmd_from_queue(struct se_cmd *cmd,
+               struct se_queue_obj *qobj)
+ {
+-      struct se_cmd *t;
+       unsigned long flags;
+       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
+@@ -676,14 +679,9 @@ static void transport_remove_cmd_from_qu
+               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+               return;
+       }
+-
+-      list_for_each_entry(t, &qobj->qobj_list, se_queue_node)
+-              if (t == cmd) {
+-                      atomic_dec(&cmd->t_transport_queue_active);
+-                      atomic_dec(&qobj->queue_cnt);
+-                      list_del(&cmd->se_queue_node);
+-                      break;
+-              }
++      atomic_set(&cmd->t_transport_queue_active, 0);
++      atomic_dec(&qobj->queue_cnt);
++      list_del_init(&cmd->se_queue_node);
+       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+       if (atomic_read(&cmd->t_transport_queue_active)) {
+@@ -1067,7 +1065,7 @@ static void transport_release_all_cmds(s
+       list_for_each_entry_safe(cmd, tcmd, &dev->dev_queue_obj.qobj_list,
+                               se_queue_node) {
+               t_state = cmd->t_state;
+-              list_del(&cmd->se_queue_node);
++              list_del_init(&cmd->se_queue_node);
+               spin_unlock_irqrestore(&dev->dev_queue_obj.cmd_queue_lock,
+                               flags);
+@@ -1598,6 +1596,7 @@ void transport_init_se_cmd(
+       INIT_LIST_HEAD(&cmd->se_delayed_node);
+       INIT_LIST_HEAD(&cmd->se_ordered_node);
+       INIT_LIST_HEAD(&cmd->se_qf_node);
++      INIT_LIST_HEAD(&cmd->se_queue_node);
+       INIT_LIST_HEAD(&cmd->t_task_list);
+       init_completion(&cmd->transport_lun_fe_stop_comp);
diff --git a/queue-3.1/target-prevent-transport_free_cmd_intr-processing-in-core_tmr_drain_cmd_list.patch b/queue-3.1/target-prevent-transport_free_cmd_intr-processing-in-core_tmr_drain_cmd_list.patch
new file mode 100644 (file)
index 0000000..cf6a653
--- /dev/null
@@ -0,0 +1,42 @@
+From b0e062aec578c756d1aea4b5809294488366a6e8 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Tue, 11 Oct 2011 06:02:48 +0000
+Subject: target: Prevent TRANSPORT_FREE_CMD_INTR processing in core_tmr_drain_cmd_list
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit b0e062aec578c756d1aea4b5809294488366a6e8 upstream.
+
+This patch contains a bugfix for TMR LUN_RESET related to TRANSPORT_FREE_CMD_INTR
+operation, where core_tmr_drain_cmd_list() will now skip processing for this
+case to prevent an ABORT_TASK status from being returned for descriptors that
+are already queued up to be released by processing thread context.
+
+Cc: Roland Dreier <roland@purestorage.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_tmr.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/target/target_core_tmr.c
++++ b/drivers/target/target_core_tmr.c
+@@ -337,6 +337,16 @@ int core_tmr_lun_reset(
+                */
+               if (prout_cmd == cmd)
+                       continue;
++              /*
++               * Skip direct processing of TRANSPORT_FREE_CMD_INTR for
++               * HW target mode fabrics.
++               */
++              spin_lock(&cmd->t_state_lock);
++              if (cmd->t_state == TRANSPORT_FREE_CMD_INTR) {
++                      spin_unlock(&cmd->t_state_lock);
++                      continue;
++              }
++              spin_unlock(&cmd->t_state_lock);
+               atomic_dec(&cmd->t_transport_queue_active);
+               atomic_dec(&qobj->queue_cnt);
diff --git a/queue-3.1/target-prevent-transport_send_task_abort-when-check_condition-status.patch b/queue-3.1/target-prevent-transport_send_task_abort-when-check_condition-status.patch
new file mode 100644 (file)
index 0000000..6215cd0
--- /dev/null
@@ -0,0 +1,39 @@
+From c252f003470a99d319db4ebd12f4a9e4710a65db Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Thu, 29 Sep 2011 14:22:13 -0700
+Subject: target: Prevent transport_send_task_abort when CHECK_CONDITION status
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit c252f003470a99d319db4ebd12f4a9e4710a65db upstream.
+
+This patch fixes a bug where transport_send_task_abort() could be called
+during LUN_RESET to return SAM_STAT_TASK_ABORTED + tfo->queue_status(), when
+SCF_SENT_CHECK_CONDITION -> tfo->queue_status() has already been sent from
+within another context via transport_send_check_condition_and_sense().
+
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_transport.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -4920,6 +4920,15 @@ EXPORT_SYMBOL(transport_check_aborted_st
+ void transport_send_task_abort(struct se_cmd *cmd)
+ {
++      unsigned long flags;
++
++      spin_lock_irqsave(&cmd->t_state_lock, flags);
++      if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
++              spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++              return;
++      }
++      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+       /*
+        * If there are still expected incoming fabric WRITEs, we wait
+        * until until they have completed before sending a TASK_ABORTED
diff --git a/queue-3.1/target-re-org-of-core_tmr_lun_reset.patch b/queue-3.1/target-re-org-of-core_tmr_lun_reset.patch
new file mode 100644 (file)
index 0000000..8b9d1e8
--- /dev/null
@@ -0,0 +1,338 @@
+From d050ffb922c782f092234611b9019e95024481ab Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Wed, 28 Sep 2011 21:37:29 -0700
+Subject: target: Re-org of core_tmr_lun_reset
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit d050ffb922c782f092234611b9019e95024481ab upstream.
+
+This patch is a re-orginzation of core_tmr_lun_reset() logic to properly
+scan the active tmr_list, dev->state_task_list and qobj->qobj_list w/ the
+relivent locks held, and performing a list_move_tail onto seperate local
+scope lists before performing the full drain.
+
+This involves breaking out the code into three seperate list specific
+functions: core_tmr_drain_tmr_list(), core_tmr_drain_task_list() and
+core_tmr_drain_cmd_list().
+
+(nab: Include target: Remove non-active tasks from execute list during
+      LUN_RESET patch to address original breakage)
+
+Reported-by: Roland Dreier <roland@purestorage.com>
+Cc: Roland Dreier <roland@purestorage.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/target/target_core_tmr.c |  197 ++++++++++++++++++++++++---------------
+ 1 file changed, 125 insertions(+), 72 deletions(-)
+
+--- a/drivers/target/target_core_tmr.c
++++ b/drivers/target/target_core_tmr.c
+@@ -67,15 +67,16 @@ void core_tmr_release_req(
+       struct se_tmr_req *tmr)
+ {
+       struct se_device *dev = tmr->tmr_dev;
++      unsigned long flags;
+       if (!dev) {
+               kmem_cache_free(se_tmr_req_cache, tmr);
+               return;
+       }
+-      spin_lock_irq(&dev->se_tmr_lock);
++      spin_lock_irqsave(&dev->se_tmr_lock, flags);
+       list_del(&tmr->tmr_list);
+-      spin_unlock_irq(&dev->se_tmr_lock);
++      spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+       kmem_cache_free(se_tmr_req_cache, tmr);
+ }
+@@ -100,54 +101,20 @@ static void core_tmr_handle_tas_abort(
+       transport_cmd_finish_abort(cmd, 0);
+ }
+-int core_tmr_lun_reset(
++static void core_tmr_drain_tmr_list(
+       struct se_device *dev,
+       struct se_tmr_req *tmr,
+-      struct list_head *preempt_and_abort_list,
+-      struct se_cmd *prout_cmd)
++      struct list_head *preempt_and_abort_list)
+ {
+-      struct se_cmd *cmd, *tcmd;
+-      struct se_node_acl *tmr_nacl = NULL;
+-      struct se_portal_group *tmr_tpg = NULL;
+-      struct se_queue_obj *qobj = &dev->dev_queue_obj;
++      LIST_HEAD(drain_tmr_list);
+       struct se_tmr_req *tmr_p, *tmr_pp;
+-      struct se_task *task, *task_tmp;
++      struct se_cmd *cmd;
+       unsigned long flags;
+-      int fe_count, tas;
+-      /*
+-       * TASK_ABORTED status bit, this is configurable via ConfigFS
+-       * struct se_device attributes.  spc4r17 section 7.4.6 Control mode page
+-       *
+-       * A task aborted status (TAS) bit set to zero specifies that aborted
+-       * tasks shall be terminated by the device server without any response
+-       * to the application client. A TAS bit set to one specifies that tasks
+-       * aborted by the actions of an I_T nexus other than the I_T nexus on
+-       * which the command was received shall be completed with TASK ABORTED
+-       * status (see SAM-4).
+-       */
+-      tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
+-      /*
+-       * Determine if this se_tmr is coming from a $FABRIC_MOD
+-       * or struct se_device passthrough..
+-       */
+-      if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
+-              tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
+-              tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
+-              if (tmr_nacl && tmr_tpg) {
+-                      pr_debug("LUN_RESET: TMR caller fabric: %s"
+-                              " initiator port %s\n",
+-                              tmr_tpg->se_tpg_tfo->get_fabric_name(),
+-                              tmr_nacl->initiatorname);
+-              }
+-      }
+-      pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
+-              (preempt_and_abort_list) ? "Preempt" : "TMR",
+-              dev->transport->name, tas);
+       /*
+        * Release all pending and outgoing TMRs aside from the received
+        * LUN_RESET tmr..
+        */
+-      spin_lock_irq(&dev->se_tmr_lock);
++      spin_lock_irqsave(&dev->se_tmr_lock, flags);
+       list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
+               /*
+                * Allow the received TMR to return with FUNCTION_COMPLETE.
+@@ -169,29 +136,48 @@ int core_tmr_lun_reset(
+                   (core_scsi3_check_cdb_abort_and_preempt(
+                                       preempt_and_abort_list, cmd) != 0))
+                       continue;
+-              spin_unlock_irq(&dev->se_tmr_lock);
+-              spin_lock_irqsave(&cmd->t_state_lock, flags);
++              spin_lock(&cmd->t_state_lock);
+               if (!atomic_read(&cmd->t_transport_active)) {
+-                      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-                      spin_lock_irq(&dev->se_tmr_lock);
++                      spin_unlock(&cmd->t_state_lock);
+                       continue;
+               }
+               if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
+-                      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-                      spin_lock_irq(&dev->se_tmr_lock);
++                      spin_unlock(&cmd->t_state_lock);
+                       continue;
+               }
++              spin_unlock(&cmd->t_state_lock);
++
++              list_move_tail(&tmr->tmr_list, &drain_tmr_list);
++      }
++      spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
++
++      while (!list_empty(&drain_tmr_list)) {
++              tmr = list_entry(drain_tmr_list.next, struct se_tmr_req, tmr_list);
++              list_del(&tmr->tmr_list);
++              cmd = tmr_p->task_cmd;
++
+               pr_debug("LUN_RESET: %s releasing TMR %p Function: 0x%02x,"
+                       " Response: 0x%02x, t_state: %d\n",
+-                      (preempt_and_abort_list) ? "Preempt" : "", tmr_p,
+-                      tmr_p->function, tmr_p->response, cmd->t_state);
+-              spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++                      (preempt_and_abort_list) ? "Preempt" : "", tmr,
++                      tmr->function, tmr->response, cmd->t_state);
+               transport_cmd_finish_abort_tmr(cmd);
+-              spin_lock_irq(&dev->se_tmr_lock);
+       }
+-      spin_unlock_irq(&dev->se_tmr_lock);
++}
++
++static void core_tmr_drain_task_list(
++      struct se_device *dev,
++      struct se_cmd *prout_cmd,
++      struct se_node_acl *tmr_nacl,
++      int tas,
++      struct list_head *preempt_and_abort_list)
++{
++      LIST_HEAD(drain_task_list);
++      struct se_cmd *cmd;
++      struct se_task *task, *task_tmp;
++      unsigned long flags;
++      int fe_count;
+       /*
+        * Complete outstanding struct se_task CDBs with TASK_ABORTED SAM status.
+        * This is following sam4r17, section 5.6 Aborting commands, Table 38
+@@ -236,9 +222,23 @@ int core_tmr_lun_reset(
+               if (prout_cmd == cmd)
+                       continue;
+-              list_del(&task->t_state_list);
++              list_move_tail(&task->t_state_list, &drain_task_list);
+               atomic_set(&task->task_state_active, 0);
+-              spin_unlock_irqrestore(&dev->execute_task_lock, flags);
++              /*
++               * Remove from task execute list before processing drain_task_list
++               */
++              if (atomic_read(&task->task_execute_queue) != 0) {
++                      list_del(&task->t_execute_list);
++                      atomic_set(&task->task_execute_queue, 0);
++                      atomic_dec(&dev->execute_tasks);
++              }
++      }
++      spin_unlock_irqrestore(&dev->execute_task_lock, flags);
++
++      while (!list_empty(&drain_task_list)) {
++              task = list_entry(drain_task_list.next, struct se_task, t_state_list);
++              list_del(&task->t_state_list);
++              cmd = task->task_se_cmd;
+               spin_lock_irqsave(&cmd->t_state_lock, flags);
+               pr_debug("LUN_RESET: %s cmd: %p task: %p"
+@@ -275,20 +275,14 @@ int core_tmr_lun_reset(
+                       atomic_set(&task->task_active, 0);
+                       atomic_set(&task->task_stop, 0);
+-              } else {
+-                      if (atomic_read(&task->task_execute_queue) != 0)
+-                              transport_remove_task_from_execute_queue(task, dev);
+               }
+               __transport_stop_task_timer(task, &flags);
+               if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) {
+-                      spin_unlock_irqrestore(
+-                                      &cmd->t_state_lock, flags);
++                      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+                       pr_debug("LUN_RESET: Skipping task: %p, dev: %p for"
+                               " t_task_cdbs_ex_left: %d\n", task, dev,
+                               atomic_read(&cmd->t_task_cdbs_ex_left));
+-
+-                      spin_lock_irqsave(&dev->execute_task_lock, flags);
+                       continue;
+               }
+               fe_count = atomic_read(&cmd->t_fe_count);
+@@ -298,22 +292,31 @@ int core_tmr_lun_reset(
+                               " task: %p, t_fe_count: %d dev: %p\n", task,
+                               fe_count, dev);
+                       atomic_set(&cmd->t_transport_aborted, 1);
+-                      spin_unlock_irqrestore(&cmd->t_state_lock,
+-                                              flags);
+-                      core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
++                      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-                      spin_lock_irqsave(&dev->execute_task_lock, flags);
++                      core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+                       continue;
+               }
+               pr_debug("LUN_RESET: Got t_transport_active = 0 for task: %p,"
+                       " t_fe_count: %d dev: %p\n", task, fe_count, dev);
+               atomic_set(&cmd->t_transport_aborted, 1);
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-              core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+-              spin_lock_irqsave(&dev->execute_task_lock, flags);
++              core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+       }
+-      spin_unlock_irqrestore(&dev->execute_task_lock, flags);
++}
++
++static void core_tmr_drain_cmd_list(
++      struct se_device *dev,
++      struct se_cmd *prout_cmd,
++      struct se_node_acl *tmr_nacl,
++      int tas,
++      struct list_head *preempt_and_abort_list)
++{
++      LIST_HEAD(drain_cmd_list);
++      struct se_queue_obj *qobj = &dev->dev_queue_obj;
++      struct se_cmd *cmd, *tcmd;
++      unsigned long flags;
+       /*
+        * Release all commands remaining in the struct se_device cmd queue.
+        *
+@@ -348,10 +351,15 @@ int core_tmr_lun_reset(
+               }
+               spin_unlock(&cmd->t_state_lock);
+-              atomic_dec(&cmd->t_transport_queue_active);
++              atomic_set(&cmd->t_transport_queue_active, 0);
+               atomic_dec(&qobj->queue_cnt);
++              list_move_tail(&cmd->se_queue_node, &drain_cmd_list);
++      }
++      spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
++
++      while (!list_empty(&drain_cmd_list)) {
++              cmd = list_entry(drain_cmd_list.next, struct se_cmd, se_queue_node);
+               list_del_init(&cmd->se_queue_node);
+-              spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+               pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
+                       " %d t_fe_count: %d\n", (preempt_and_abort_list) ?
+@@ -364,9 +372,53 @@ int core_tmr_lun_reset(
+               core_tmr_handle_tas_abort(tmr_nacl, cmd, tas,
+                               atomic_read(&cmd->t_fe_count));
+-              spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
+       }
+-      spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
++}
++
++int core_tmr_lun_reset(
++        struct se_device *dev,
++        struct se_tmr_req *tmr,
++        struct list_head *preempt_and_abort_list,
++        struct se_cmd *prout_cmd)
++{
++      struct se_node_acl *tmr_nacl = NULL;
++      struct se_portal_group *tmr_tpg = NULL;
++      int tas;
++        /*
++       * TASK_ABORTED status bit, this is configurable via ConfigFS
++       * struct se_device attributes.  spc4r17 section 7.4.6 Control mode page
++       *
++       * A task aborted status (TAS) bit set to zero specifies that aborted
++       * tasks shall be terminated by the device server without any response
++       * to the application client. A TAS bit set to one specifies that tasks
++       * aborted by the actions of an I_T nexus other than the I_T nexus on
++       * which the command was received shall be completed with TASK ABORTED
++       * status (see SAM-4).
++       */
++      tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
++      /*
++       * Determine if this se_tmr is coming from a $FABRIC_MOD
++       * or struct se_device passthrough..
++       */
++      if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
++              tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
++              tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
++              if (tmr_nacl && tmr_tpg) {
++                      pr_debug("LUN_RESET: TMR caller fabric: %s"
++                              " initiator port %s\n",
++                              tmr_tpg->se_tpg_tfo->get_fabric_name(),
++                              tmr_nacl->initiatorname);
++              }
++      }
++      pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
++              (preempt_and_abort_list) ? "Preempt" : "TMR",
++              dev->transport->name, tas);
++
++      core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
++      core_tmr_drain_task_list(dev, prout_cmd, tmr_nacl, tas,
++                              preempt_and_abort_list);
++      core_tmr_drain_cmd_list(dev, prout_cmd, tmr_nacl, tas,
++                              preempt_and_abort_list);
+       /*
+        * Clear any legacy SPC-2 reservation when called during
+        * LOGICAL UNIT RESET
+@@ -389,3 +441,4 @@ int core_tmr_lun_reset(
+                       dev->transport->name);
+       return 0;
+ }
++
diff --git a/queue-3.1/x86-fix-compilation-bug-in-kprobes-twobyte_is_boostable.patch b/queue-3.1/x86-fix-compilation-bug-in-kprobes-twobyte_is_boostable.patch
new file mode 100644 (file)
index 0000000..fe5dac3
--- /dev/null
@@ -0,0 +1,96 @@
+From 315eb8a2a1b7f335d40ceeeb11b9e067475eb881 Mon Sep 17 00:00:00 2001
+From: Josh Stone <jistone@redhat.com>
+Date: Mon, 24 Oct 2011 10:15:51 -0700
+Subject: x86: Fix compilation bug in kprobes' twobyte_is_boostable
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Josh Stone <jistone@redhat.com>
+
+commit 315eb8a2a1b7f335d40ceeeb11b9e067475eb881 upstream.
+
+When compiling an i386_defconfig kernel with gcc-4.6.1-9.fc15.i686, I
+noticed a warning about the asm operand for test_bit in kprobes'
+can_boost.  I discovered that this caused only the first long of
+twobyte_is_boostable[] to be output.
+
+Jakub filed and fixed gcc PR50571 to correct the warning and this output
+issue.  But to solve it for less current gcc, we can make kprobes'
+twobyte_is_boostable[] non-const, and it won't be optimized out.
+
+Before:
+
+    CC      arch/x86/kernel/kprobes.o
+  In file included from include/linux/bitops.h:22:0,
+                   from include/linux/kernel.h:17,
+                   from [...]/arch/x86/include/asm/percpu.h:44,
+                   from [...]/arch/x86/include/asm/current.h:5,
+                   from [...]/arch/x86/include/asm/processor.h:15,
+                   from [...]/arch/x86/include/asm/atomic.h:6,
+                   from include/linux/atomic.h:4,
+                   from include/linux/mutex.h:18,
+                   from include/linux/notifier.h:13,
+                   from include/linux/kprobes.h:34,
+                   from arch/x86/kernel/kprobes.c:43:
+  [...]/arch/x86/include/asm/bitops.h: In function ‘can_boost.part.1’:
+  [...]/arch/x86/include/asm/bitops.h:319:2: warning: use of memory input
+        without lvalue in asm operand 1 is deprecated [enabled by default]
+
+  $ objdump -rd arch/x86/kernel/kprobes.o | grep -A1 -w bt
+       551:    0f a3 05 00 00 00 00    bt     %eax,0x0
+                          554: R_386_32        .rodata.cst4
+
+  $ objdump -s -j .rodata.cst4 -j .data arch/x86/kernel/kprobes.o
+
+  arch/x86/kernel/kprobes.o:     file format elf32-i386
+
+  Contents of section .data:
+   0000 48000000 00000000 00000000 00000000  H...............
+  Contents of section .rodata.cst4:
+   0000 4c030000                             L...
+
+Only a single long of twobyte_is_boostable[] is in the object file.
+
+After, without the const on twobyte_is_boostable:
+
+  $ objdump -rd arch/x86/kernel/kprobes.o | grep -A1 -w bt
+       551:    0f a3 05 20 00 00 00    bt     %eax,0x20
+                          554: R_386_32        .data
+
+  $ objdump -s -j .rodata.cst4 -j .data arch/x86/kernel/kprobes.o
+
+  arch/x86/kernel/kprobes.o:     file format elf32-i386
+
+  Contents of section .data:
+   0000 48000000 00000000 00000000 00000000  H...............
+   0010 00000000 00000000 00000000 00000000  ................
+   0020 4c030000 0f000200 ffff0000 ffcff0c0  L...............
+   0030 0000ffff 3bbbfff8 03ff2ebb 26bb2e77  ....;.......&..w
+
+Now all 32 bytes are output into .data instead.
+
+Signed-off-by: Josh Stone <jistone@redhat.com>
+Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+Cc: Jakub Jelinek <jakub@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/kprobes.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/kprobes.c
++++ b/arch/x86/kernel/kprobes.c
+@@ -75,8 +75,10 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kpr
+       /*
+        * Undefined/reserved opcodes, conditional jump, Opcode Extension
+        * Groups, and some special opcodes can not boost.
++       * This is non-const to keep gcc from statically optimizing it out, as
++       * variable_test_bit makes gcc think only *(unsigned long*) is used.
+        */
+-static const u32 twobyte_is_boostable[256 / 32] = {
++static u32 twobyte_is_boostable[256 / 32] = {
+       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
+       /*      ----------------------------------------------          */
+       W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
diff --git a/queue-3.1/x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch b/queue-3.1/x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch
new file mode 100644 (file)
index 0000000..9e2cb55
--- /dev/null
@@ -0,0 +1,220 @@
+From 6a469e4665bc158599de55d64388861d0a9f10f4 Mon Sep 17 00:00:00 2001
+From: Jack Steiner <steiner@sgi.com>
+Date: Tue, 20 Sep 2011 13:55:04 -0700
+Subject: x86: uv2: Workaround for UV2 Hub bug (system global address format)
+
+From: Jack Steiner <steiner@sgi.com>
+
+commit 6a469e4665bc158599de55d64388861d0a9f10f4 upstream.
+
+This is a workaround for a UV2 hub bug that affects the format of system
+global addresses.
+
+The GRU API for UV2 was inadvertently broken by a hardware change.  The
+format of the physical address used for TLB dropins and for addresses used
+with instructions running in unmapped mode has changed.  This change was
+not documented and became apparent only when diags failed running on
+system simulators.
+
+For UV1, TLB and GRU instruction physical addresses are identical to
+socket physical addresses (although high NASID bits must be OR'ed into the
+address).
+
+For UV2, socket physical addresses need to be converted.  The NODE portion
+of the physical address needs to be shifted so that the low bit is in bit
+39 or bit 40, depending on an MMR value.
+
+It is not yet clear if this bug will be fixed in a silicon respin.  If it
+is fixed, the hub revision will be incremented & the workaround disabled.
+
+Signed-off-by: Jack Steiner <steiner@sgi.com>
+Cc: Ingo Molnar <mingo@elte.hu>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/include/asm/uv/uv_bau.h   |    1 +
+ arch/x86/include/asm/uv/uv_hub.h   |   37 ++++++++++++++++++++++++++++++++++---
+ arch/x86/kernel/apic/x2apic_uv_x.c |    7 +++++--
+ arch/x86/platform/uv/tlb_uv.c      |   17 ++++++-----------
+ 4 files changed, 46 insertions(+), 16 deletions(-)
+
+--- a/arch/x86/include/asm/uv/uv_bau.h
++++ b/arch/x86/include/asm/uv/uv_bau.h
+@@ -55,6 +55,7 @@
+ #define UV_BAU_TUNABLES_DIR           "sgi_uv"
+ #define UV_BAU_TUNABLES_FILE          "bau_tunables"
+ #define WHITESPACE                    " \t\n"
++#define uv_mmask                      ((1UL << uv_hub_info->m_val) - 1)
+ #define uv_physnodeaddr(x)            ((__pa((unsigned long)(x)) & uv_mmask))
+ #define cpubit_isset(cpu, bau_local_cpumask) \
+       test_bit((cpu), (bau_local_cpumask).bits)
+--- a/arch/x86/include/asm/uv/uv_hub.h
++++ b/arch/x86/include/asm/uv/uv_hub.h
+@@ -46,6 +46,13 @@
+  *    PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
+  *              of the nasid for socket usage.
+  *
++ *    GPA     - (global physical address) a socket physical address converted
++ *              so that it can be used by the GRU as a global address. Socket
++ *              physical addresses 1) need additional NASID (node) bits added
++ *              to the high end of the address, and 2) unaliased if the
++ *              partition does not have a physical address 0. In addition, on
++ *              UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
++ *
+  *
+  *  NumaLink Global Physical Address Format:
+  *  +--------------------------------+---------------------+
+@@ -141,6 +148,8 @@ struct uv_hub_info_s {
+       unsigned int            gnode_extra;
+       unsigned char           hub_revision;
+       unsigned char           apic_pnode_shift;
++      unsigned char           m_shift;
++      unsigned char           n_lshift;
+       unsigned long           gnode_upper;
+       unsigned long           lowmem_remap_top;
+       unsigned long           lowmem_remap_base;
+@@ -177,6 +186,16 @@ static inline int is_uv2_hub(void)
+       return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
+ }
++static inline int is_uv2_1_hub(void)
++{
++      return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
++}
++
++static inline int is_uv2_2_hub(void)
++{
++      return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
++}
++
+ union uvh_apicid {
+     unsigned long       v;
+     struct uvh_apicid_s {
+@@ -276,7 +295,10 @@ static inline unsigned long uv_soc_phys_
+ {
+       if (paddr < uv_hub_info->lowmem_remap_top)
+               paddr |= uv_hub_info->lowmem_remap_base;
+-      return paddr | uv_hub_info->gnode_upper;
++      paddr |= uv_hub_info->gnode_upper;
++      paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
++              ((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
++      return paddr;
+ }
+@@ -300,16 +322,19 @@ static inline unsigned long uv_gpa_to_so
+       unsigned long remap_base = uv_hub_info->lowmem_remap_base;
+       unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
++      gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
++              ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
++      gpa = gpa & uv_hub_info->gpa_mask;
+       if (paddr >= remap_base && paddr < remap_base + remap_top)
+               paddr -= remap_base;
+       return paddr;
+ }
+-/* gnode -> pnode */
++/* gpa -> pnode */
+ static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
+ {
+-      return gpa >> uv_hub_info->m_val;
++      return gpa >> uv_hub_info->n_lshift;
+ }
+ /* gpa -> pnode */
+@@ -320,6 +345,12 @@ static inline int uv_gpa_to_pnode(unsign
+       return uv_gpa_to_gnode(gpa) & n_mask;
+ }
++/* gpa -> node offset*/
++static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
++{
++      return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
++}
++
+ /* pnode, offset --> socket virtual */
+ static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
+ {
+--- a/arch/x86/kernel/apic/x2apic_uv_x.c
++++ b/arch/x86/kernel/apic/x2apic_uv_x.c
+@@ -832,6 +832,10 @@ void __init uv_system_init(void)
+               uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
+               uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
++              uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
++              uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
++                              (m_val == 40 ? 40 : 39) : m_val;
++
+               pnode = uv_apicid_to_pnode(apicid);
+               blade = boot_pnode_to_blade(pnode);
+               lcpu = uv_blade_info[blade].nr_possible_cpus;
+@@ -862,8 +866,7 @@ void __init uv_system_init(void)
+               if (uv_node_to_blade[nid] >= 0)
+                       continue;
+               paddr = node_start_pfn(nid) << PAGE_SHIFT;
+-              paddr = uv_soc_phys_ram_to_gpa(paddr);
+-              pnode = (paddr >> m_val) & pnode_mask;
++              pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
+               blade = boot_pnode_to_blade(pnode);
+               uv_node_to_blade[nid] = blade;
+       }
+--- a/arch/x86/platform/uv/tlb_uv.c
++++ b/arch/x86/platform/uv/tlb_uv.c
+@@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
+ /* base pnode in this partition */
+ static int uv_base_pnode __read_mostly;
+-/* position of pnode (which is nasid>>1): */
+-static int uv_nshift __read_mostly;
+-static unsigned long uv_mmask __read_mostly;
+ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
+ static DEFINE_PER_CPU(struct bau_control, bau_control);
+@@ -1435,7 +1432,7 @@ static void activation_descriptor_init(i
+ {
+       int i;
+       int cpu;
+-      unsigned long pa;
++      unsigned long gpa;
+       unsigned long m;
+       unsigned long n;
+       size_t dsize;
+@@ -1451,9 +1448,9 @@ static void activation_descriptor_init(i
+       bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
+       BUG_ON(!bau_desc);
+-      pa = uv_gpa(bau_desc); /* need the real nasid*/
+-      n = pa >> uv_nshift;
+-      m = pa & uv_mmask;
++      gpa = uv_gpa(bau_desc);
++      n = uv_gpa_to_gnode(gpa);
++      m = uv_gpa_to_offset(gpa);
+       /* the 14-bit pnode */
+       write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
+@@ -1525,9 +1522,9 @@ static void pq_init(int node, int pnode)
+               bcp->queue_last         = pqp + (DEST_Q_SIZE - 1);
+       }
+       /*
+-       * need the pnode of where the memory was really allocated
++       * need the gnode of where the memory was really allocated
+        */
+-      pn = uv_gpa(pqp) >> uv_nshift;
++      pn = uv_gpa_to_gnode(uv_gpa(pqp));
+       first = uv_physnodeaddr(pqp);
+       pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
+       last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
+@@ -1837,8 +1834,6 @@ static int __init uv_bau_init(void)
+               zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
+       }
+-      uv_nshift = uv_hub_info->m_val;
+-      uv_mmask = (1UL << uv_hub_info->m_val) - 1;
+       nuvhubs = uv_num_possible_blades();
+       spin_lock_init(&disable_lock);
+       congested_cycles = usec_2_cycles(congested_respns_us);