summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libre/linux-libre/PKGBUILD50
-rw-r--r--libre/linux-libre/config.i6865
-rw-r--r--libre/linux-libre/config.x86_645
-rw-r--r--libre/linux-libre/dib0700-fix.patch1487
-rw-r--r--libre/linux-libre/i915-fix-ghost-tv-output.patch26
-rw-r--r--libre/linux-libre/i915-fix-incorrect-error-message.patch22
-rw-r--r--libre/linux-libre/iwlagn-fix-NULL-pointer-dereference.patch38
-rw-r--r--libre/linux-libre/linux-libre.install7
-rw-r--r--libre/linux-libre/md-raid10-fix-bug-when-activating-a-hot-spare.patch41
-rw-r--r--libre/linux-libre/usb-add-reset-resume-quirk-for-several-webcams.patch99
10 files changed, 1755 insertions, 25 deletions
diff --git a/libre/linux-libre/PKGBUILD b/libre/linux-libre/PKGBUILD
index 062efe27e..341b508e2 100644
--- a/libre/linux-libre/PKGBUILD
+++ b/libre/linux-libre/PKGBUILD
@@ -9,30 +9,51 @@ pkgname=('linux-libre' 'linux-libre-headers' 'linux-libre-docs') # Build stock -
# pkgname=linux-custom # Build kernel with a different name
_kernelname=${pkgname#linux-libre}
_basekernel=3.1
-pkgver=${_basekernel}
-pkgrel=2
+pkgver=${_basekernel}.2
+pkgrel=1
arch=('i686' 'x86_64')
url="http://linux-libre.fsfla.org/"
license=('GPL2')
makedepends=('xmlto' 'docbook-xsl')
options=('!strip')
source=("http://linux-libre.fsfla.org/pub/linux-libre/releases/${_basekernel}-libre/linux-${_basekernel}-libre.tar.xz"
- # "http://linux-libre.fsfla.org/pub/linux-libre/releases/${pkgver}-libre/patch-${_basekernel}-libre-${pkgver}-libre.xz"
+ "http://linux-libre.fsfla.org/pub/linux-libre/releases/${pkgver}-libre/patch-${_basekernel}-libre-${pkgver}-libre.xz"
# the main kernel config files
'config.i686' 'config.x86_64'
# standard config files for mkinitcpio ramdisk
"${pkgname}.preset"
'boot-logo.patch'
- 'change-default-console-loglevel.patch')
+ 'change-default-console-loglevel.patch'
+ 'i915-fix-ghost-tv-output.patch'
+ 'i915-fix-incorrect-error-message.patch'
+ 'usb-add-reset-resume-quirk-for-several-webcams.patch')
build() {
cd "${srcdir}/linux-${_basekernel}"
-# patch -Np1 -i "${srcdir}/patch-${_basekernel}-libre-${pkgver}-libre"
+ patch -Np1 -i "${srcdir}/patch-${_basekernel}-libre-${pkgver}-libre"
# Add freedo as boot logo
patch -Np1 -i "${srcdir}/boot-logo.patch"
+ # Some chips detect a ghost TV output
+ # mailing list discussion: http://lists.freedesktop.org/archives/intel-gfx/2011-April/010371.html
+ # Arch Linux bug report: FS#19234
+ #
+ # It is unclear why this patch wasn't merged upstream, it was accepted,
+ # then dropped because the reasoning was unclear. However, it is clearly
+ # needed.
+ patch -Np1 -i "${srcdir}/i915-fix-ghost-tv-output.patch"
+
+ # In 3.1.1, a DRM_DEBUG message is falsely declared as DRM_ERROR. This
+ # worries users, as this message is displayed even at loglevel 4. Fix
+ # this.
+ patch -Np1 -i "${srcdir}/i915-fix-incorrect-error-message.patch"
+
+ # Add the USB_QUIRK_RESET_RESUME for several webcams
+ # FS#26528
+ patch -Np1 -i "${srcdir}/usb-add-reset-resume-quirk-for-several-webcams.patch"
+
# set DEFAULT_CONSOLE_LOGLEVEL to 4 (same value as the 'quiet' kernel param)
# remove this when a Kconfig knob is made available by upstream
# (relevant patch sent upstream: https://lkml.org/lkml/2011/7/26/227)
@@ -270,18 +291,13 @@ package_linux-libre-docs() {
# remove a file already in linux package
rm -f "${pkgdir}/usr/src/linux-${_kernver}/Documentation/DocBook/Makefile"
}
-md5sums=('44e7bc20c235a193f9b6123a8d5e9509'
- '8840c46301f6eb425b9ab456d1ca7b7f'
- '8089b63fdecf93735f178eb2907ce61e'
- '4cc90e12cab492c1d61183c47683bd52'
- 'a8a3843046926eb7ab81312cd438c5c5'
- '04b21c79df0a952c22d681dd4f4562df'
- '263725f20c0b9eb9c353040792d644e5'
- '9d3c56a4b999c8bfbd4018089a62f662')
-
md5sums=('d73df15ab1d36fe3c102755d8f42117f'
- 'a7cbd8c216a1f4c6068625c4dc746164'
- '616e05f7436572a7e83500b5daa7e958'
+ '1ff1e0f6d56911eed8afc0c32456da02'
+ '7d8fac41f4c4c2d14d8c65645fb676bd'
+ '2a0302eda795903d3b01e41ba807c91e'
'a8a3843046926eb7ab81312cd438c5c5'
'04b21c79df0a952c22d681dd4f4562df'
- '9d3c56a4b999c8bfbd4018089a62f662')
+ '9d3c56a4b999c8bfbd4018089a62f662'
+ '263725f20c0b9eb9c353040792d644e5'
+ 'a50c9076012cb2dda49952dc6ec3e9c1'
+ '52d41fa61e80277ace2b994412a0c856')
diff --git a/libre/linux-libre/config.i686 b/libre/linux-libre/config.i686
index 86fe20b40..43bf1d3c3 100644
--- a/libre/linux-libre/config.i686
+++ b/libre/linux-libre/config.i686
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/i386 3.1.0 Kernel Configuration
+# Linux/i386 3.1.1-1 Kernel Configuration
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
@@ -4281,7 +4281,7 @@ CONFIG_USB_HIDDEV=y
#
CONFIG_HID_A4TECH=m
CONFIG_HID_ACRUX=m
-CONFIG_HID_ACRUX_FF=m
+CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
CONFIG_HID_CHERRY=m
@@ -4413,6 +4413,7 @@ CONFIG_USB_TMC=m
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_REALTEK_AUTOPM=y
CONFIG_USB_STORAGE_DATAFAB=m
CONFIG_USB_STORAGE_FREECOM=m
CONFIG_USB_STORAGE_ISD200=m
diff --git a/libre/linux-libre/config.x86_64 b/libre/linux-libre/config.x86_64
index 4ec38fd52..6011a797a 100644
--- a/libre/linux-libre/config.x86_64
+++ b/libre/linux-libre/config.x86_64
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 3.1.0 Kernel Configuration
+# Linux/x86_64 3.1.1-1 Kernel Configuration
#
CONFIG_64BIT=y
# CONFIG_X86_32 is not set
@@ -4071,7 +4071,7 @@ CONFIG_USB_HIDDEV=y
#
CONFIG_HID_A4TECH=m
CONFIG_HID_ACRUX=m
-CONFIG_HID_ACRUX_FF=m
+CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
CONFIG_HID_CHERRY=m
@@ -4203,6 +4203,7 @@ CONFIG_USB_TMC=m
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_REALTEK_AUTOPM=y
CONFIG_USB_STORAGE_DATAFAB=m
CONFIG_USB_STORAGE_FREECOM=m
CONFIG_USB_STORAGE_ISD200=m
diff --git a/libre/linux-libre/dib0700-fix.patch b/libre/linux-libre/dib0700-fix.patch
new file mode 100644
index 000000000..48f07e6fd
--- /dev/null
+++ b/libre/linux-libre/dib0700-fix.patch
@@ -0,0 +1,1487 @@
+commit 198c545cd7306dc90aaae1d61e64175e70a70dc8
+Author: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
+Date: Wed Aug 3 17:08:21 2011 +0200
+
+ [media] DiBcom: protect the I2C bufer access
+
+ This patch protect the I2C buffer access in order to manage concurrent
+ access. This protection is done using mutex.
+ Furthermore, for the dib9000, if a pid filtering command is
+ received during the tuning, this pid filtering command is delayed to
+ avoid any concurrent access issue.
+
+ Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
+ Cc: Florian Mickler <florian@mickler.org>
+ Cc: stable@kernel.org
+
+ Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+ Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
+
+diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
+index 1d47d4d..dc1cb17 100644
+--- a/drivers/media/dvb/frontends/dib0070.c
++++ b/drivers/media/dvb/frontends/dib0070.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+
+ #include "dvb_frontend.h"
+
+@@ -78,10 +79,18 @@ struct dib0070_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[3];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
++static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = reg;
+
+ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+
+ if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0070 I2C read failed\n");
+- return 0;
+- }
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ ret = 0;
++ } else
++ ret = (state->i2c_read_buffer[0] << 8)
++ | state->i2c_read_buffer[1];
++
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
+ state->i2c_write_buffer[0] = reg;
+ state->i2c_write_buffer[1] = val >> 8;
+ state->i2c_write_buffer[2] = val & 0xff;
+@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+
+ if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0070 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
++ ret = -EREMOTEIO;
++ } else
++ ret = 0;
++
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ #define HARD_RESET(state) do { \
+@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
+ state->cfg = cfg;
+ state->i2c = i2c;
+ state->fe = fe;
++ mutex_init(&state->i2c_buffer_lock);
+ fe->tuner_priv = state;
+
+ if (dib0070_reset(fe) != 0)
+diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
+index c9c935a..b174d1c 100644
+--- a/drivers/media/dvb/frontends/dib0090.c
++++ b/drivers/media/dvb/frontends/dib0090.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+
+ #include "dvb_frontend.h"
+
+@@ -196,6 +197,7 @@ struct dib0090_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[3];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ struct dib0090_fw_state {
+@@ -208,10 +210,18 @@ struct dib0090_fw_state {
+ struct i2c_msg msg;
+ u8 i2c_write_buffer[2];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = reg;
+
+ memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+
+ if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+- return 0;
+- }
++ ret = 0;
++ } else
++ ret = (state->i2c_read_buffer[0] << 8)
++ | state->i2c_read_buffer[1];
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ state->i2c_write_buffer[0] = reg & 0xff;
+ state->i2c_write_buffer[1] = val >> 8;
+ state->i2c_write_buffer[2] = val & 0xff;
+@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+
+ if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
++ ret = -EREMOTEIO;
++ } else
++ ret = 0;
++
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = reg;
+
+ memset(&state->msg, 0, sizeof(struct i2c_msg));
+@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+ state->msg.len = 2;
+ if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+- return 0;
+- }
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ ret = 0;
++ } else
++ ret = (state->i2c_read_buffer[0] << 8)
++ | state->i2c_read_buffer[1];
++
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ state->i2c_write_buffer[0] = val >> 8;
+ state->i2c_write_buffer[1] = val & 0xff;
+
+@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+ state->msg.len = 2;
+ if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+- return -EREMOTEIO;
+- }
+- return 0;
++ ret = -EREMOTEIO;
++ } else
++ ret = 0;
++
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0)
+@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte
+ st->config = config;
+ st->i2c = i2c;
+ st->fe = fe;
++ mutex_init(&st->i2c_buffer_lock);
+ fe->tuner_priv = st;
+
+ if (config->wbd == NULL)
+@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada
+ st->config = config;
+ st->i2c = i2c;
+ st->fe = fe;
++ mutex_init(&st->i2c_buffer_lock);
+ fe->tuner_priv = st;
+
+ if (dib0090_fw_reset_digital(fe, st->config) != 0)
+diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
+index 79cb1c2..dbb76d7 100644
+--- a/drivers/media/dvb/frontends/dib7000m.c
++++ b/drivers/media/dvb/frontends/dib7000m.c
+@@ -11,6 +11,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+
+ #include "dvb_frontend.h"
+
+@@ -55,6 +56,7 @@ struct dib7000m_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[4];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ enum dib7000m_power_mode {
+@@ -69,6 +71,13 @@ enum dib7000m_power_mode {
+
+ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
+ state->i2c_write_buffer[1] = reg & 0xff;
+
+@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+ if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+ dprintk("i2c read error on %d",reg);
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ mutex_unlock(&state->i2c_buffer_lock);
++
++ return ret;
+ }
+
+ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+ state->i2c_write_buffer[1] = reg & 0xff;
+ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+ state->msg[0].buf = state->i2c_write_buffer;
+ state->msg[0].len = 4;
+
+- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
++ -EREMOTEIO : 0);
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+ static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+ {
+@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+ demod = &st->demod;
+ demod->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
++ mutex_init(&st->i2c_buffer_lock);
+
+ st->timf_default = cfg->bw->timf;
+
+diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
+index 0c9f40c..292bc19 100644
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -10,6 +10,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+
+ #include "dvb_math.h"
+ #include "dvb_frontend.h"
+@@ -68,6 +69,7 @@ struct dib7000p_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[4];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ enum dib7000p_power_mode {
+@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
+
+ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = reg >> 8;
+ state->i2c_write_buffer[1] = reg & 0xff;
+
+@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+ if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+ state->i2c_write_buffer[1] = reg & 0xff;
+ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+ state->msg[0].buf = state->i2c_write_buffer;
+ state->msg[0].len = 4;
+
+- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
++ -EREMOTEIO : 0);
++ mutex_unlock(&state->i2c_buffer_lock);
++ return ret;
+ }
+
+ static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
+@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
+ return -ENOMEM;
+
+ dpst->i2c_adap = i2c;
++ mutex_init(&dpst->i2c_buffer_lock);
+
+ for (k = no_of_demods - 1; k >= 0; k--) {
+ dpst->cfg = cfg[k];
+@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+ demod = &st->demod;
+ demod->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
++ mutex_init(&st->i2c_buffer_lock);
+
+ dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
+
+@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+ st->version = dib7000p_read_word(st, 897);
+
+ /* FIXME: make sure the dev.parent field is initialized, or else
+- request_firmware() will hit an OOPS (this should be moved somewhere
+- more common) */
++ request_firmware() will hit an OOPS (this should be moved somewhere
++ more common) */
++ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+
+ dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
+
+diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
+index 7d2ea11..fe284d5 100644
+--- a/drivers/media/dvb/frontends/dib8000.c
++++ b/drivers/media/dvb/frontends/dib8000.c
+@@ -10,6 +10,8 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
++
+ #include "dvb_math.h"
+
+ #include "dvb_frontend.h"
+@@ -37,6 +39,7 @@ struct i2c_device {
+ u8 addr;
+ u8 *i2c_write_buffer;
+ u8 *i2c_read_buffer;
++ struct mutex *i2c_buffer_lock;
+ };
+
+ struct dib8000_state {
+@@ -77,6 +80,7 @@ struct dib8000_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[4];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ enum dib8000_power_mode {
+@@ -86,24 +90,39 @@ enum dib8000_power_mode {
+
+ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
++ u16 ret;
+ struct i2c_msg msg[2] = {
+- {.addr = i2c->addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 2},
+- {.addr = i2c->addr >> 1, .flags = I2C_M_RD,
+- .buf = i2c->i2c_read_buffer, .len = 2},
++ {.addr = i2c->addr >> 1, .flags = 0, .len = 2},
++ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
+ };
+
++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
++ msg[0].buf = i2c->i2c_write_buffer;
+ msg[0].buf[0] = reg >> 8;
+ msg[0].buf[1] = reg & 0xff;
++ msg[1].buf = i2c->i2c_read_buffer;
+
+ if (i2c_transfer(i2c->adap, msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (msg[1].buf[0] << 8) | msg[1].buf[1];
++ ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
++ mutex_unlock(i2c->i2c_buffer_lock);
++ return ret;
+ }
+
+ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ state->i2c_write_buffer[0] = reg >> 8;
+ state->i2c_write_buffer[1] = reg & 0xff;
+
+@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+ if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ mutex_unlock(&state->i2c_buffer_lock);
++
++ return ret;
+ }
+
+ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+
+ static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
+- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 4};
++ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
+ int ret = 0;
+
++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
++ msg.buf = i2c->i2c_write_buffer;
+ msg.buf[0] = (reg >> 8) & 0xff;
+ msg.buf[1] = reg & 0xff;
+ msg.buf[2] = (val >> 8) & 0xff;
+ msg.buf[3] = val & 0xff;
+
+ ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
++ mutex_unlock(i2c->i2c_buffer_lock);
+
+ return ret;
+ }
+
+ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+ state->i2c_write_buffer[1] = reg & 0xff;
+ state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+ state->msg[0].buf = state->i2c_write_buffer;
+ state->msg[0].len = 4;
+
+- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
++ -EREMOTEIO : 0);
++ mutex_unlock(&state->i2c_buffer_lock);
++
++ return ret;
+ }
+
+ static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
+@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
+ if (!client.i2c_read_buffer) {
+ dprintk("%s: not enough memory", __func__);
+ ret = -ENOMEM;
+- goto error_memory;
++ goto error_memory_read;
++ }
++ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
++ if (!client.i2c_buffer_lock) {
++ dprintk("%s: not enough memory", __func__);
++ ret = -ENOMEM;
++ goto error_memory_lock;
+ }
++ mutex_init(client.i2c_buffer_lock);
+
+ for (k = no_of_demods - 1; k >= 0; k--) {
+ /* designated i2c address */
+@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
+ }
+
+ error:
++ kfree(client.i2c_buffer_lock);
++error_memory_lock:
+ kfree(client.i2c_read_buffer);
+-error_memory:
++error_memory_read:
+ kfree(client.i2c_write_buffer);
+
+ return ret;
+@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
+ state->i2c.addr = i2c_addr;
+ state->i2c.i2c_write_buffer = state->i2c_write_buffer;
+ state->i2c.i2c_read_buffer = state->i2c_read_buffer;
++ mutex_init(&state->i2c_buffer_lock);
++ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
+ state->gpio_val = cfg->gpio_val;
+ state->gpio_dir = cfg->gpio_dir;
+
+diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
+index a085588..b931074 100644
+--- a/drivers/media/dvb/frontends/dib9000.c
++++ b/drivers/media/dvb/frontends/dib9000.c
+@@ -38,6 +38,15 @@ struct i2c_device {
+ #define DibInitLock(lock) mutex_init(lock)
+ #define DibFreeLock(lock)
+
++struct dib9000_pid_ctrl {
++#define DIB9000_PID_FILTER_CTRL 0
++#define DIB9000_PID_FILTER 1
++ u8 cmd;
++ u8 id;
++ u16 pid;
++ u8 onoff;
++};
++
+ struct dib9000_state {
+ struct i2c_device i2c;
+
+@@ -99,6 +108,10 @@ struct dib9000_state {
+ struct i2c_msg msg[2];
+ u8 i2c_write_buffer[255];
+ u8 i2c_read_buffer[255];
++ DIB_LOCK demod_lock;
++ u8 get_frontend_internal;
++ struct dib9000_pid_ctrl pid_ctrl[10];
++ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
+ };
+
+ static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio);
+ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef;
++ u16 val;
++ int ret;
++
++ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
++ /* postpone the pid filtering cmd */
++ dprintk("pid filter cmd postpone");
++ state->pid_ctrl_index++;
++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
++ return 0;
++ }
++
++ DibAcquireLock(&state->demod_lock);
++
++ val = dib9000_read_word(state, 294 + 1) & 0xffef;
+ val |= (onoff & 0x1) << 4;
+
+ dprintk("PID filter enabled %d", onoff);
+- return dib9000_write_word(state, 294 + 1, val);
++ ret = dib9000_write_word(state, 294 + 1, val);
++ DibReleaseLock(&state->demod_lock);
++ return ret;
++
+ }
+ EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
+
+ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
++ int ret;
++
++ if (state->pid_ctrl_index != -2) {
++ /* postpone the pid filtering cmd */
++ dprintk("pid filter postpone");
++ if (state->pid_ctrl_index < 9) {
++ state->pid_ctrl_index++;
++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
++ state->pid_ctrl[state->pid_ctrl_index].id = id;
++ state->pid_ctrl[state->pid_ctrl_index].pid = pid;
++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
++ } else
++ dprintk("can not add any more pid ctrl cmd");
++ return 0;
++ }
++
++ DibAcquireLock(&state->demod_lock);
+ dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
++ ret = dib9000_write_word(state, 300 + 1 + id,
++ onoff ? (1 << 13) | pid : 0);
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+ EXPORT_SYMBOL(dib9000_fw_pid_filter);
+
+@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod)
+ DibFreeLock(&state->platform.risc.mbx_lock);
+ DibFreeLock(&state->platform.risc.mem_lock);
+ DibFreeLock(&state->platform.risc.mem_mbx_lock);
++ DibFreeLock(&state->demod_lock);
+ dibx000_exit_i2c_master(&st->i2c_master);
+
+ i2c_del_adapter(&st->tuner_adap);
+@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+ u8 index_frontend;
+- int ret;
++ int ret = 0;
+
++ DibAcquireLock(&state->demod_lock);
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+ ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+ if (ret < 0)
+- return ret;
++ goto error;
+ }
+- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
++ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
++
++error:
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+
+ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ struct dib9000_state *state = fe->demodulator_priv;
+ u8 index_frontend, sub_index_frontend;
+ fe_status_t stat;
+- int ret;
++ int ret = 0;
++
++ if (state->get_frontend_internal == 0)
++ DibAcquireLock(&state->demod_lock);
+
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+ state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ state->fe[index_frontend]->dtv_property_cache.rolloff;
+ }
+ }
+- return 0;
++ ret = 0;
++ goto return_value;
+ }
+ }
+
+ /* get the channel from master chip */
+ ret = dib9000_fw_get_channel(fe, fep);
+ if (ret != 0)
+- return ret;
++ goto return_value;
+
+ /* synchronize the cache with the other frontends */
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
+ state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
+ }
++ ret = 0;
+
+- return 0;
++return_value:
++ if (state->get_frontend_internal == 0)
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+
+ static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ dprintk("dib9000: must specify bandwidth ");
+ return 0;
+ }
++
++ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
++ DibAcquireLock(&state->demod_lock);
++
+ fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+ /* set the master status */
+@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ /* check the tune result */
+ if (exit_condition == 1) { /* tune failed */
+ dprintk("tune failed");
++ DibReleaseLock(&state->demod_lock);
++ /* tune failed; put all the pid filtering cmd to junk */
++ state->pid_ctrl_index = -1;
+ return 0;
+ }
+
+ dprintk("tune success on frontend%i", index_frontend_success);
+
+ /* synchronize all the channel cache */
++ state->get_frontend_internal = 1;
+ dib9000_get_frontend(state->fe[0], fep);
++ state->get_frontend_internal = 0;
+
+ /* retune the other frontends with the found channel */
+ channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
+ /* turn off the diversity for the last frontend */
+ dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
+
++ DibReleaseLock(&state->demod_lock);
++ if (state->pid_ctrl_index >= 0) {
++ u8 index_pid_filter_cmd;
++ u8 pid_ctrl_index = state->pid_ctrl_index;
++
++ state->pid_ctrl_index = -2;
++ for (index_pid_filter_cmd = 0;
++ index_pid_filter_cmd <= pid_ctrl_index;
++ index_pid_filter_cmd++) {
++ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
++ dib9000_fw_pid_filter_ctrl(state->fe[0],
++ state->pid_ctrl[index_pid_filter_cmd].onoff);
++ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
++ dib9000_fw_pid_filter(state->fe[0],
++ state->pid_ctrl[index_pid_filter_cmd].id,
++ state->pid_ctrl[index_pid_filter_cmd].pid,
++ state->pid_ctrl[index_pid_filter_cmd].onoff);
++ }
++ }
++ /* do not postpone any more the pid filtering */
++ state->pid_ctrl_index = -2;
++
+ return 0;
+ }
+
+@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+ u8 index_frontend;
+ u16 lock = 0, lock_slave = 0;
+
++ DibAcquireLock(&state->demod_lock);
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+ lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
+
+@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+ if ((lock & 0x0008) || (lock_slave & 0x0008))
+ *stat |= FE_HAS_LOCK;
+
++ DibReleaseLock(&state->demod_lock);
++
+ return 0;
+ }
+
+@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+ u16 *c;
++ int ret = 0;
+
++ DibAcquireLock(&state->demod_lock);
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+- return -EIO;
++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++ ret = -EIO;
++ goto error;
++ }
+ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+ state->i2c_read_buffer, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+ c = (u16 *)state->i2c_read_buffer;
+
+ *ber = c[10] << 16 | c[11];
+- return 0;
++
++error:
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+
+ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+ u8 index_frontend;
+ u16 *c = (u16 *)state->i2c_read_buffer;
+ u16 val;
++ int ret = 0;
+
++ DibAcquireLock(&state->demod_lock);
+ *strength = 0;
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+ state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+ }
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+- return -EIO;
++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++ ret = -EIO;
++ goto error;
++ }
+ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+ *strength = 65535;
+ else
+ *strength += val;
+- return 0;
++
++error:
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+
+ static u32 dib9000_get_snr(struct dvb_frontend *fe)
+@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
+ u8 index_frontend;
+ u32 snr_master;
+
++ DibAcquireLock(&state->demod_lock);
+ snr_master = dib9000_get_snr(fe);
+ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+ snr_master += dib9000_get_snr(state->fe[index_frontend]);
+@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
+ } else
+ *snr = 0;
+
++ DibReleaseLock(&state->demod_lock);
++
+ return 0;
+ }
+
+@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+ u16 *c = (u16 *)state->i2c_read_buffer;
++ int ret = 0;
+
++ DibAcquireLock(&state->demod_lock);
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+- return -EIO;
++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
++ ret = -EIO;
++ goto error;
++ }
+ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ *unc = c[12];
+- return 0;
++
++error:
++ DibReleaseLock(&state->demod_lock);
++ return ret;
+ }
+
+ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
+ DibInitLock(&st->platform.risc.mbx_lock);
+ DibInitLock(&st->platform.risc.mem_lock);
+ DibInitLock(&st->platform.risc.mem_mbx_lock);
++ DibInitLock(&st->demod_lock);
++ st->get_frontend_internal = 0;
++
++ st->pid_ctrl_index = -2;
+
+ st->fe[0] = fe;
+ fe->demodulator_priv = st;
+diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
+index dc5d17a..774d507 100644
+--- a/drivers/media/dvb/frontends/dibx000_common.c
++++ b/drivers/media/dvb/frontends/dibx000_common.c
+@@ -1,4 +1,5 @@
+ #include <linux/i2c.h>
++#include <linux/mutex.h>
+
+ #include "dibx000_common.h"
+
+@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+ {
++ int ret;
++
++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
+ mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+ mst->i2c_write_buffer[1] = reg & 0xff;
+ mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
+@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+ mst->msg[0].buf = mst->i2c_write_buffer;
+ mst->msg[0].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
++ mutex_unlock(&mst->i2c_buffer_lock);
++
++ return ret;
+ }
+
+ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+ {
++ u16 ret;
++
++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ mst->i2c_write_buffer[0] = reg >> 8;
+ mst->i2c_write_buffer[1] = reg & 0xff;
+
+@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+ if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
++ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
++ mutex_unlock(&mst->i2c_buffer_lock);
++
++ return ret;
+ }
+
+ static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++ int ret;
+
+ if (num > 32) {
+ dprintk("%s: too much I2C message to be transmitted (%i).\
+@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
+ return -ENOMEM;
+ }
+
+- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+-
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+
++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++
++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++
+ /* open the gate */
+ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+ mst->msg[0].addr = mst->i2c_addr;
+@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
+ mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+ mst->msg[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
++ num : -EIO);
++
++ mutex_unlock(&mst->i2c_buffer_lock);
++ return ret;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++ int ret;
+
+ if (num > 32) {
+ dprintk("%s: too much I2C message to be transmitted (%i).\
+@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
+ return -ENOMEM;
+ }
+
+- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+-
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++
+ /* open the gate */
+ dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+ mst->msg[0].addr = mst->i2c_addr;
+@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
+ mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+ mst->msg[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
++ num : -EIO);
++ mutex_unlock(&mst->i2c_buffer_lock);
++ return ret;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
+ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
+ struct i2c_adapter *i2c_adap, u8 i2c_addr)
+ {
+- u8 tx[4];
+- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
++ int ret;
++
++ mutex_init(&mst->i2c_buffer_lock);
++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
++ dprintk("could not acquire lock");
++ return -EINVAL;
++ }
++ memset(mst->msg, 0, sizeof(struct i2c_msg));
++ mst->msg[0].addr = i2c_addr >> 1;
++ mst->msg[0].flags = 0;
++ mst->msg[0].buf = mst->i2c_write_buffer;
++ mst->msg[0].len = 4;
+
+ mst->device_rev = device_rev;
+ mst->i2c_adap = i2c_adap;
+@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
+ "DiBX000: could not initialize the master i2c_adapter\n");
+
+ /* initialize the i2c-master by closing the gate */
+- dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
++ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
++
++ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
++ mutex_unlock(&mst->i2c_buffer_lock);
+
+- return i2c_transfer(i2c_adap, &m, 1) == 1;
++ return ret;
+ }
+
+ EXPORT_SYMBOL(dibx000_init_i2c_master);
+diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
+index f031165..5e01147 100644
+--- a/drivers/media/dvb/frontends/dibx000_common.h
++++ b/drivers/media/dvb/frontends/dibx000_common.h
+@@ -33,6 +33,7 @@ struct dibx000_i2c_master {
+ struct i2c_msg msg[34];
+ u8 i2c_write_buffer[8];
+ u8 i2c_read_buffer[2];
++ struct mutex i2c_buffer_lock;
+ };
+
+ extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
+commit 45cbff13693d645fa5dcbba964e802e1746b2e57
+Author: Olivier Grenie <olivier.grenie@dibcom.fr>
+Date: Mon Aug 1 17:45:58 2011 +0200
+
+ [media] dib0700: protect the dib0700 buffer access
+
+ This patch protects the common buffer access inside the dib0700 in order
+ to manage concurrent access. This protection is done using mutex.
+
+ Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
+ Cc: Florian Mickler <florian@mickler.org>
+ Cc: stable@kernel.org
+
+ Signed-off-by: Javier Marcet <javier@marcet.info>
+ Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+ Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
+
+diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
+index 5eb91b4..291b645 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
+@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ struct dib0700_state *st = d->priv;
+ int ret;
+
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+ REQUEST_GET_VERSION,
+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ if (fwtype != NULL)
+ *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
+ (st->buf[14] << 8) | st->buf[15];
++ mutex_unlock(&d->usb_mutex);
+ return ret;
+ }
+
+@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
+ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
+ {
+ struct dib0700_state *st = d->priv;
+- s16 ret;
++ int ret;
++
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
+
+ st->buf[0] = REQUEST_SET_GPIO;
+ st->buf[1] = gpio;
+@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
+
+ ret = dib0700_ctrl_wr(d, st->buf, 3);
+
++ mutex_unlock(&d->usb_mutex);
+ return ret;
+ }
+
+@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
+ int ret;
+
+ if (st->fw_version >= 0x10201) {
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ st->buf[0] = REQUEST_SET_USB_XFER_LEN;
+ st->buf[1] = (nb_ts_packets >> 8) & 0xff;
+ st->buf[2] = nb_ts_packets & 0xff;
+@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
+ deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
+
+ ret = dib0700_ctrl_wr(d, st->buf, 3);
++ mutex_unlock(&d->usb_mutex);
+ } else {
+ deb_info("this firmware does not allow to change the USB xfer len\n");
+ ret = -EIO;
+@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+
+ } else {
+ /* Write request */
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
+ st->buf[0] = REQUEST_NEW_I2C_WRITE;
+ st->buf[1] = msg[i].addr << 1;
+ st->buf[2] = (en_start << 7) | (en_stop << 6) |
+@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ 0, 0, st->buf, msg[i].len + 4,
+ USB_CTRL_GET_TIMEOUT);
++ mutex_unlock(&d->usb_mutex);
+ if (result < 0) {
+ deb_info("i2c write error (status = %d)\n", result);
+ break;
+@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
+
+ for (i = 0; i < num; i++) {
+ /* fill in the address */
+@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+ break;
+ }
+ }
++ mutex_unlock(&d->usb_mutex);
+ mutex_unlock(&d->i2c_mutex);
+
+ return i;
+@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
+ u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
+ {
+ struct dib0700_state *st = d->priv;
+- s16 ret;
++ int ret;
++
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
+
+ st->buf[0] = REQUEST_SET_CLOCK;
+ st->buf[1] = (en_pll << 7) | (pll_src << 6) |
+@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
+ st->buf[9] = dsuScaler & 0xff; /* LSB */
+
+ ret = dib0700_ctrl_wr(d, st->buf, 10);
++ mutex_unlock(&d->usb_mutex);
+
+ return ret;
+ }
+@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
+ {
+ struct dib0700_state *st = d->priv;
+ u16 divider;
++ int ret;
+
+ if (scl_kHz == 0)
+ return -EINVAL;
+
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ st->buf[0] = REQUEST_SET_I2C_PARAM;
+ divider = (u16) (30000 / scl_kHz);
+ st->buf[1] = 0;
+@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
+ deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
+ (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
+ st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
+- return dib0700_ctrl_wr(d, st->buf, 8);
++
++ ret = dib0700_ctrl_wr(d, st->buf, 8);
++ mutex_unlock(&d->usb_mutex);
++
++ return ret;
+ }
+
+
+@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ }
+ }
+
++ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ st->buf[0] = REQUEST_ENABLE_VIDEO;
+ /* this bit gives a kind of command,
+ * rather than enabling something or not */
+@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+
+ deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
+
+- return dib0700_ctrl_wr(adap->dev, st->buf, 4);
++ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
++ mutex_unlock(&adap->dev->usb_mutex);
++
++ return ret;
+ }
+
+ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+ struct dib0700_state *st = d->priv;
+ int new_proto, ret;
+
++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
++ dprintk("could not acquire lock");
++ return 0;
++ }
++
+ st->buf[0] = REQUEST_SET_RC;
+ st->buf[1] = 0;
+ st->buf[2] = 0;
+@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+ else if (rc_type == RC_TYPE_NEC)
+ new_proto = 0;
+ else if (rc_type == RC_TYPE_RC6) {
+- if (st->fw_version < 0x10200)
+- return -EINVAL;
++ if (st->fw_version < 0x10200) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ new_proto = 2;
+- } else
+- return -EINVAL;
++ } else {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ st->buf[1] = new_proto;
+
+ ret = dib0700_ctrl_wr(d, st->buf, 3);
+ if (ret < 0) {
+ err("ir protocol setup failed");
+- return ret;
++ goto out;
+ }
+
+ d->props.rc.core.protocol = rc_type;
+
++out:
++ mutex_unlock(&d->usb_mutex);
+ return ret;
+ }
+
+commit aeb2d456b746164a4bd19e53de0a6678ca63fcad
+Author: Olivier Grenie <olivier.grenie@dibcom.fr>
+Date: Thu Aug 4 18:10:03 2011 +0200
+
+ [media] dib0700: correct error message
+
+ The goal of this patch is to correct a previous patch. In case of error,
+ the err() function should be used instead of dprintk() function.
+
+ Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
+
+diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
+index 291b645..b693ed1 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
+@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ int ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
+ int ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
+
+ if (st->fw_version >= 0x10201) {
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+ } else {
+ /* Write request */
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+ st->buf[0] = REQUEST_NEW_I2C_WRITE;
+@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
+ int ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ }
+
+ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
+@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+ int new_proto, ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+- dprintk("could not acquire lock");
++ err("could not acquire lock");
+ return 0;
+ }
+
diff --git a/libre/linux-libre/i915-fix-ghost-tv-output.patch b/libre/linux-libre/i915-fix-ghost-tv-output.patch
new file mode 100644
index 000000000..3b631361a
--- /dev/null
+++ b/libre/linux-libre/i915-fix-ghost-tv-output.patch
@@ -0,0 +1,26 @@
+Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
+Tested-by: Santi <santi@agolina.net>
+---
+ drivers/gpu/drm/i915/intel_tv.c | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
+index dc83b7a..c8f67bf 100644
+--- a/drivers/gpu/drm/i915/intel_tv.c
++++ b/drivers/gpu/drm/i915/intel_tv.c
+@@ -1267,6 +1267,15 @@
+ DAC_B_0_7_V |
+ DAC_C_0_7_V);
+
++ /*
++ * The TV sense state should be cleared to zero on cantiga platform. Otherwise
++ * the TV is misdetected. This is hardware requirement.
++ */
++ if (IS_GM45(dev))
++ tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
++ TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
++
++
+ I915_WRITE(TV_CTL, tv_ctl);
+ I915_WRITE(TV_DAC, tv_dac);
+ POSTING_READ(TV_DAC);
diff --git a/libre/linux-libre/i915-fix-incorrect-error-message.patch b/libre/linux-libre/i915-fix-incorrect-error-message.patch
new file mode 100644
index 000000000..e1addbb05
--- /dev/null
+++ b/libre/linux-libre/i915-fix-incorrect-error-message.patch
@@ -0,0 +1,22 @@
+commit 6c76e0b94e484ffbdf38d2fe2769b6ca9aa99de4
+Author: Thomas Bächler <thomas@archlinux.org>
+Date: Mon Oct 31 19:16:18 2011 +0100
+
+ Change accidental error message to debug message.
+
+ According to https://lkml.org/lkml/2011/9/19/80, this is not supposed
+ to be an error message, but a debug message. This worries users.
+
+diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
+index 04411ad..02d5794 100644
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -5172,7 +5172,7 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
+ } else {
+ /* Enable SSC on PCH eDP if needed */
+ if (intel_panel_use_ssc(dev_priv)) {
+- DRM_ERROR("enabling SSC on PCH\n");
++ DRM_DEBUG("enabling SSC on PCH\n");
+ temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
+ }
+ }
diff --git a/libre/linux-libre/iwlagn-fix-NULL-pointer-dereference.patch b/libre/linux-libre/iwlagn-fix-NULL-pointer-dereference.patch
new file mode 100644
index 000000000..a53a3a425
--- /dev/null
+++ b/libre/linux-libre/iwlagn-fix-NULL-pointer-dereference.patch
@@ -0,0 +1,38 @@
+This fix regression introduced by commit:
+
+commit 15b3f3b006b42a678523cad989bfd60b76bf4403
+Author: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+Date: Fri Jun 3 07:54:13 2011 -0700
+
+ iwlagn: set smps mode after assoc for 1000 device
+
+Also remove unneeded brackets on the way.
+
+Address:
+https://bugzilla.redhat.com/show_bug.cgi?id=744155
+
+If fix will not get 3.1 release, it should be applied in 3.1 stable.
+
+Cc: stable@kernel.org # 3.1+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+index ca632f9..5004342 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+@@ -296,8 +296,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
+ return ret;
+ }
+
+- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) &&
+- priv->cfg->ht_params->smps_mode)
++ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
++ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode)
+ ieee80211_request_smps(ctx->vif,
+ priv->cfg->ht_params->smps_mode);
+
+--
+1.7.1
diff --git a/libre/linux-libre/linux-libre.install b/libre/linux-libre/linux-libre.install
index 493a6e3a7..772e15b24 100644
--- a/libre/linux-libre/linux-libre.install
+++ b/libre/linux-libre/linux-libre.install
@@ -2,7 +2,7 @@
# arg 2: the old package version
KERNEL_NAME=
-KERNEL_VERSION=3.1.0-2-LIBRE
+KERNEL_VERSION=3.1.2-1-LIBRE
post_install () {
# updating module dependencies
@@ -45,9 +45,8 @@ post_upgrade() {
if grep "^[^#]*[[:space:]]/boot" etc/fstab 2>&1 >/dev/null; then
if ! grep "[[:space:]]/boot" etc/mtab 2>&1 >/dev/null; then
- echo "WARNING: /boot appears to be a seperate partition but is not mounted"
- echo " This is most likely not what you want. Please mount your /boot"
- echo " partition and reinstall the kernel unless you are sure this is OK"
+ echo "WARNING: /boot appears to be a seperate partition but is not mounted."
+ echo " You probably just broke your system. Congratulations."
fi
fi
diff --git a/libre/linux-libre/md-raid10-fix-bug-when-activating-a-hot-spare.patch b/libre/linux-libre/md-raid10-fix-bug-when-activating-a-hot-spare.patch
new file mode 100644
index 000000000..79be53afb
--- /dev/null
+++ b/libre/linux-libre/md-raid10-fix-bug-when-activating-a-hot-spare.patch
@@ -0,0 +1,41 @@
+From 7fcc7c8acf0fba44d19a713207af7e58267c1179 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Mon, 31 Oct 2011 12:59:44 +1100
+Subject: md/raid10: Fix bug when activating a hot-spare.
+
+From: NeilBrown <neilb@suse.de>
+
+commit 7fcc7c8acf0fba44d19a713207af7e58267c1179 upstream.
+
+This is a fairly serious bug in RAID10.
+
+When a RAID10 array is degraded and a hot-spare is activated, the
+spare does not take up the empty slot, but rather replaces the first
+working device.
+This is likely to make the array non-functional. It would normally
+be possible to recover the data, but that would need care and is not
+guaranteed.
+
+This bug was introduced in commit
+ 2bb77736ae5dca0a189829fbb7379d43364a9dac
+which first appeared in 3.1.
+
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/raid10.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1337,7 +1337,7 @@ static int raid10_add_disk(mddev_t *mdde
+ mirror_info_t *p = &conf->mirrors[mirror];
+ if (p->recovery_disabled == mddev->recovery_disabled)
+ continue;
+- if (!p->rdev)
++ if (p->rdev)
+ continue;
+
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+
diff --git a/libre/linux-libre/usb-add-reset-resume-quirk-for-several-webcams.patch b/libre/linux-libre/usb-add-reset-resume-quirk-for-several-webcams.patch
new file mode 100644
index 000000000..9e570dd3f
--- /dev/null
+++ b/libre/linux-libre/usb-add-reset-resume-quirk-for-several-webcams.patch
@@ -0,0 +1,99 @@
+commit 2394d67e446bf616a0885167d5f0d397bdacfdfc
+Author: Oliver Neukum <oneukum@suse.de>
+Date: Tue Sep 13 08:42:21 2011 +0200
+
+ USB: add RESET_RESUME for webcams shown to be quirky
+
+ The new runtime PM code has shown that many webcams suffer
+ from a race condition that may crash them upon resume.
+ Runtime PM is especially prone to show the problem because
+ it retains power to the cameras at all times. However
+ system suspension may also crash the devices and retain
+ power to the devices.
+ The only way to solve this problem without races is in
+ usbcore with the RESET_RESUME quirk.
+
+ Signed-off-by: Oliver Neukum <oneukum@suse.de>
+ Signed-off-by: stable <stable@kernel.org>
+ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 81ce6a8..38f0510 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -38,6 +38,24 @@ static const struct usb_device_id usb_quirk_list[] = {
+ /* Creative SB Audigy 2 NX */
+ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
+
++ /* Logitech Webcam C200 */
++ { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME },
++
++ /* Logitech Webcam C250 */
++ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
++
++ /* Logitech Webcam B/C500 */
++ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
++
++ /* Logitech Webcam Pro 9000 */
++ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
++
++ /* Logitech Webcam C310 */
++ { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME },
++
++ /* Logitech Webcam C270 */
++ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ /* Logitech Harmony 700-series */
+ { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
+
+@@ -69,6 +87,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ { USB_DEVICE(0x06a3, 0x0006), .driver_info =
+ USB_QUIRK_CONFIG_INTF_STRINGS },
+
++ /* Guillemot Webcam Hercules Dualpix Exchange*/
++ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ /* M-Systems Flash Disk Pioneers */
+ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+
+commit 5b253d88cc6c65a23cefc457a5a4ef139913c5fc
+Author: Jon Levell <linuxusb@coralbark.net>
+Date: Thu Sep 29 20:42:52 2011 +0100
+
+ USB: add quirk for Logitech C300 web cam
+
+ My webcam is a Logitech C300 and I get "chipmunk"ed squeaky sound.
+ The following trivial patch fixes it.
+
+ Signed-off-by: Jon Levell <linuxusb@coralbark.net>
+ Cc: stable <stable@kernel.org>
+ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 38f0510..d6a8d82 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ /* Logitech Webcam C250 */
+ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
+
++ /* Logitech Webcam C300 */
++ { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ /* Logitech Webcam B/C500 */
+ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index d6a8d82..caa1991 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -50,6 +50,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ /* Logitech Webcam B/C500 */
+ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
+
++ /* Logitech Webcam C600 */
++ { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ /* Logitech Webcam Pro 9000 */
+ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
+