]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Nov 2012 17:13:07 +0000 (10:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Nov 2012 17:13:07 +0000 (10:13 -0700)
added patches:
alsa-avoid-endless-sleep-after-disconnect.patch
alsa-pcm-fix-some-races-at-disconnection.patch
hid-microsoft-fix-invalid-rdesc-for-3k-kbd.patch
qla2xxx-update-target-lookup-session-tables-when-a-target-session-changes.patch
target-fix-double-free-of-se_cmd-in-target_complete_tmr_failure.patch
target-reintroduce-some-obsolete-scsi-2-commands.patch

queue-3.6/alsa-avoid-endless-sleep-after-disconnect.patch [new file with mode: 0644]
queue-3.6/alsa-pcm-fix-some-races-at-disconnection.patch [new file with mode: 0644]
queue-3.6/hid-microsoft-fix-invalid-rdesc-for-3k-kbd.patch [new file with mode: 0644]
queue-3.6/qla2xxx-update-target-lookup-session-tables-when-a-target-session-changes.patch [new file with mode: 0644]
queue-3.6/series
queue-3.6/target-fix-double-free-of-se_cmd-in-target_complete_tmr_failure.patch [new file with mode: 0644]
queue-3.6/target-reintroduce-some-obsolete-scsi-2-commands.patch [new file with mode: 0644]

diff --git a/queue-3.6/alsa-avoid-endless-sleep-after-disconnect.patch b/queue-3.6/alsa-avoid-endless-sleep-after-disconnect.patch
new file mode 100644 (file)
index 0000000..fb77433
--- /dev/null
@@ -0,0 +1,182 @@
+From 0914f7961babbf28aaa2f19b453951fb4841c03f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 16 Oct 2012 16:43:39 +0200
+Subject: ALSA: Avoid endless sleep after disconnect
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 0914f7961babbf28aaa2f19b453951fb4841c03f upstream.
+
+When disconnect callback is called, each component should wake up
+sleepers and check card->shutdown flag for avoiding the endless sleep
+blocking the proper resource release.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/control.c     |    2 ++
+ sound/core/hwdep.c       |    7 +++++++
+ sound/core/oss/pcm_oss.c |    4 ++++
+ sound/core/pcm.c         |    6 +++++-
+ sound/core/pcm_native.c  |    8 ++++++++
+ sound/core/rawmidi.c     |   20 ++++++++++++++++++++
+ 6 files changed, 46 insertions(+), 1 deletion(-)
+
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1433,6 +1433,8 @@ static ssize_t snd_ctl_read(struct file
+                       spin_unlock_irq(&ctl->read_lock);
+                       schedule();
+                       remove_wait_queue(&ctl->change_sleep, &wait);
++                      if (ctl->card->shutdown)
++                              return -ENODEV;
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
+                       spin_lock_irq(&ctl->read_lock);
+--- a/sound/core/hwdep.c
++++ b/sound/core/hwdep.c
+@@ -129,6 +129,10 @@ static int snd_hwdep_open(struct inode *
+               mutex_unlock(&hw->open_mutex);
+               schedule();
+               mutex_lock(&hw->open_mutex);
++              if (hw->card->shutdown) {
++                      err = -ENODEV;
++                      break;
++              }
+               if (signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       break;
+@@ -459,12 +463,15 @@ static int snd_hwdep_dev_disconnect(stru
+               mutex_unlock(&register_mutex);
+               return -EINVAL;
+       }
++      mutex_lock(&hwdep->open_mutex);
++      wake_up(&hwdep->open_wait);
+ #ifdef CONFIG_SND_OSSEMUL
+       if (hwdep->ossreg)
+               snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
+ #endif
+       snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
+       list_del_init(&hwdep->list);
++      mutex_unlock(&hwdep->open_mutex);
+       mutex_unlock(&register_mutex);
+       return 0;
+ }
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode
+               mutex_unlock(&pcm->open_mutex);
+               schedule();
+               mutex_lock(&pcm->open_mutex);
++              if (pcm->card->shutdown) {
++                      err = -ENODEV;
++                      break;
++              }
+               if (signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       break;
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -1087,12 +1087,16 @@ static int snd_pcm_dev_disconnect(struct
+               goto unlock;
+       mutex_lock(&pcm->open_mutex);
++      wake_up(&pcm->open_wait);
+       list_del_init(&pcm->list);
+       for (cidx = 0; cidx < 2; cidx++)
+               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+                       snd_pcm_stream_lock_irq(substream);
+-                      if (substream->runtime)
++                      if (substream->runtime) {
+                               substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
++                              wake_up(&substream->runtime->sleep);
++                              wake_up(&substream->runtime->tsleep);
++                      }
+                       snd_pcm_stream_unlock_irq(substream);
+               }
+       list_for_each_entry(notify, &snd_pcm_notify_list, list) {
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1518,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_
+               down_read(&snd_pcm_link_rwsem);
+               snd_pcm_stream_lock_irq(substream);
+               remove_wait_queue(&to_check->sleep, &wait);
++              if (card->shutdown) {
++                      result = -ENODEV;
++                      break;
++              }
+               if (tout == 0) {
+                       if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
+                               result = -ESTRPIPE;
+@@ -2163,6 +2167,10 @@ static int snd_pcm_open(struct file *fil
+               mutex_unlock(&pcm->open_mutex);
+               schedule();
+               mutex_lock(&pcm->open_mutex);
++              if (pcm->card->shutdown) {
++                      err = -ENODEV;
++                      break;
++              }
+               if (signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       break;
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -422,6 +422,10 @@ static int snd_rawmidi_open(struct inode
+               mutex_unlock(&rmidi->open_mutex);
+               schedule();
+               mutex_lock(&rmidi->open_mutex);
++              if (rmidi->card->shutdown) {
++                      err = -ENODEV;
++                      break;
++              }
+               if (signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       break;
+@@ -991,6 +995,8 @@ static ssize_t snd_rawmidi_read(struct f
+                       spin_unlock_irq(&runtime->lock);
+                       schedule();
+                       remove_wait_queue(&runtime->sleep, &wait);
++                      if (rfile->rmidi->card->shutdown)
++                              return -ENODEV;
+                       if (signal_pending(current))
+                               return result > 0 ? result : -ERESTARTSYS;
+                       if (!runtime->avail)
+@@ -1234,6 +1240,8 @@ static ssize_t snd_rawmidi_write(struct
+                       spin_unlock_irq(&runtime->lock);
+                       timeout = schedule_timeout(30 * HZ);
+                       remove_wait_queue(&runtime->sleep, &wait);
++                      if (rfile->rmidi->card->shutdown)
++                              return -ENODEV;
+                       if (signal_pending(current))
+                               return result > 0 ? result : -ERESTARTSYS;
+                       if (!runtime->avail && !timeout)
+@@ -1609,9 +1617,20 @@ static int snd_rawmidi_dev_register(stru
+ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
+ {
+       struct snd_rawmidi *rmidi = device->device_data;
++      int dir;
+       mutex_lock(&register_mutex);
++      mutex_lock(&rmidi->open_mutex);
++      wake_up(&rmidi->open_wait);
+       list_del_init(&rmidi->list);
++      for (dir = 0; dir < 2; dir++) {
++              struct snd_rawmidi_substream *s;
++              list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
++                      if (s->runtime)
++                              wake_up(&s->runtime->sleep);
++              }
++      }
++
+ #ifdef CONFIG_SND_OSSEMUL
+       if (rmidi->ossreg) {
+               if ((int)rmidi->device == midi_map[rmidi->card->number]) {
+@@ -1626,6 +1645,7 @@ static int snd_rawmidi_dev_disconnect(st
+       }
+ #endif /* CONFIG_SND_OSSEMUL */
+       snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
++      mutex_unlock(&rmidi->open_mutex);
+       mutex_unlock(&register_mutex);
+       return 0;
+ }
diff --git a/queue-3.6/alsa-pcm-fix-some-races-at-disconnection.patch b/queue-3.6/alsa-pcm-fix-some-races-at-disconnection.patch
new file mode 100644 (file)
index 0000000..a984a9b
--- /dev/null
@@ -0,0 +1,103 @@
+From 9b0573c07f278e9888c352aa9724035c75784ea0 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 12 Oct 2012 15:07:34 +0200
+Subject: ALSA: PCM: Fix some races at disconnection
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 9b0573c07f278e9888c352aa9724035c75784ea0 upstream.
+
+Fix races at PCM disconnection:
+- while a PCM device is being opened or closed
+- while the PCM state is being changed without lock in prepare,
+  hw_params, hw_free ops
+
+Reported-by: Matthieu CASTET <matthieu.castet@parrot.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/pcm.c        |    7 ++++++-
+ sound/core/pcm_native.c |   16 ++++++++++++----
+ 2 files changed, 18 insertions(+), 5 deletions(-)
+
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -1086,11 +1086,15 @@ static int snd_pcm_dev_disconnect(struct
+       if (list_empty(&pcm->list))
+               goto unlock;
++      mutex_lock(&pcm->open_mutex);
+       list_del_init(&pcm->list);
+       for (cidx = 0; cidx < 2; cidx++)
+-              for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
++              for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
++                      snd_pcm_stream_lock_irq(substream);
+                       if (substream->runtime)
+                               substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
++                      snd_pcm_stream_unlock_irq(substream);
++              }
+       list_for_each_entry(notify, &snd_pcm_notify_list, list) {
+               notify->n_disconnect(pcm);
+       }
+@@ -1106,6 +1110,7 @@ static int snd_pcm_dev_disconnect(struct
+               }
+               snd_unregister_device(devtype, pcm->card, pcm->device);
+       }
++      mutex_unlock(&pcm->open_mutex);
+  unlock:
+       mutex_unlock(&register_mutex);
+       return 0;
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pc
+       return usecs;
+ }
++static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
++{
++      snd_pcm_stream_lock_irq(substream);
++      if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
++              substream->runtime->status->state = state;
++      snd_pcm_stream_unlock_irq(substream);
++}
++
+ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params)
+ {
+@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_
+               runtime->boundary *= 2;
+       snd_pcm_timer_resolution_change(substream);
+-      runtime->status->state = SNDRV_PCM_STATE_SETUP;
++      snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
+       if (pm_qos_request_active(&substream->latency_pm_qos_req))
+               pm_qos_remove_request(&substream->latency_pm_qos_req);
+@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_
+       /* hardware might be unusable from this time,
+          so we force application to retry to set
+          the correct hardware parameter settings */
+-      runtime->status->state = SNDRV_PCM_STATE_OPEN;
++      snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
+       if (substream->ops->hw_free != NULL)
+               substream->ops->hw_free(substream);
+       return err;
+@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pc
+               return -EBADFD;
+       if (substream->ops->hw_free)
+               result = substream->ops->hw_free(substream);
+-      runtime->status->state = SNDRV_PCM_STATE_OPEN;
++      snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
+       pm_qos_remove_request(&substream->latency_pm_qos_req);
+       return result;
+ }
+@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       runtime->control->appl_ptr = runtime->status->hw_ptr;
+-      runtime->status->state = SNDRV_PCM_STATE_PREPARED;
++      snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
+ }
+ static struct action_ops snd_pcm_action_prepare = {
diff --git a/queue-3.6/hid-microsoft-fix-invalid-rdesc-for-3k-kbd.patch b/queue-3.6/hid-microsoft-fix-invalid-rdesc-for-3k-kbd.patch
new file mode 100644 (file)
index 0000000..163bf2d
--- /dev/null
@@ -0,0 +1,86 @@
+From 3ccc60f9d8c39180c205dba1a020735bda1b2491 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Fri, 19 Oct 2012 13:28:46 +0200
+Subject: HID: microsoft: fix invalid rdesc for 3k kbd
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 3ccc60f9d8c39180c205dba1a020735bda1b2491 upstream.
+
+Microsoft Digital Media Keyboard 3000 has two interfaces, and the
+second one has a report descriptor with a bug. The second collection
+says:
+05 01 -- global; usage page -- 01 -- Generic Desktop Controls
+09 80 -- local; usage -- 80 -- System Control
+a1 01 -- main; collection -- 01 -- application
+
+85 03 -- global; report ID -- 03
+19 00 -- local; Usage Minimum -- 00
+29 ff -- local; Usage Maximum -- ff
+15 00 -- global; Logical Minimum -- 0
+26 ff 00 -- global; Logical Maximum -- ff
+81 00 -- main; input
+
+c0 -- main; End Collection
+
+I.e. it makes us think that there are all kinds of usages of system
+control. That the keyboard is a not only a keyboard, but also a
+joystick, mouse, gamepad, keypad, etc. The same as for the Wireless
+Desktop Receiver, this should be Physical Min/Max. So fix that
+appropriately.
+
+References: https://bugzilla.novell.com/show_bug.cgi?id=776834
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-microsoft.c |   18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -29,22 +29,30 @@
+ #define MS_RDESC              0x08
+ #define MS_NOGET              0x10
+ #define MS_DUPLICATE_USAGES   0x20
++#define MS_RDESC_3K           0x40
+-/*
+- * Microsoft Wireless Desktop Receiver (Model 1028) has
+- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+- */
+ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+ {
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
++      /*
++       * Microsoft Wireless Desktop Receiver (Model 1028) has
++       * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
++       */
+       if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
+                       rdesc[559] == 0x29) {
+               hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
+               rdesc[557] = 0x35;
+               rdesc[559] = 0x45;
+       }
++      /* the same as above (s/usage/physical/) */
++      if ((quirks & MS_RDESC_3K) && *rsize == 106 &&
++                      !memcmp((char []){ 0x19, 0x00, 0x29, 0xff },
++                              &rdesc[94], 4)) {
++              rdesc[94] = 0x35;
++              rdesc[96] = 0x45;
++      }
+       return rdesc;
+ }
+@@ -193,7 +201,7 @@ static const struct hid_device_id ms_dev
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
+               .driver_data = MS_PRESENTER },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
+-              .driver_data = MS_ERGONOMY },
++              .driver_data = MS_ERGONOMY | MS_RDESC_3K },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
+               .driver_data = MS_NOGET },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
diff --git a/queue-3.6/qla2xxx-update-target-lookup-session-tables-when-a-target-session-changes.patch b/queue-3.6/qla2xxx-update-target-lookup-session-tables-when-a-target-session-changes.patch
new file mode 100644 (file)
index 0000000..5cb4f7b
--- /dev/null
@@ -0,0 +1,199 @@
+From c8292d1da53fa60c7516ab03a9d83f7ea266d335 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Thu, 11 Oct 2012 13:41:32 -0700
+Subject: qla2xxx: Update target lookup session tables when a target session changes
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit c8292d1da53fa60c7516ab03a9d83f7ea266d335 upstream.
+
+It is possible for the target code to change the loop_id or s_id of a
+target session in reaction to an FC fabric change.  However, the
+session structures are stored in tables that are indexed by these two
+keys, and if we just change the session structure but leave the
+pointers to it in the old places in the table, havoc can ensue.  For
+example, a new session might come along that should go in the old slot
+in the table and overwrite the old session pointer.
+
+To handle this, add a new tgt_ops->update_sess() method that also
+updates the "by loop_id" and "by s_id" lookup tables when a session
+changes, so that the keys where a session pointer is stored in these
+tables always matches the keys in the session structure itself.
+
+(nab: Drop unnecessary double inversion with FCF_CONF_COMP_SUPPORTED
+      usage)
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Cc: Chad Dupuis <chad.dupuis@qlogic.com>
+Cc: Arun Easi <arun.easi@qlogic.com>
+Cc: Saurav Kashyap <saurav.kashyap@qlogic.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/qla2xxx/qla_target.c  |   25 +++++-------
+ drivers/scsi/qla2xxx/qla_target.h  |    1 
+ drivers/scsi/qla2xxx/tcm_qla2xxx.c |   73 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 85 insertions(+), 14 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struc
+       int pmap_len;
+       fc_port_t *fcport;
+       int global_resets;
++      unsigned long flags;
+ retry:
+       global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
+@@ -625,10 +626,10 @@ retry:
+           sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
+           fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
+-      sess->s_id = fcport->d_id;
+-      sess->loop_id = fcport->loop_id;
+-      sess->conf_compl_supported = !!(fcport->flags &
+-          FCF_CONF_COMP_SUPPORTED);
++      spin_lock_irqsave(&ha->hardware_lock, flags);
++      ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
++                              (fcport->flags & FCF_CONF_COMP_SUPPORTED));
++      spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       res = true;
+@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_s
+                               qlt_undelete_sess(sess);
+                       kref_get(&sess->se_sess->sess_kref);
+-                      sess->s_id = fcport->d_id;
+-                      sess->loop_id = fcport->loop_id;
+-                      sess->conf_compl_supported = !!(fcport->flags &
+-                          FCF_CONF_COMP_SUPPORTED);
++                      ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
++                                              (fcport->flags & FCF_CONF_COMP_SUPPORTED));
++
+                       if (sess->local && !local)
+                               sess->local = 0;
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_s
+        */
+       kref_get(&sess->se_sess->sess_kref);
+-      sess->conf_compl_supported = !!(fcport->flags &
+-          FCF_CONF_COMP_SUPPORTED);
++      sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
+       BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
+       memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
+@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_h
+                       ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
+                           "Reappeared sess %p\n", sess);
+               }
+-              sess->s_id = fcport->d_id;
+-              sess->loop_id = fcport->loop_id;
+-              sess->conf_compl_supported = !!(fcport->flags &
+-                  FCF_CONF_COMP_SUPPORTED);
++              ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
++                                      (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+       }
+       if (sess && sess->local) {
+--- a/drivers/scsi/qla2xxx/qla_target.h
++++ b/drivers/scsi/qla2xxx/qla_target.h
+@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
+       int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
+                                       void *, uint8_t *, uint16_t);
++      void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
+       struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
+                                               const uint16_t);
+       struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
+--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+@@ -1468,6 +1468,78 @@ static int tcm_qla2xxx_check_initiator_n
+       return 0;
+ }
++static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
++                                  uint16_t loop_id, bool conf_compl_supported)
++{
++      struct qla_tgt *tgt = sess->tgt;
++      struct qla_hw_data *ha = tgt->ha;
++      struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
++      struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
++      struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
++                      struct tcm_qla2xxx_nacl, se_node_acl);
++      u32 key;
++
++
++      if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
++              pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
++                      sess,
++                      sess->port_name[0], sess->port_name[1],
++                      sess->port_name[2], sess->port_name[3],
++                      sess->port_name[4], sess->port_name[5],
++                      sess->port_name[6], sess->port_name[7],
++                      sess->loop_id, loop_id,
++                      sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
++                      s_id.b.domain, s_id.b.area, s_id.b.al_pa);
++
++      if (sess->loop_id != loop_id) {
++              /*
++               * Because we can shuffle loop IDs around and we
++               * update different sessions non-atomically, we might
++               * have overwritten this session's old loop ID
++               * already, and we might end up overwriting some other
++               * session that will be updated later.  So we have to
++               * be extra careful and we can't warn about those things...
++               */
++              if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
++                      lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
++
++              lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
++
++              sess->loop_id = loop_id;
++      }
++
++      if (sess->s_id.b24 != s_id.b24) {
++              key = (((u32) sess->s_id.b.domain << 16) |
++                     ((u32) sess->s_id.b.area   <<  8) |
++                     ((u32) sess->s_id.b.al_pa));
++
++              if (btree_lookup32(&lport->lport_fcport_map, key))
++                      WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
++                           "Found wrong se_nacl when updating s_id %x:%x:%x\n",
++                           sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
++              else
++                      WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
++                           sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
++
++              key = (((u32) s_id.b.domain << 16) |
++                     ((u32) s_id.b.area   <<  8) |
++                     ((u32) s_id.b.al_pa));
++
++              if (btree_lookup32(&lport->lport_fcport_map, key)) {
++                      WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
++                           s_id.b.domain, s_id.b.area, s_id.b.al_pa);
++                      btree_update32(&lport->lport_fcport_map, key, se_nacl);
++              } else {
++                      btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
++              }
++
++              sess->s_id = s_id;
++              nacl->nport_id = key;
++      }
++
++      sess->conf_compl_supported = conf_compl_supported;
++}
++
+ /*
+  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
+  */
+@@ -1478,6 +1550,7 @@ static struct qla_tgt_func_tmpl tcm_qla2
+       .free_cmd               = tcm_qla2xxx_free_cmd,
+       .free_mcmd              = tcm_qla2xxx_free_mcmd,
+       .free_session           = tcm_qla2xxx_free_session,
++      .update_sess            = tcm_qla2xxx_update_sess,
+       .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
+       .find_sess_by_s_id      = tcm_qla2xxx_find_sess_by_s_id,
+       .find_sess_by_loop_id   = tcm_qla2xxx_find_sess_by_loop_id,
index 30fcbc555a5fbd9281f2beb97ccdf6aa50cabf3f..ee9901ffda509bcce6537253cc714c384ffd09d7 100644 (file)
@@ -15,3 +15,9 @@ ceph-avoid-32-bit-page-index-overflow.patch
 usb-mos7840-fix-port-data-memory-leak.patch
 usb-iuu_phoenix-fix-backported-patches.patch
 usb-io_edgeport-remove-unused-variable.patch
