From: Greg Kroah-Hartman Date: Tue, 1 Nov 2011 18:51:23 +0000 (-0700) Subject: 3.1 patches X-Git-Tag: v3.0.9~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0aa785a292ee80bfa37d44f7b86c5d4652ae519;p=thirdparty%2Fkernel%2Fstable-queue.git 3.1 patches --- 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 index 00000000000..71ee8096f0e --- /dev/null +++ b/queue-3.1/drm-i915-fix-ilk-infoframe-support.patch @@ -0,0 +1,84 @@ +From 64a8fc0145a1d0fdc25fc9367c2e6c621955fb3b Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Thu, 22 Sep 2011 11:16:00 +0530 +Subject: drm/i915: fix ILK+ infoframe support + +From: Jesse Barnes + +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 +Signed-off-by: Keith Packard +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..be82c4a018e --- /dev/null +++ b/queue-3.1/drm-i915-panel-always-record-the-backlight-level-again-but-cleverly.patch @@ -0,0 +1,80 @@ +From f52c619a590fa75276c07dfcaf380dee53e4ea4c Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 14 Oct 2011 11:45:40 +0200 +Subject: drm/i915/panel: Always record the backlight level again (but cleverly) + +From: Takashi Iwai + +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 +Reviewed-by: Keith Packard +Signed-off-by: Keith Packard +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7379e70c69a --- /dev/null +++ b/queue-3.1/drm-i915-use-correct-spd-type-value.patch @@ -0,0 +1,30 @@ +From 260052100ef669b5374f72055379adc5da35034b Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Thu, 22 Sep 2011 11:16:01 +0530 +Subject: drm/i915: use correct SPD type value + +From: Jesse Barnes + +commit 260052100ef669b5374f72055379adc5da35034b upstream. + +SPD frames are actually type 0x83, not just 0x3. + +Signed-off-by: Jesse Barnes +Signed-off-by: Keith Packard +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f80db37ea5b --- /dev/null +++ b/queue-3.1/drm-i915-wrap-dp-edid-fetch-functions-to-enable-edp-panel.patch @@ -0,0 +1,83 @@ +From 8c241fef3e6f69f3f675678ae03599ece3f562e2 Mon Sep 17 00:00:00 2001 +From: Keith Packard +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 + +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 +Reviewed-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c865312a38b --- /dev/null +++ b/queue-3.1/drm-radeon-kms-bail-early-in-dvi_detect-for-digital-only-connectors.patch @@ -0,0 +1,41 @@ +From 5f0a26128d66ef81613fe923d5c288942844ccdc Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..bedfff23fca --- /dev/null +++ b/queue-3.1/drm-radeon-kms-fix-i2c-mask-definitions.patch @@ -0,0 +1,37 @@ +From 286e0c94f9c3f292cb38a977fbbde3433347a868 Mon Sep 17 00:00:00 2001 +From: Jean Delvare +Date: Thu, 6 Oct 2011 18:16:24 +0200 +Subject: drm/radeon/kms: Fix I2C mask definitions + +From: Jean Delvare + +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 +Reviewed-by: Alex Deucher +Cc: Jerome Glisse +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..278f2d12be4 --- /dev/null +++ b/queue-3.1/drm-radeon-kms-handle-force-case-in-connector-detect-more-gracefully.patch @@ -0,0 +1,103 @@ +From d0d0a225e6ad43314c9aa7ea081f76adc5098ad4 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 7 Oct 2011 14:23:48 -0400 +Subject: drm/radeon/kms: handle !force case in connector detect more gracefully + +From: Alex Deucher + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6381fea8d82 --- /dev/null +++ b/queue-3.1/ehci-introduce-a-common-ehci_setup.patch @@ -0,0 +1,57 @@ +From 2093c6b49c8f1dc581d8953aca71297d4cace55e Mon Sep 17 00:00:00 2001 +From: Matthieu CASTET +Date: Sat, 2 Jul 2011 19:47:33 +0200 +Subject: EHCI : introduce a common ehci_setup + +From: Matthieu CASTET + +commit 2093c6b49c8f1dc581d8953aca71297d4cace55e upstream. + +This allow to clean duplicated code in most of SOC driver. + +Signed-off-by: Matthieu CASTET +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..95ebde2b98d --- /dev/null +++ b/queue-3.1/ehci-workaround-for-moschip-controller-bug.patch @@ -0,0 +1,170 @@ +From 68aa95d5d4de31c9348c1628ffa85c805305ebc5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 12 Oct 2011 10:39:14 -0400 +Subject: EHCI: workaround for MosChip controller bug + +From: Alan Stern + +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 +Tested-by: Jason N Pitt +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e5daaa3f7ce --- /dev/null +++ b/queue-3.1/mmc-core-ext_csd.raw_-used-in-comparison-but-never-set.patch @@ -0,0 +1,43 @@ +From 5238acbe36dd5100fb6b035a995ae5fc89dd0708 Mon Sep 17 00:00:00 2001 +From: Andrei Warkentin +Date: Sat, 24 Sep 2011 12:12:30 -0400 +Subject: mmc: core: ext_csd.raw_* used in comparison but never set + +From: Andrei Warkentin + +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 +Acked-by: Philip Rakity +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..16a1a6c1b39 --- /dev/null +++ b/queue-3.1/mmc-core-fix-hangs-related-to-insert-remove-of-cards.patch @@ -0,0 +1,128 @@ +From 7f7e4129c23f0419257184dff6fec89d2d5a8964 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Wed, 21 Sep 2011 14:08:13 -0400 +Subject: mmc: core: Fix hangs related to insert/remove of cards + +From: Ulf Hansson + +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 +Acked-by: Linus Walleij +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..91d81cbeba4 --- /dev/null +++ b/queue-3.1/pci-quirk-mmc-always-check-for-lower-base-frequency-quirk-for-ricoh-1180-e823.patch @@ -0,0 +1,74 @@ +From 3e309cdf07c930f29a4e0f233e47d399bea34c68 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +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 + +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 +Signed-off-by: Jesse Barnes +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.1/series b/queue-3.1/series index a40d310807b..3f0d2746a42 100644 --- a/queue-3.1/series +++ b/queue-3.1/series @@ -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 index 00000000000..20400cf0e92 --- /dev/null +++ b/queue-3.1/usb-fix-ehci-alignment-error.patch @@ -0,0 +1,32 @@ +From 276532ba9666b36974cbe16f303fc8be99c9da17 Mon Sep 17 00:00:00 2001 +From: Harro Haan +Date: Mon, 10 Oct 2011 14:38:27 +0200 +Subject: USB: fix ehci alignment error + +From: Harro Haan + +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 +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2d8f2bc1d39 --- /dev/null +++ b/queue-3.1/xhci-amd-isoc-link-trb-chain-bit-quirk.patch @@ -0,0 +1,392 @@ +From 7e393a834b41001174a8fb3ae3bc23a749467760 Mon Sep 17 00:00:00 2001 +From: Andiry Xu +Date: Fri, 23 Sep 2011 14:19:54 -0700 +Subject: xHCI: AMD isoc link TRB chain bit quirk + +From: Andiry Xu + +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 +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a607bd3bd1f --- /dev/null +++ b/queue-3.1/xhci-mem.c-check-for-ring-first_seg-null.patch @@ -0,0 +1,61 @@ +From 0e6c7f746ea99089fb3263709075c20485a479ae Mon Sep 17 00:00:00 2001 +From: Kautuk Consul +Date: Mon, 19 Sep 2011 16:53:12 -0700 +Subject: xhci-mem.c: Check for ring->first_seg != NULL + +From: Kautuk Consul + +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 +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } +