]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.1 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 1 Nov 2011 18:51:23 +0000 (11:51 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 1 Nov 2011 18:51:23 +0000 (11:51 -0700)
16 files changed:
queue-3.1/drm-i915-fix-ilk-infoframe-support.patch [new file with mode: 0644]
queue-3.1/drm-i915-panel-always-record-the-backlight-level-again-but-cleverly.patch [new file with mode: 0644]
queue-3.1/drm-i915-use-correct-spd-type-value.patch [new file with mode: 0644]
queue-3.1/drm-i915-wrap-dp-edid-fetch-functions-to-enable-edp-panel.patch [new file with mode: 0644]
queue-3.1/drm-radeon-kms-bail-early-in-dvi_detect-for-digital-only-connectors.patch [new file with mode: 0644]
queue-3.1/drm-radeon-kms-fix-i2c-mask-definitions.patch [new file with mode: 0644]
queue-3.1/drm-radeon-kms-handle-force-case-in-connector-detect-more-gracefully.patch [new file with mode: 0644]
queue-3.1/ehci-introduce-a-common-ehci_setup.patch [new file with mode: 0644]
queue-3.1/ehci-workaround-for-moschip-controller-bug.patch [new file with mode: 0644]
queue-3.1/mmc-core-ext_csd.raw_-used-in-comparison-but-never-set.patch [new file with mode: 0644]
queue-3.1/mmc-core-fix-hangs-related-to-insert-remove-of-cards.patch [new file with mode: 0644]
queue-3.1/pci-quirk-mmc-always-check-for-lower-base-frequency-quirk-for-ricoh-1180-e823.patch [new file with mode: 0644]
queue-3.1/series
queue-3.1/usb-fix-ehci-alignment-error.patch [new file with mode: 0644]
queue-3.1/xhci-amd-isoc-link-trb-chain-bit-quirk.patch [new file with mode: 0644]
queue-3.1/xhci-mem.c-check-for-ring-first_seg-null.patch [new file with mode: 0644]

diff --git a/queue-3.1/drm-i915-fix-ilk-infoframe-support.patch b/queue-3.1/drm-i915-fix-ilk-infoframe-support.patch
new file mode 100644 (file)
index 0000000..71ee809
--- /dev/null
@@ -0,0 +1,84 @@
+From 64a8fc0145a1d0fdc25fc9367c2e6c621955fb3b Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 22 Sep 2011 11:16:00 +0530
+Subject: drm/i915: fix ILK+ infoframe support
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 64a8fc0145a1d0fdc25fc9367c2e6c621955fb3b upstream.
+
+Misc fixes based on tests with an infoframe analyzer:
+  - checksum *does* include header bytes
+  - DIP enable & AVI infoframe are tied together in hw, so disable both
+    and make sure AVI frames are enabled first
+  - use every vsync flag for SPD frames to avoid reserved value in
+    frequency field when enabling both AVI & SPD
+
+Fixes https://bugs.freedesktop.org/show_bug.cgi?id=40281.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_hdmi.c |   18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_hdmi.c
++++ b/drivers/gpu/drm/i915/intel_hdmi.c
+@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip
+       frame->checksum = 0;
+       frame->ecc = 0;
+-      /* Header isn't part of the checksum */
+-      for (i = 5; i < frame->len; i++)
++      for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
+               sum += data[i];
+       frame->checksum = 0x100 - sum;
+@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct
+               flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
+               break;
+       case DIP_TYPE_SPD:
+-              flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
++              flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(str
+       flags = intel_infoframe_index(frame);
+-      val &= ~VIDEO_DIP_SELECT_MASK;
++      val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
+-      I915_WRITE(reg, val | flags);
++      I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
+       for (i = 0; i < len; i += 4) {
+               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
+@@ -486,6 +485,7 @@ void intel_hdmi_init(struct drm_device *
+       struct intel_encoder *intel_encoder;
+       struct intel_connector *intel_connector;
+       struct intel_hdmi *intel_hdmi;
++      int i;
+       intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
+       if (!intel_hdmi)
+@@ -538,10 +538,14 @@ void intel_hdmi_init(struct drm_device *
+       intel_hdmi->sdvox_reg = sdvox_reg;
+-      if (!HAS_PCH_SPLIT(dev))
++      if (!HAS_PCH_SPLIT(dev)) {
+               intel_hdmi->write_infoframe = i9xx_write_infoframe;
+-      else
++              I915_WRITE(VIDEO_DIP_CTL, 0);
++      } else {
+               intel_hdmi->write_infoframe = ironlake_write_infoframe;
++              for_each_pipe(i)
++                      I915_WRITE(TVIDEO_DIP_CTL(i), 0);
++      }
+       drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
diff --git a/queue-3.1/drm-i915-panel-always-record-the-backlight-level-again-but-cleverly.patch b/queue-3.1/drm-i915-panel-always-record-the-backlight-level-again-but-cleverly.patch
new file mode 100644 (file)
index 0000000..be82c4a
--- /dev/null
@@ -0,0 +1,80 @@
+From f52c619a590fa75276c07dfcaf380dee53e4ea4c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 14 Oct 2011 11:45:40 +0200
+Subject: drm/i915/panel: Always record the backlight level again (but cleverly)
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit f52c619a590fa75276c07dfcaf380dee53e4ea4c upstream.
+
+The commit 47356eb67285014527a5ab87543ba1fae3d1e10a introduced a
+mechanism to record the backlight level only at disabling time, but it
+also introduced a regression.  Since intel_lvds_enable() may be called
+without disabling (e.g. intel_lvds_commit() calls it unconditionally),
+the backlight gets back to the last recorded value.  For example, this
+happens when you dim the backlight, close the lid and open the lid,
+then the backlight suddenly goes to the brightest.
+
+This patch fixes the bug by recording the backlight level always
+when changed via intel_panel_set_backlight().  And,
+intel_panel_{enable|disable}_backlight() call the internal function not
+to update the recorded level wrongly.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Reviewed-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_panel.c |   21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_panel.c
++++ b/drivers/gpu/drm/i915/intel_panel.c
+@@ -226,7 +226,7 @@ static void intel_pch_panel_set_backligh
+       I915_WRITE(BLC_PWM_CPU_CTL, val | level);
+ }
+-void intel_panel_set_backlight(struct drm_device *dev, u32 level)
++static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+@@ -254,16 +254,21 @@ void intel_panel_set_backlight(struct dr
+       I915_WRITE(BLC_PWM_CTL, tmp | level);
+ }
+-void intel_panel_disable_backlight(struct drm_device *dev)
++void intel_panel_set_backlight(struct drm_device *dev, u32 level)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+-      if (dev_priv->backlight_enabled) {
+-              dev_priv->backlight_level = intel_panel_get_backlight(dev);
+-              dev_priv->backlight_enabled = false;
+-      }
++      dev_priv->backlight_level = level;
++      if (dev_priv->backlight_enabled)
++              intel_panel_actually_set_backlight(dev, level);
++}
++
++void intel_panel_disable_backlight(struct drm_device *dev)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
+-      intel_panel_set_backlight(dev, 0);
++      dev_priv->backlight_enabled = false;
++      intel_panel_actually_set_backlight(dev, 0);
+ }
+ void intel_panel_enable_backlight(struct drm_device *dev)
+@@ -273,8 +278,8 @@ void intel_panel_enable_backlight(struct
+       if (dev_priv->backlight_level == 0)
+               dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
+-      intel_panel_set_backlight(dev, dev_priv->backlight_level);
+       dev_priv->backlight_enabled = true;
++      intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
+ }
+ static void intel_panel_init_backlight(struct drm_device *dev)
diff --git a/queue-3.1/drm-i915-use-correct-spd-type-value.patch b/queue-3.1/drm-i915-use-correct-spd-type-value.patch
new file mode 100644 (file)
index 0000000..7379e70
--- /dev/null
@@ -0,0 +1,30 @@
+From 260052100ef669b5374f72055379adc5da35034b Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 22 Sep 2011 11:16:01 +0530
+Subject: drm/i915: use correct SPD type value
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 260052100ef669b5374f72055379adc5da35034b upstream.
+
+SPD frames are actually type 0x83, not just 0x3.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_drv.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_drv.h
++++ b/drivers/gpu/drm/i915/intel_drv.h
+@@ -184,7 +184,7 @@ struct intel_crtc {
+ #define DIP_VERSION_AVI 0x2
+ #define DIP_LEN_AVI     13
+-#define DIP_TYPE_SPD  0x3
++#define DIP_TYPE_SPD  0x83
+ #define DIP_VERSION_SPD       0x1
+ #define DIP_LEN_SPD   25
+ #define DIP_SPD_UNKNOWN       0
diff --git a/queue-3.1/drm-i915-wrap-dp-edid-fetch-functions-to-enable-edp-panel.patch b/queue-3.1/drm-i915-wrap-dp-edid-fetch-functions-to-enable-edp-panel.patch
new file mode 100644 (file)
index 0000000..f80db37
--- /dev/null
@@ -0,0 +1,83 @@
+From 8c241fef3e6f69f3f675678ae03599ece3f562e2 Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Wed, 28 Sep 2011 16:38:44 -0700
+Subject: drm/i915: Wrap DP EDID fetch functions to enable eDP panel
+ power
+
+From: Keith Packard <keithp@keithp.com>
+
+commit 8c241fef3e6f69f3f675678ae03599ece3f562e2 upstream.
+
+Talking to the eDP DDC channel requires that the panel be powered
+up. Wrap both the EDID and modes fetch code with calls to turn the vdd
+power on and back off.
+
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_dp.c |   31 ++++++++++++++++++++++++++++---
+ 1 file changed, 28 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_dp.c
++++ b/drivers/gpu/drm/i915/intel_dp.c
+@@ -1683,6 +1683,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
+       return intel_dp_detect_dpcd(intel_dp);
+ }
++static struct edid *
++intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
++{
++      struct intel_dp *intel_dp = intel_attached_dp(connector);
++      struct edid     *edid;
++
++      ironlake_edp_panel_vdd_on(intel_dp);
++      edid = drm_get_edid(connector, adapter);
++      ironlake_edp_panel_vdd_off(intel_dp);
++      return edid;
++}
++
++static int
++intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
++{
++      struct intel_dp *intel_dp = intel_attached_dp(connector);
++      int     ret;
++
++      ironlake_edp_panel_vdd_on(intel_dp);
++      ret = intel_ddc_get_modes(connector, adapter);
++      ironlake_edp_panel_vdd_off(intel_dp);
++      return ret;
++}
++
++
+ /**
+  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+  *
+@@ -1715,7 +1740,7 @@ intel_dp_detect(struct drm_connector *co
+       if (intel_dp->force_audio) {
+               intel_dp->has_audio = intel_dp->force_audio > 0;
+       } else {
+-              edid = drm_get_edid(connector, &intel_dp->adapter);
++              edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+               if (edid) {
+                       intel_dp->has_audio = drm_detect_monitor_audio(edid);
+                       connector->display_info.raw_edid = NULL;
+@@ -1736,7 +1761,7 @@ static int intel_dp_get_modes(struct drm
+       /* We should parse the EDID data and find out if it has an audio sink
+        */
+-      ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
++      ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
+       if (ret) {
+               if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) {
+                       struct drm_display_mode *newmode;
+@@ -1772,7 +1797,7 @@ intel_dp_detect_audio(struct drm_connect
+       struct edid *edid;
+       bool has_audio = false;
+-      edid = drm_get_edid(connector, &intel_dp->adapter);
++      edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+       if (edid) {
+               has_audio = drm_detect_monitor_audio(edid);
diff --git a/queue-3.1/drm-radeon-kms-bail-early-in-dvi_detect-for-digital-only-connectors.patch b/queue-3.1/drm-radeon-kms-bail-early-in-dvi_detect-for-digital-only-connectors.patch
new file mode 100644 (file)
index 0000000..c865312
--- /dev/null
@@ -0,0 +1,41 @@
+From 5f0a26128d66ef81613fe923d5c288942844ccdc Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 7 Oct 2011 14:23:47 -0400
+Subject: drm/radeon/kms: bail early in dvi_detect for digital only connectors
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 5f0a26128d66ef81613fe923d5c288942844ccdc upstream.
+
+DVI-D and HDMI-A are digital only, so there's no need to
+attempt analog load detect.  Also, skip bail before the
+!force check, or we fail to get a disconnect events.
+The next patches in the series attempt to fix disconnect
+events for connectors with analog support (DVI-I, HDMI-B,
+DVI-A).
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=41561
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/radeon_connectors.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_connectors.c
++++ b/drivers/gpu/drm/radeon/radeon_connectors.c
+@@ -959,6 +959,11 @@ radeon_dvi_detect(struct drm_connector *
+       if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
+               goto out;
++      /* DVI-D and HDMI-A are digital only */
++      if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
++          (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
++              goto out;
++
+       if (!force) {
+               ret = connector->status;
+               goto out;
diff --git a/queue-3.1/drm-radeon-kms-fix-i2c-mask-definitions.patch b/queue-3.1/drm-radeon-kms-fix-i2c-mask-definitions.patch
new file mode 100644 (file)
index 0000000..bedfff2
--- /dev/null
@@ -0,0 +1,37 @@
+From 286e0c94f9c3f292cb38a977fbbde3433347a868 Mon Sep 17 00:00:00 2001
+From: Jean Delvare <jdelvare@suse.de>
+Date: Thu, 6 Oct 2011 18:16:24 +0200
+Subject: drm/radeon/kms: Fix I2C mask definitions
+
+From: Jean Delvare <jdelvare@suse.de>
+
+commit 286e0c94f9c3f292cb38a977fbbde3433347a868 upstream.
+
+Commit 9b9fe724 accidentally used RADEON_GPIO_EN_* where
+RADEON_GPIO_MASK_* was intended. This caused improper initialization
+of I2C buses, mostly visible when setting i2c_algo_bit.bit_test=1.
+Using the right constants fixes the problem.
+
+Signed-off-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: Jerome Glisse <j.glisse@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/radeon_combios.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_combios.c
++++ b/drivers/gpu/drm/radeon/radeon_combios.c
+@@ -620,8 +620,8 @@ static struct radeon_i2c_bus_rec combios
+               i2c.y_data_mask = 0x80;
+       } else {
+               /* default masks for ddc pads */
+-              i2c.mask_clk_mask = RADEON_GPIO_EN_1;
+-              i2c.mask_data_mask = RADEON_GPIO_EN_0;
++              i2c.mask_clk_mask = RADEON_GPIO_MASK_1;
++              i2c.mask_data_mask = RADEON_GPIO_MASK_0;
+               i2c.a_clk_mask = RADEON_GPIO_A_1;
+               i2c.a_data_mask = RADEON_GPIO_A_0;
+               i2c.en_clk_mask = RADEON_GPIO_EN_1;
diff --git a/queue-3.1/drm-radeon-kms-handle-force-case-in-connector-detect-more-gracefully.patch b/queue-3.1/drm-radeon-kms-handle-force-case-in-connector-detect-more-gracefully.patch
new file mode 100644 (file)
index 0000000..278f2d1
--- /dev/null
@@ -0,0 +1,103 @@
+From d0d0a225e6ad43314c9aa7ea081f76adc5098ad4 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 7 Oct 2011 14:23:48 -0400
+Subject: drm/radeon/kms: handle !force case in connector detect more gracefully
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit d0d0a225e6ad43314c9aa7ea081f76adc5098ad4 upstream.
+
+When force == false, we don't do load detection in the connector
+detect functions.  Unforunately, we also return the previous
+connector state so we never get disconnect events for DVI-I, DVI-A,
+or VGA.  Save whether we detected the monitor via load detection
+previously and use that to determine whether we return the previous
+state or not.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=41561
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/radeon_connectors.c |   23 ++++++++++++++++++++---
+ drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
+ 2 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_connectors.c
++++ b/drivers/gpu/drm/radeon/radeon_connectors.c
+@@ -724,6 +724,7 @@ radeon_vga_detect(struct drm_connector *
+               dret = radeon_ddc_probe(radeon_connector,
+                                       radeon_connector->requires_extended_probe);
+       if (dret) {
++              radeon_connector->detected_by_load = false;
+               if (radeon_connector->edid) {
+                       kfree(radeon_connector->edid);
+                       radeon_connector->edid = NULL;
+@@ -750,12 +751,21 @@ radeon_vga_detect(struct drm_connector *
+       } else {
+               /* if we aren't forcing don't do destructive polling */
+-              if (!force)
+-                      return connector->status;
++              if (!force) {
++                      /* only return the previous status if we last
++                       * detected a monitor via load.
++                       */
++                      if (radeon_connector->detected_by_load)
++                              return connector->status;
++                      else
++                              return ret;
++              }
+               if (radeon_connector->dac_load_detect && encoder) {
+                       encoder_funcs = encoder->helper_private;
+                       ret = encoder_funcs->detect(encoder, connector);
++                      if (ret == connector_status_connected)
++                              radeon_connector->detected_by_load = true;
+               }
+       }
+@@ -897,6 +907,7 @@ radeon_dvi_detect(struct drm_connector *
+               dret = radeon_ddc_probe(radeon_connector,
+                                       radeon_connector->requires_extended_probe);
+       if (dret) {
++              radeon_connector->detected_by_load = false;
+               if (radeon_connector->edid) {
+                       kfree(radeon_connector->edid);
+                       radeon_connector->edid = NULL;
+@@ -964,8 +975,13 @@ radeon_dvi_detect(struct drm_connector *
+           (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
+               goto out;
++      /* if we aren't forcing don't do destructive polling */
+       if (!force) {
+-              ret = connector->status;
++              /* only return the previous status if we last
++               * detected a monitor via load.
++               */
++              if (radeon_connector->detected_by_load)
++                      ret = connector->status;
+               goto out;
+       }
+@@ -989,6 +1005,7 @@ radeon_dvi_detect(struct drm_connector *
+                                       ret = encoder_funcs->detect(encoder, connector);
+                                       if (ret == connector_status_connected) {
+                                               radeon_connector->use_digital = false;
++                                              radeon_connector->detected_by_load = true;
+                                       }
+                               }
+                               break;
+--- a/drivers/gpu/drm/radeon/radeon_mode.h
++++ b/drivers/gpu/drm/radeon/radeon_mode.h
+@@ -447,6 +447,7 @@ struct radeon_connector {
+       struct edid *edid;
+       void *con_priv;
+       bool dac_load_detect;
++      bool detected_by_load; /* if the connection status was determined by load */
+       uint16_t connector_object_id;
+       struct radeon_hpd hpd;
+       struct radeon_router router;
diff --git a/queue-3.1/ehci-introduce-a-common-ehci_setup.patch b/queue-3.1/ehci-introduce-a-common-ehci_setup.patch
new file mode 100644 (file)
index 0000000..6381fea
--- /dev/null
@@ -0,0 +1,57 @@
+From 2093c6b49c8f1dc581d8953aca71297d4cace55e Mon Sep 17 00:00:00 2001
+From: Matthieu CASTET <castet.matthieu@free.fr>
+Date: Sat, 2 Jul 2011 19:47:33 +0200
+Subject: EHCI : introduce a common ehci_setup
+
+From: Matthieu CASTET <castet.matthieu@free.fr>
+
+commit 2093c6b49c8f1dc581d8953aca71297d4cace55e upstream.
+
+This allow to clean duplicated code in most of SOC driver.
+
+Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-hcd.c |   29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -768,6 +768,35 @@ static int ehci_run (struct usb_hcd *hcd
+       return 0;
+ }
++static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
++{
++      struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++      int retval;
++
++      ehci->regs = (void __iomem *)ehci->caps +
++          HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
++      dbg_hcs_params(ehci, "reset");
++      dbg_hcc_params(ehci, "reset");
++
++      /* cache this readonly data; minimize chip reads */
++      ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
++
++      ehci->sbrn = HCD_USB2;
++
++      retval = ehci_halt(ehci);
++      if (retval)
++              return retval;
++
++      /* data structure init */
++      retval = ehci_init(hcd);
++      if (retval)
++              return retval;
++
++      ehci_reset(ehci);
++
++      return 0;
++}
++
+ /*-------------------------------------------------------------------------*/
+ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
diff --git a/queue-3.1/ehci-workaround-for-moschip-controller-bug.patch b/queue-3.1/ehci-workaround-for-moschip-controller-bug.patch
new file mode 100644 (file)
index 0000000..95ebde2
--- /dev/null
@@ -0,0 +1,170 @@
+From 68aa95d5d4de31c9348c1628ffa85c805305ebc5 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 12 Oct 2011 10:39:14 -0400
+Subject: EHCI: workaround for MosChip controller bug
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 68aa95d5d4de31c9348c1628ffa85c805305ebc5 upstream.
+
+This patch (as1489) works around a hardware bug in MosChip EHCI
+controllers.  Evidently when one of these controllers increments the
+frame-index register, it changes the three low-order bits (the
+microframe counter) before changing the higher order bits (the frame
+counter).  If the register is read at just the wrong time, the value
+obtained is too low by 8.
+
+When the appropriate quirk flag is set, we work around this problem by
+reading the frame-index register a second time if the first value's
+three low-order bits are all 0.  This gives the hardware a chance to
+finish updating the register, yielding the correct value.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Jason N Pitt <jpitt@fhcrc.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-dbg.c   |    2 +-
+ drivers/usb/host/ehci-hcd.c   |    3 +--
+ drivers/usb/host/ehci-pci.c   |    5 +++++
+ drivers/usb/host/ehci-sched.c |   30 +++++++++++++++++++++++++-----
+ drivers/usb/host/ehci.h       |   17 +++++++++++++++++
+ 5 files changed, 49 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -808,7 +808,7 @@ static ssize_t fill_registers_buffer(str
+       next += temp;
+       temp = scnprintf (next, size, "uframe %04x\n",
+-                      ehci_readl(ehci, &ehci->regs->frame_index));
++                      ehci_read_frame_index(ehci));
+       size -= temp;
+       next += temp;
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1195,8 +1195,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd,
+ static int ehci_get_frame (struct usb_hcd *hcd)
+ {
+       struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
+-      return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) %
+-              ehci->periodic_size;
++      return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size;
+ }
+ /*-------------------------------------------------------------------------*/
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -224,6 +224,11 @@ static int ehci_pci_setup(struct usb_hcd
+                       pci_dev_put(p_smbus);
+               }
+               break;
++      case PCI_VENDOR_ID_NETMOS:
++              /* MosChip frame-index-register bug */
++              ehci_info(ehci, "applying MosChip frame-index workaround\n");
++              ehci->frame_index_bug = 1;
++              break;
+       }
+       /* optional debug port, normally in the first BAR */
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -36,6 +36,27 @@
+ static int ehci_get_frame (struct usb_hcd *hcd);
++#ifdef CONFIG_PCI
++
++static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
++{
++      unsigned uf;
++
++      /*
++       * The MosChip MCS9990 controller updates its microframe counter
++       * a little before the frame counter, and occasionally we will read
++       * the invalid intermediate value.  Avoid problems by checking the
++       * microframe number (the low-order 3 bits); if they are 0 then
++       * re-read the register to get the correct value.
++       */
++      uf = ehci_readl(ehci, &ehci->regs->frame_index);
++      if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
++              uf = ehci_readl(ehci, &ehci->regs->frame_index);
++      return uf;
++}
++
++#endif
++
+ /*-------------------------------------------------------------------------*/
+ /*
+@@ -482,7 +503,7 @@ static int enable_periodic (struct ehci_
+       ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
+       /* make sure ehci_work scans these */
+-      ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
++      ehci->next_uframe = ehci_read_frame_index(ehci)
+               % (ehci->periodic_size << 3);
+       if (unlikely(ehci->broken_periodic))
+               ehci->last_periodic_enable = ktime_get_real();
+@@ -1409,7 +1430,7 @@ iso_stream_schedule (
+               goto fail;
+       }
+-      now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
++      now = ehci_read_frame_index(ehci) & (mod - 1);
+       /* Typical case: reuse current schedule, stream is still active.
+        * Hopefully there are no gaps from the host falling behind
+@@ -2276,7 +2297,7 @@ scan_periodic (struct ehci_hcd *ehci)
+        */
+       now_uframe = ehci->next_uframe;
+       if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+-              clock = ehci_readl(ehci, &ehci->regs->frame_index);
++              clock = ehci_read_frame_index(ehci);
+               clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+       } else  {
+               clock = now_uframe + mod - 1;
+@@ -2455,8 +2476,7 @@ restart:
+                                       || ehci->periodic_sched == 0)
+                               break;
+                       ehci->next_uframe = now_uframe;
+-                      now = ehci_readl(ehci, &ehci->regs->frame_index) &
+-                                      (mod - 1);
++                      now = ehci_read_frame_index(ehci) & (mod - 1);
+                       if (now_uframe == now)
+                               break;
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -139,6 +139,7 @@ struct ehci_hcd {                  /* one per controlle
+       unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
+       unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
+       unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
++      unsigned                frame_index_bug:1; /* MosChip (AKA NetMos) */
+       /* required for usb32 quirk */
+       #define OHCI_CTRL_HCFS          (3 << 6)
+@@ -737,6 +738,22 @@ static inline u32 hc32_to_cpup (const st
+ }
+ #endif
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef CONFIG_PCI
++
++/* For working around the MosChip frame-index-register bug */
++static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
++
++#else
++
++static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
++{
++      return ehci_readl(ehci, &ehci->regs->frame_index);
++}
++
++#endif
+ /*-------------------------------------------------------------------------*/
diff --git a/queue-3.1/mmc-core-ext_csd.raw_-used-in-comparison-but-never-set.patch b/queue-3.1/mmc-core-ext_csd.raw_-used-in-comparison-but-never-set.patch
new file mode 100644 (file)
index 0000000..e5daaa3
--- /dev/null
@@ -0,0 +1,43 @@
+From 5238acbe36dd5100fb6b035a995ae5fc89dd0708 Mon Sep 17 00:00:00 2001
+From: Andrei Warkentin <andrey.warkentin@gmail.com>
+Date: Sat, 24 Sep 2011 12:12:30 -0400
+Subject: mmc: core: ext_csd.raw_* used in comparison but never set
+
+From: Andrei Warkentin <andrey.warkentin@gmail.com>
+
+commit 5238acbe36dd5100fb6b035a995ae5fc89dd0708 upstream.
+
+f39b2dd9d ("mmc: core: Bus width testing needs to handle suspend/resume")
+added code to only compare read-only ext_csd fields in bus width testing
+code, yet it's comparing some fields that are never set.
+
+The affected fields are ext_csd.raw_erased_mem_count and
+ext_csd.raw_partition_support.
+
+Signed-off-by: Andrei Warkentin <andrey.warkentin@gmail.com>
+Acked-by: Philip Rakity <prakity@marvell.com>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mmc/core/mmc.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -359,6 +359,7 @@ static int mmc_read_ext_csd(struct mmc_c
+                * card has the Enhanced area enabled.  If so, export enhanced
+                * area offset and size to user by adding sysfs interface.
+                */
++              card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
+               if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+                   (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+                       u8 hc_erase_grp_sz =
+@@ -405,6 +406,7 @@ static int mmc_read_ext_csd(struct mmc_c
+       if (card->ext_csd.rev >= 5)
+               card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
++      card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
+       if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
+               card->erased_byte = 0xFF;
+       else
diff --git a/queue-3.1/mmc-core-fix-hangs-related-to-insert-remove-of-cards.patch b/queue-3.1/mmc-core-fix-hangs-related-to-insert-remove-of-cards.patch
new file mode 100644 (file)
index 0000000..16a1a6c
--- /dev/null
@@ -0,0 +1,128 @@
+From 7f7e4129c23f0419257184dff6fec89d2d5a8964 Mon Sep 17 00:00:00 2001
+From: Ulf Hansson <ulf.hansson@stericsson.com>
+Date: Wed, 21 Sep 2011 14:08:13 -0400
+Subject: mmc: core: Fix hangs related to insert/remove of cards
+
+From: Ulf Hansson <ulf.hansson@stericsson.com>
+
+commit 7f7e4129c23f0419257184dff6fec89d2d5a8964 upstream.
+
+During a rescan operation mmc_attach(sd|mmc|sdio) functions are
+called. The error handling in these function can trigger a detach
+of the bus, which also meant a power off. This is not notified by
+the rescan operation which then continues to the next attach function.
+
+If a power off has been done, the framework must never send any
+new commands to the host driver, without first doing a new power up.
+This will most likely trigger any host driver to hang.
+
+Moving power off out of detach and instead handle power off
+separately when it is actually needed, solves the issue.
+
+Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mmc/core/core.c |   10 +++++-----
+ drivers/mmc/core/core.h |    1 +
+ drivers/mmc/core/mmc.c  |    1 +
+ drivers/mmc/core/sd.c   |    1 +
+ drivers/mmc/core/sdio.c |    1 +
+ 5 files changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -1151,7 +1151,7 @@ static void mmc_power_up(struct mmc_host
+       mmc_host_clk_release(host);
+ }
+-static void mmc_power_off(struct mmc_host *host)
++void mmc_power_off(struct mmc_host *host)
+ {
+       mmc_host_clk_hold(host);
+@@ -1241,8 +1241,7 @@ void mmc_attach_bus(struct mmc_host *hos
+ }
+ /*
+- * Remove the current bus handler from a host. Assumes that there are
+- * no interesting cards left, so the bus is powered down.
++ * Remove the current bus handler from a host.
+  */
+ void mmc_detach_bus(struct mmc_host *host)
+ {
+@@ -1259,8 +1258,6 @@ void mmc_detach_bus(struct mmc_host *hos
+       spin_unlock_irqrestore(&host->lock, flags);
+-      mmc_power_off(host);
+-
+       mmc_bus_put(host);
+ }
+@@ -1845,6 +1842,7 @@ void mmc_stop_host(struct mmc_host *host
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
++              mmc_power_off(host);
+               mmc_release_host(host);
+               mmc_bus_put(host);
+               return;
+@@ -1974,6 +1972,7 @@ int mmc_suspend_host(struct mmc_host *ho
+                               host->bus_ops->remove(host);
+                       mmc_claim_host(host);
+                       mmc_detach_bus(host);
++                      mmc_power_off(host);
+                       mmc_release_host(host);
+                       host->pm_flags = 0;
+                       err = 0;
+@@ -2061,6 +2060,7 @@ int mmc_pm_notify(struct notifier_block
+                       host->bus_ops->remove(host);
+               mmc_detach_bus(host);
++              mmc_power_off(host);
+               mmc_release_host(host);
+               host->pm_flags = 0;
+               break;
+--- a/drivers/mmc/core/core.h
++++ b/drivers/mmc/core/core.h
+@@ -43,6 +43,7 @@ int mmc_set_signal_voltage(struct mmc_ho
+                          bool cmd11);
+ void mmc_set_timing(struct mmc_host *host, unsigned int timing);
+ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
++void mmc_power_off(struct mmc_host *host);
+ static inline void mmc_delay(unsigned int ms)
+ {
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -891,6 +891,7 @@ static void mmc_detect(struct mmc_host *
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
++              mmc_power_off(host);
+               mmc_release_host(host);
+       }
+ }
+--- a/drivers/mmc/core/sd.c
++++ b/drivers/mmc/core/sd.c
+@@ -1043,6 +1043,7 @@ static void mmc_sd_detect(struct mmc_hos
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
++              mmc_power_off(host);
+               mmc_release_host(host);
+       }
+ }
+--- a/drivers/mmc/core/sdio.c
++++ b/drivers/mmc/core/sdio.c
+@@ -597,6 +597,7 @@ out:
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
++              mmc_power_off(host);
+               mmc_release_host(host);
+       }
+ }
diff --git a/queue-3.1/pci-quirk-mmc-always-check-for-lower-base-frequency-quirk-for-ricoh-1180-e823.patch b/queue-3.1/pci-quirk-mmc-always-check-for-lower-base-frequency-quirk-for-ricoh-1180-e823.patch
new file mode 100644 (file)
index 0000000..91d81cb
--- /dev/null
@@ -0,0 +1,74 @@
+From 3e309cdf07c930f29a4e0f233e47d399bea34c68 Mon Sep 17 00:00:00 2001
+From: Josh Boyer <jwboyer@redhat.com>
+Date: Wed, 5 Oct 2011 11:44:50 -0400
+Subject: PCI quirk: mmc: Always check for lower base frequency quirk for Ricoh 1180:e823
+
+From: Josh Boyer <jwboyer@redhat.com>
+
+commit 3e309cdf07c930f29a4e0f233e47d399bea34c68 upstream.
+
+Commit 15bed0f2f added a quirk for the e823 Ricoh card reader to lower the
+base frequency.  However, the quirk first checks to see if the proprietary
+MMC controller is disabled, and returns if so.  On some devices, such as the
+Lenovo X220, the MMC controller is already disabled by firmware it seems,
+but the frequency change is still needed so sdhci-pci can talk to the cards.
+Since the MMC controller is disabled, the frequency fixup was never being run
+on these machines.
+
+This moves the e823 check above the MMC controller check so that it always
+gets run.
+
+This fixes https://bugzilla.redhat.com/show_bug.cgi?id=722509
+
+Signed-off-by: Josh Boyer <jwboyer@redhat.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/quirks.c |   28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struc
+       /* disable must be done via function #0 */
+       if (PCI_FUNC(dev->devfn))
+               return;
+-
+-      pci_read_config_byte(dev, 0xCB, &disable);
+-
+-      if (disable & 0x02)
+-              return;
+-
+-      pci_read_config_byte(dev, 0xCA, &write_enable);
+-      pci_write_config_byte(dev, 0xCA, 0x57);
+-      pci_write_config_byte(dev, 0xCB, disable | 0x02);
+-      pci_write_config_byte(dev, 0xCA, write_enable);
+-
+-      dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
+-      dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+-
+       /*
+        * RICOH 0xe823 SD/MMC card reader fails to recognize
+        * certain types of SD/MMC cards. Lowering the SD base
+@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struc
+               dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n");
+       }
++
++      pci_read_config_byte(dev, 0xCB, &disable);
++
++      if (disable & 0x02)
++              return;
++
++      pci_read_config_byte(dev, 0xCA, &write_enable);
++      pci_write_config_byte(dev, 0xCA, 0x57);
++      pci_write_config_byte(dev, 0xCB, disable | 0x02);
++      pci_write_config_byte(dev, 0xCA, write_enable);
++
++      dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
++      dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
++
+ }
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
index a40d310807b8e9b0d55f2b7663d898c111227d0d..3f0d2746a4221f48095387451870db2ed1c87732 100644 (file)
@@ -13,3 +13,18 @@ usb-qcserial-add-support-for-sierra-wireless-mc8355-gobi-3000.patch
 usb-qcserial-add-device-id-for-hp-un2430-mobile-broadband-module.patch
 serial-pxa-work-around-for-errata-20.patch
 serial-core-power-up-uart-port-early-before-we-do-set_termios-when-resuming.patch
+ehci-introduce-a-common-ehci_setup.patch
+usb-fix-ehci-alignment-error.patch
+ehci-workaround-for-moschip-controller-bug.patch
+xhci-mem.c-check-for-ring-first_seg-null.patch
+xhci-amd-isoc-link-trb-chain-bit-quirk.patch
+drm-i915-wrap-dp-edid-fetch-functions-to-enable-edp-panel.patch
+drm-i915-panel-always-record-the-backlight-level-again-but-cleverly.patch
+drm-i915-fix-ilk-infoframe-support.patch
+drm-i915-use-correct-spd-type-value.patch
+drm-radeon-kms-bail-early-in-dvi_detect-for-digital-only-connectors.patch
+drm-radeon-kms-handle-force-case-in-connector-detect-more-gracefully.patch
+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
diff --git a/queue-3.1/usb-fix-ehci-alignment-error.patch b/queue-3.1/usb-fix-ehci-alignment-error.patch
new file mode 100644 (file)
index 0000000..20400cf
--- /dev/null
@@ -0,0 +1,32 @@
+From 276532ba9666b36974cbe16f303fc8be99c9da17 Mon Sep 17 00:00:00 2001
+From: Harro Haan <hrhaan@gmail.com>
+Date: Mon, 10 Oct 2011 14:38:27 +0200
+Subject: USB: fix ehci alignment error
+
+From: Harro Haan <hrhaan@gmail.com>
+
+commit 276532ba9666b36974cbe16f303fc8be99c9da17 upstream.
+
+The Kirkwood gave an unaligned memory access error on
+line 742 of drivers/usb/host/echi-hcd.c:
+"ehci->last_periodic_enable = ktime_get_real();"
+
+Signed-off-by: Harro Haan <hrhaan@gmail.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb/hcd.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -178,7 +178,7 @@ struct usb_hcd {
+        * this structure.
+        */
+       unsigned long hcd_priv[0]
+-                      __attribute__ ((aligned(sizeof(unsigned long))));
++                      __attribute__ ((aligned(sizeof(s64))));
+ };
+ /* 2.4 does this a bit differently ... */
diff --git a/queue-3.1/xhci-amd-isoc-link-trb-chain-bit-quirk.patch b/queue-3.1/xhci-amd-isoc-link-trb-chain-bit-quirk.patch
new file mode 100644 (file)
index 0000000..2d8f2bc
--- /dev/null
@@ -0,0 +1,392 @@
+From 7e393a834b41001174a8fb3ae3bc23a749467760 Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Fri, 23 Sep 2011 14:19:54 -0700
+Subject: xHCI: AMD isoc link TRB chain bit quirk
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit 7e393a834b41001174a8fb3ae3bc23a749467760 upstream.
+
+Setting the chain (CH) bit in the link TRB of isochronous transfer rings
+is required by AMD 0.96 xHCI host controller to successfully transverse
+multi-TRB TD that span through different memory segments.
+
+When a Missed Service Error event occurs, if the chain bit is not set in
+the link TRB and the host skips TDs which just across a link TRB, the
+host may falsely recognize the link TRB as a normal TRB. You can see
+this may cause big trouble - the host does not jump to the right address
+which is pointed by the link TRB, but continue fetching the memory which
+is after the link TRB address, which may not even belong to the host,
+and the result cannot be predicted.
+
+This causes some big problems. Without the former patch I sent: "xHCI:
+prevent infinite loop when processing MSE event", the system may hang.
+With that patch applied, system does not hang, but the host still access
+wrong memory address and isoc transfer will fail. With this patch,
+isochronous transfer works as expected.
+
+This patch should be applied to kernels as old as 2.6.36, which was when
+the first isochronous support was added for the xHCI host controller.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c  |   32 ++++++++++++++-----------
+ drivers/usb/host/xhci-pci.c  |    3 ++
+ drivers/usb/host/xhci-ring.c |   53 +++++++++++++++++++++++--------------------
+ drivers/usb/host/xhci.h      |    1 
+ 4 files changed, 51 insertions(+), 38 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -81,7 +81,7 @@ static void xhci_segment_free(struct xhc
+  * related flags, such as End TRB, Toggle Cycle, and no snoop.
+  */
+ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
+-              struct xhci_segment *next, bool link_trbs)
++              struct xhci_segment *next, bool link_trbs, bool isoc)
+ {
+       u32 val;
+@@ -97,7 +97,9 @@ static void xhci_link_segments(struct xh
+               val &= ~TRB_TYPE_BITMASK;
+               val |= TRB_TYPE(TRB_LINK);
+               /* Always set the chain bit with 0.95 hardware */
+-              if (xhci_link_trb_quirk(xhci))
++              /* Set chain bit for isoc rings on AMD 0.96 host */
++              if (xhci_link_trb_quirk(xhci) ||
++                              (isoc && (xhci->quirks & XHCI_AMD_0x96_HOST)))
+                       val |= TRB_CHAIN;
+               prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
+       }
+@@ -154,7 +156,7 @@ static void xhci_initialize_ring_info(st
+  * See section 4.9.1 and figures 15 and 16.
+  */
+ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
+-              unsigned int num_segs, bool link_trbs, gfp_t flags)
++              unsigned int num_segs, bool link_trbs, bool isoc, gfp_t flags)
+ {
+       struct xhci_ring        *ring;
+       struct xhci_segment     *prev;
+@@ -180,12 +182,12 @@ static struct xhci_ring *xhci_ring_alloc
+               next = xhci_segment_alloc(xhci, flags);
+               if (!next)
+                       goto fail;
+-              xhci_link_segments(xhci, prev, next, link_trbs);
++              xhci_link_segments(xhci, prev, next, link_trbs, isoc);
+               prev = next;
+               num_segs--;
+       }
+-      xhci_link_segments(xhci, prev, ring->first_seg, link_trbs);
++      xhci_link_segments(xhci, prev, ring->first_seg, link_trbs, isoc);
+       if (link_trbs) {
+               /* See section 4.9.2.1 and 6.4.4.1 */
+@@ -231,14 +233,14 @@ void xhci_free_or_cache_endpoint_ring(st
+  * pointers to the beginning of the ring.
+  */
+ static void xhci_reinit_cached_ring(struct xhci_hcd *xhci,
+-              struct xhci_ring *ring)
++              struct xhci_ring *ring, bool isoc)
+ {
+       struct xhci_segment     *seg = ring->first_seg;
+       do {
+               memset(seg->trbs, 0,
+                               sizeof(union xhci_trb)*TRBS_PER_SEGMENT);
+               /* All endpoint rings have link TRBs */
+-              xhci_link_segments(xhci, seg, seg->next, 1);
++              xhci_link_segments(xhci, seg, seg->next, 1, isoc);
+               seg = seg->next;
+       } while (seg != ring->first_seg);
+       xhci_initialize_ring_info(ring);
+@@ -542,7 +544,7 @@ struct xhci_stream_info *xhci_alloc_stre
+        */
+       for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
+               stream_info->stream_rings[cur_stream] =
+-                      xhci_ring_alloc(xhci, 1, true, mem_flags);
++                      xhci_ring_alloc(xhci, 1, true, false, mem_flags);
+               cur_ring = stream_info->stream_rings[cur_stream];
+               if (!cur_ring)
+                       goto cleanup_rings;
+@@ -767,7 +769,7 @@ int xhci_alloc_virt_device(struct xhci_h
+       }
+       /* Allocate endpoint 0 ring */
+-      dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags);
++      dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, false, flags);
+       if (!dev->eps[0].ring)
+               goto fail;
+@@ -1177,10 +1179,10 @@ int xhci_endpoint_init(struct xhci_hcd *
+        */
+       if (usb_endpoint_xfer_isoc(&ep->desc))
+               virt_dev->eps[ep_index].new_ring =
+-                      xhci_ring_alloc(xhci, 8, true, mem_flags);
++                      xhci_ring_alloc(xhci, 8, true, true, mem_flags);
+       else
+               virt_dev->eps[ep_index].new_ring =
+-                      xhci_ring_alloc(xhci, 1, true, mem_flags);
++                      xhci_ring_alloc(xhci, 1, true, false, mem_flags);
+       if (!virt_dev->eps[ep_index].new_ring) {
+               /* Attempt to use the ring cache */
+               if (virt_dev->num_rings_cached == 0)
+@@ -1189,7 +1191,8 @@ int xhci_endpoint_init(struct xhci_hcd *
+                       virt_dev->ring_cache[virt_dev->num_rings_cached];
+               virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
+               virt_dev->num_rings_cached--;
+-              xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring);
++              xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
++                      usb_endpoint_xfer_isoc(&ep->desc) ? true : false);
+       }
+       virt_dev->eps[ep_index].skip = false;
+       ep_ring = virt_dev->eps[ep_index].new_ring;
+@@ -2003,7 +2006,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+               goto fail;
+       /* Set up the command ring to have one segments for now. */
+-      xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, flags);
++      xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, false, flags);
+       if (!xhci->cmd_ring)
+               goto fail;
+       xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
+@@ -2034,7 +2037,8 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+        * the event ring segment table (ERST).  Section 4.9.3.
+        */
+       xhci_dbg(xhci, "// Allocating event ring\n");
+-      xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, flags);
++      xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, false,
++                                              flags);
+       if (!xhci->event_ring)
+               goto fail;
+       if (xhci_check_trb_in_td_math(xhci, flags) < 0)
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -128,6 +128,9 @@ static int xhci_pci_setup(struct usb_hcd
+       if (pdev->vendor == PCI_VENDOR_ID_NEC)
+               xhci->quirks |= XHCI_NEC_HOST;
++      if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96)
++              xhci->quirks |= XHCI_AMD_0x96_HOST;
++
+       /* AMD PLL quirk */
+       if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
+               xhci->quirks |= XHCI_AMD_PLL_FIX;
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -185,7 +185,7 @@ static void inc_deq(struct xhci_hcd *xhc
+  *                    prepare_transfer()?
+  */
+ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+-              bool consumer, bool more_trbs_coming)
++              bool consumer, bool more_trbs_coming, bool isoc)
+ {
+       u32 chain;
+       union xhci_trb *next;
+@@ -212,11 +212,13 @@ static void inc_enq(struct xhci_hcd *xhc
+                               if (!chain && !more_trbs_coming)
+                                       break;
+-                              /* If we're not dealing with 0.95 hardware,
++                              /* If we're not dealing with 0.95 hardware or
++                               * isoc rings on AMD 0.96 host,
+                                * carry over the chain bit of the previous TRB
+                                * (which may mean the chain bit is cleared).
+                                */
+-                              if (!xhci_link_trb_quirk(xhci)) {
++                              if (!(isoc && (xhci->quirks & XHCI_AMD_0x96_HOST))
++                                              && !xhci_link_trb_quirk(xhci)) {
+                                       next->link.control &=
+                                               cpu_to_le32(~TRB_CHAIN);
+                                       next->link.control |=
+@@ -2409,7 +2411,7 @@ irqreturn_t xhci_msi_irq(int irq, struct
+  *                    prepare_transfer()?
+  */
+ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
+-              bool consumer, bool more_trbs_coming,
++              bool consumer, bool more_trbs_coming, bool isoc,
+               u32 field1, u32 field2, u32 field3, u32 field4)
+ {
+       struct xhci_generic_trb *trb;
+@@ -2419,7 +2421,7 @@ static void queue_trb(struct xhci_hcd *x
+       trb->field[1] = cpu_to_le32(field2);
+       trb->field[2] = cpu_to_le32(field3);
+       trb->field[3] = cpu_to_le32(field4);
+-      inc_enq(xhci, ring, consumer, more_trbs_coming);
++      inc_enq(xhci, ring, consumer, more_trbs_coming, isoc);
+ }
+ /*
+@@ -2427,7 +2429,7 @@ static void queue_trb(struct xhci_hcd *x
+  * FIXME allocate segments if the ring is full.
+  */
+ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
+-              u32 ep_state, unsigned int num_trbs, gfp_t mem_flags)
++              u32 ep_state, unsigned int num_trbs, bool isoc, gfp_t mem_flags)
+ {
+       /* Make sure the endpoint has been added to xHC schedule */
+       switch (ep_state) {
+@@ -2469,10 +2471,11 @@ static int prepare_ring(struct xhci_hcd
+               next = ring->enqueue;
+               while (last_trb(xhci, ring, ring->enq_seg, next)) {
+-                      /* If we're not dealing with 0.95 hardware,
+-                       * clear the chain bit.
++                      /* If we're not dealing with 0.95 hardware or isoc rings
++                       * on AMD 0.96 host, clear the chain bit.
+                        */
+-                      if (!xhci_link_trb_quirk(xhci))
++                      if (!xhci_link_trb_quirk(xhci) && !(isoc &&
++                                      (xhci->quirks & XHCI_AMD_0x96_HOST)))
+                               next->link.control &= cpu_to_le32(~TRB_CHAIN);
+                       else
+                               next->link.control |= cpu_to_le32(TRB_CHAIN);
+@@ -2505,6 +2508,7 @@ static int prepare_transfer(struct xhci_
+               unsigned int num_trbs,
+               struct urb *urb,
+               unsigned int td_index,
++              bool isoc,
+               gfp_t mem_flags)
+ {
+       int ret;
+@@ -2522,7 +2526,7 @@ static int prepare_transfer(struct xhci_
+       ret = prepare_ring(xhci, ep_ring,
+                          le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
+-                         num_trbs, mem_flags);
++                         num_trbs, isoc, mem_flags);
+       if (ret)
+               return ret;
+@@ -2745,7 +2749,7 @@ static int queue_bulk_sg_tx(struct xhci_
+       trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+                       ep_index, urb->stream_id,
+-                      num_trbs, urb, 0, mem_flags);
++                      num_trbs, urb, 0, false, mem_flags);
+       if (trb_buff_len < 0)
+               return trb_buff_len;
+@@ -2840,7 +2844,7 @@ static int queue_bulk_sg_tx(struct xhci_
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+-              queue_trb(xhci, ep_ring, false, more_trbs_coming,
++              queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
+                               lower_32_bits(addr),
+                               upper_32_bits(addr),
+                               length_field,
+@@ -2931,7 +2935,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+       ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                       ep_index, urb->stream_id,
+-                      num_trbs, urb, 0, mem_flags);
++                      num_trbs, urb, 0, false, mem_flags);
+       if (ret < 0)
+               return ret;
+@@ -3003,7 +3007,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+-              queue_trb(xhci, ep_ring, false, more_trbs_coming,
++              queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
+                               lower_32_bits(addr),
+                               upper_32_bits(addr),
+                               length_field,
+@@ -3063,7 +3067,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+               num_trbs++;
+       ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                       ep_index, urb->stream_id,
+-                      num_trbs, urb, 0, mem_flags);
++                      num_trbs, urb, 0, false, mem_flags);
+       if (ret < 0)
+               return ret;
+@@ -3096,7 +3100,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+               }
+       }
+-      queue_trb(xhci, ep_ring, false, true,
++      queue_trb(xhci, ep_ring, false, true, false,
+                 setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16,
+                 le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16,
+                 TRB_LEN(8) | TRB_INTR_TARGET(0),
+@@ -3116,7 +3120,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+       if (urb->transfer_buffer_length > 0) {
+               if (setup->bRequestType & USB_DIR_IN)
+                       field |= TRB_DIR_IN;
+-              queue_trb(xhci, ep_ring, false, true,
++              queue_trb(xhci, ep_ring, false, true, false,
+                               lower_32_bits(urb->transfer_dma),
+                               upper_32_bits(urb->transfer_dma),
+                               length_field,
+@@ -3132,7 +3136,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+               field = 0;
+       else
+               field = TRB_DIR_IN;
+-      queue_trb(xhci, ep_ring, false, false,
++      queue_trb(xhci, ep_ring, false, false, false,
+                       0,
+                       0,
+                       TRB_INTR_TARGET(0),
+@@ -3281,7 +3285,8 @@ static int xhci_queue_isoc_tx(struct xhc
+               trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
+               ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
+-                              urb->stream_id, trbs_per_td, urb, i, mem_flags);
++                              urb->stream_id, trbs_per_td, urb, i, true,
++                              mem_flags);
+               if (ret < 0) {
+                       if (i == 0)
+                               return ret;
+@@ -3351,7 +3356,7 @@ static int xhci_queue_isoc_tx(struct xhc
+                               remainder |
+                               TRB_INTR_TARGET(0);
+-                      queue_trb(xhci, ep_ring, false, more_trbs_coming,
++                      queue_trb(xhci, ep_ring, false, more_trbs_coming, true,
+                               lower_32_bits(addr),
+                               upper_32_bits(addr),
+                               length_field,
+@@ -3433,7 +3438,7 @@ int xhci_queue_isoc_tx_prepare(struct xh
+        * Do not insert any td of the urb to the ring if the check failed.
+        */
+       ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
+-                         num_trbs, mem_flags);
++                         num_trbs, true, mem_flags);
+       if (ret)
+               return ret;
+@@ -3492,7 +3497,7 @@ static int queue_command(struct xhci_hcd
+               reserved_trbs++;
+       ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
+-                      reserved_trbs, GFP_ATOMIC);
++                      reserved_trbs, false, GFP_ATOMIC);
+       if (ret < 0) {
+               xhci_err(xhci, "ERR: No room for command on command ring\n");
+               if (command_must_succeed)
+@@ -3500,8 +3505,8 @@ static int queue_command(struct xhci_hcd
+                                       "unfailable commands failed.\n");
+               return ret;
+       }
+-      queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
+-                      field4 | xhci->cmd_ring->cycle_state);
++      queue_trb(xhci, xhci->cmd_ring, false, false, false, field1, field2,
++                      field3, field4 | xhci->cmd_ring->cycle_state);
+       return 0;
+ }
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1318,6 +1318,7 @@ struct xhci_hcd {
+ #define XHCI_EP_LIMIT_QUIRK   (1 << 5)
+ #define XHCI_BROKEN_MSI               (1 << 6)
+ #define XHCI_RESET_ON_RESUME  (1 << 7)
++#define XHCI_AMD_0x96_HOST    (1 << 9)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
+       /* There are two roothubs to keep track of bus suspend info for */
diff --git a/queue-3.1/xhci-mem.c-check-for-ring-first_seg-null.patch b/queue-3.1/xhci-mem.c-check-for-ring-first_seg-null.patch
new file mode 100644 (file)
index 0000000..a607bd3
--- /dev/null
@@ -0,0 +1,61 @@
+From 0e6c7f746ea99089fb3263709075c20485a479ae Mon Sep 17 00:00:00 2001
+From: Kautuk Consul <consul.kautuk@gmail.com>
+Date: Mon, 19 Sep 2011 16:53:12 -0700
+Subject: xhci-mem.c: Check for ring->first_seg != NULL
+
+From: Kautuk Consul <consul.kautuk@gmail.com>
+
+commit 0e6c7f746ea99089fb3263709075c20485a479ae upstream.
+
+There are 2 situations wherein the xhci_ring* might not get freed:
+- When xhci_ring_alloc() -> xhci_segment_alloc() returns NULL and
+  we goto the fail: label in xhci_ring_alloc. In this case, the ring
+  will not get kfreed.
+- When the num_segs argument to xhci_ring_alloc is passed as 0 and
+  we try to free the rung after that.
+  ( This doesn't really happen as of now in the code but we seem to
+    be entertaining num_segs=0 in xhci_ring_alloc )
+
+This should be backported to kernels as old as 2.6.31.
+
+Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c |   22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -112,18 +112,20 @@ void xhci_ring_free(struct xhci_hcd *xhc
+       struct xhci_segment *seg;
+       struct xhci_segment *first_seg;
+-      if (!ring || !ring->first_seg)
++      if (!ring)
+               return;
+-      first_seg = ring->first_seg;
+-      seg = first_seg->next;
+-      xhci_dbg(xhci, "Freeing ring at %p\n", ring);
+-      while (seg != first_seg) {
+-              struct xhci_segment *next = seg->next;
+-              xhci_segment_free(xhci, seg);
+-              seg = next;
++      if (ring->first_seg) {
++              first_seg = ring->first_seg;
++              seg = first_seg->next;
++              xhci_dbg(xhci, "Freeing ring at %p\n", ring);
++              while (seg != first_seg) {
++                      struct xhci_segment *next = seg->next;
++                      xhci_segment_free(xhci, seg);
++                      seg = next;
++              }
++              xhci_segment_free(xhci, first_seg);
++              ring->first_seg = NULL;
+       }
+-      xhci_segment_free(xhci, first_seg);
+-      ring->first_seg = NULL;
+       kfree(ring);
+ }