+alsa-pcm-fix-some-races-at-disconnection.patch
+alsa-avoid-endless-sleep-after-disconnect.patch
+qla2xxx-update-target-lookup-session-tables-when-a-target-session-changes.patch
+target-reintroduce-some-obsolete-scsi-2-commands.patch
+target-fix-double-free-of-se_cmd-in-target_complete_tmr_failure.patch
+hid-microsoft-fix-invalid-rdesc-for-3k-kbd.patch
diff --git a/queue-3.6/target-fix-double-free-of-se_cmd-in-target_complete_tmr_failure.patch b/queue-3.6/target-fix-double-free-of-se_cmd-in-target_complete_tmr_failure.patch
new file mode 100644 (file)
index 0000000..45aa436
--- /dev/null
@@ -0,0 +1,41 @@
+From e13d5fef88c40b87c8430f8274c3a9ca32ef90bc Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Fri, 26 Oct 2012 15:35:45 -0700
+Subject: target: Fix double-free of se_cmd in target_complete_tmr_failure
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit e13d5fef88c40b87c8430f8274c3a9ca32ef90bc upstream.
+
+Fabric drivers currently expect to internally release se_cmd in the event
+of a TMR failure during target_submit_tmr(), which means the immediate call
+to transport_generic_free_cmd() after TFO->queue_tm_rsp() from within
+target_complete_tmr_failure() workqueue context is wrong.
+
+This is done as some fabrics expect TMR operations to be acknowledged
+before releasing the descriptor, so the assumption that core is releasing
+se_cmd associated TMR memory is incorrect.  This fixes a OOPs where
+transport_generic_free_cmd() was being called more than once.
+
+This bug was originally observed with tcm_qla2xxx fabric ports.
+
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Roland Dreier <roland@purestorage.com>
+Cc: Andy Grover <agrover@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_transport.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -1553,7 +1553,6 @@ static void target_complete_tmr_failure(
+       se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
+       se_cmd->se_tfo->queue_tm_rsp(se_cmd);
+-      transport_generic_free_cmd(se_cmd, 0);
+ }
+ /**
diff --git a/queue-3.6/target-reintroduce-some-obsolete-scsi-2-commands.patch b/queue-3.6/target-reintroduce-some-obsolete-scsi-2-commands.patch
new file mode 100644 (file)
index 0000000..73b8a18
--- /dev/null
@@ -0,0 +1,67 @@
+From 1a1ff38c4cebf23be8bf0009a76b082a13bd25cb Mon Sep 17 00:00:00 2001
+From: Bernhard Kohl <bernhard.kohl@nsn.com>
+Date: Wed, 24 Oct 2012 15:53:58 +0200
+Subject: target: reintroduce some obsolete SCSI-2 commands
+
+From: Bernhard Kohl <bernhard.kohl@nsn.com>
+
+commit 1a1ff38c4cebf23be8bf0009a76b082a13bd25cb upstream.
+
+With kernel 3.6 some obsolete SCSI-2 commands including SEEK_10 have
+have been removed by commit 1fd032ee10d2816c947f5d5b9abda95e728f0a8f
+"target: move code for CDB emulation".
+
+There are still clients out there which use these old SCSI-2 commands.
+This mainly happens when running VMs with legacy guest systems,
+connected via SCSI command pass-through to iSCSI targets. Make them
+happy and return status GOOD.
+
+Many real SCSI disks or external iSCSI storage devices still support
+these old commands. So let's make LIO backward compatible as well.
+
+This patch adds support for the previously removed SEEK_10 and
+additionally the SEEK_6 and REZERO_UNIT commands.
+
+Signed-off-by: Bernhard Kohl <bernhard.kohl@nsn.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_sbc.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/target/target_core_sbc.c
++++ b/drivers/target/target_core_sbc.c
+@@ -128,6 +128,12 @@ static int sbc_emulate_verify(struct se_
+       return 0;
+ }
++static int sbc_emulate_noop(struct se_cmd *cmd)
++{
++      target_complete_cmd(cmd, GOOD);
++      return 0;
++}
++
+ static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
+ {
+       return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
+@@ -524,6 +530,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, st
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_verify;
+               break;
++      case REZERO_UNIT:
++      case SEEK_6:
++      case SEEK_10:
++              /*
++               * There are still clients out there which use these old SCSI-2
++               * commands. This mainly happens when running VMs with legacy
++               * guest systems, connected via SCSI command pass-through to
++               * iSCSI targets. Make them happy and return status GOOD.
++               */
++              size = 0;
++              cmd->execute_cmd = sbc_emulate_noop;
++              break;
+       default:
+               ret = spc_parse_cdb(cmd, &size);
+               if (ret)