]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .30 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 10 Sep 2009 22:57:58 +0000 (15:57 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 10 Sep 2009 22:57:58 +0000 (15:57 -0700)
13 files changed:
queue-2.6.30/dm-exception-store-split-set_chunk_size.patch [new file with mode: 0644]
queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch [new file with mode: 0644]
queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch [new file with mode: 0644]
queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch [new file with mode: 0644]
queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch [new file with mode: 0644]
queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch [new file with mode: 0644]
queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch [new file with mode: 0644]
queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch [new file with mode: 0644]
queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch [new file with mode: 0644]
queue-2.6.30/series
queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch [new file with mode: 0644]
queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch [new file with mode: 0644]
queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch [new file with mode: 0644]

diff --git a/queue-2.6.30/dm-exception-store-split-set_chunk_size.patch b/queue-2.6.30/dm-exception-store-split-set_chunk_size.patch
new file mode 100644 (file)
index 0000000..f3e4a13
--- /dev/null
@@ -0,0 +1,51 @@
+From 2defcc3fb4661e7351cb2ac48d843efc4c64db13 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 4 Sep 2009 20:40:41 +0100
+Subject: dm exception store: split set_chunk_size
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 2defcc3fb4661e7351cb2ac48d843efc4c64db13 upstream.
+
+Break the function set_chunk_size to two functions in preparation for
+the fix in the following patch.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-exception-store.c |    8 ++++++++
+ drivers/md/dm-exception-store.h |    4 ++++
+ 2 files changed, 12 insertions(+)
+
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -171,6 +171,14 @@ static int set_chunk_size(struct dm_exce
+        */
+       chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
++      return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
++                                               error);
++}
++
++int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
++                                    unsigned long chunk_size_ulong,
++                                    char **error)
++{
+       /* Check chunk_size is a power of 2 */
+       if (!is_power_of_2(chunk_size_ulong)) {
+               *error = "Chunk size is not a power of 2";
+--- a/drivers/md/dm-exception-store.h
++++ b/drivers/md/dm-exception-store.h
+@@ -168,6 +168,10 @@ static inline chunk_t sector_to_chunk(st
+ int dm_exception_store_type_register(struct dm_exception_store_type *type);
+ int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
++int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
++                                    unsigned long chunk_size_ulong,
++                                    char **error);
++
+ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
+                             unsigned *args_used,
+                             struct dm_exception_store **store);
diff --git a/queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch b/queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch
new file mode 100644 (file)
index 0000000..451d5b9
--- /dev/null
@@ -0,0 +1,61 @@
+From d2b698644c97cb033261536a4f2010924a00eac9 Mon Sep 17 00:00:00 2001
+From: Jonathan Brassow <jbrassow@redhat.com>
+Date: Fri, 4 Sep 2009 20:40:32 +0100
+Subject: dm raid1: do not allow log_failure variable to unset after being set
+
+From: Jonathan Brassow <jbrassow@redhat.com>
+
+commit d2b698644c97cb033261536a4f2010924a00eac9 upstream.
+
+This patch fixes a bug which was triggering a case where the primary leg
+could not be changed on failure even when the mirror was in-sync.
+
+The case involves the failure of the primary device along with
+the transient failure of the log device.  The problem is that
+bios can be put on the 'failures' list (due to log failure)
+before 'fail_mirror' is called due to the primary device failure.
+Normally, this is fine, but if the log device failure is transient,
+a subsequent iteration of the work thread, 'do_mirror', will
+reset 'log_failure'.  The 'do_failures' function then resets
+the 'in_sync' variable when processing bios on the failures list.
+The 'in_sync' variable is what is used to determine if the
+primary device can be switched in the event of a failure.  Since
+this has been reset, the primary device is incorrectly assumed
+to be not switchable.
+
+The case has been seen in the cluster mirror context, where one
+machine realizes the log device is dead before the other machines.
+As the responsibilities of the server migrate from one node to
+another (because the mirror is being reconfigured due to the failure),
+the new server may think for a moment that the log device is fine -
+thus resetting the 'log_failure' variable.
+
+In any case, it is inappropiate for us to reset the 'log_failure'
+variable.  The above bug simply illustrates that it can actually
+hurt us.
+
+Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-raid1.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/dm-raid1.c
++++ b/drivers/md/dm-raid1.c
+@@ -648,7 +648,13 @@ static void do_writes(struct mirror_set 
+        */
+       dm_rh_inc_pending(ms->rh, &sync);
+       dm_rh_inc_pending(ms->rh, &nosync);
+-      ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0;
++
++      /*
++       * If the flush fails on a previous call and succeeds here,
++       * we must not reset the log_failure variable.  We need
++       * userspace interaction to do that.
++       */
++      ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure;
+       /*
+        * Dispatch io.
diff --git a/queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch b/queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch
new file mode 100644 (file)
index 0000000..95ffc27
--- /dev/null
@@ -0,0 +1,143 @@
+From 61578dcd3fafe6babd72e8db32110cc0b630a432 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 4 Sep 2009 20:40:39 +0100
+Subject: dm snapshot: fix header corruption race on invalidation
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 61578dcd3fafe6babd72e8db32110cc0b630a432 upstream.
+
+If a persistent snapshot fills up, a race can corrupt the on-disk header
+which causes a crash on any future attempt to activate the snapshot
+(typically while booting).  This patch fixes the race.
+
+When the snapshot overflows, __invalidate_snapshot is called, which calls
+snapshot store method drop_snapshot. It goes to persistent_drop_snapshot that
+calls write_header. write_header constructs the new header in the "area"
+location.
+
+Concurrently, an existing kcopyd job may finish, call copy_callback
+and commit_exception method, that goes to persistent_commit_exception.
+persistent_commit_exception doesn't do locking, relying on the fact that
+callbacks are single-threaded, but it can race with snapshot invalidation and
+overwrite the header that is just being written while the snapshot is being
+invalidated.
+
+The result of this race is a corrupted header being written that can
+lead to a crash on further reactivation (if chunk_size is zero in the
+corrupted header).
+
+The fix is to use separate memory areas for each.
+
+See the bug: https://bugzilla.redhat.com/show_bug.cgi?id=461506
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-snap-persistent.c |   44 ++++++++++++++++++++++++++++++----------
+ 1 file changed, 34 insertions(+), 10 deletions(-)
+
+--- a/drivers/md/dm-snap-persistent.c
++++ b/drivers/md/dm-snap-persistent.c
+@@ -106,6 +106,13 @@ struct pstore {
+       void *zero_area;
+       /*
++       * An area used for header. The header can be written
++       * concurrently with metadata (when invalidating the snapshot),
++       * so it needs a separate buffer.
++       */
++      void *header_area;
++
++      /*
+        * Used to keep track of which metadata area the data in
+        * 'chunk' refers to.
+        */
+@@ -148,16 +155,27 @@ static int alloc_area(struct pstore *ps)
+        */
+       ps->area = vmalloc(len);
+       if (!ps->area)
+-              return r;
++              goto err_area;
+       ps->zero_area = vmalloc(len);
+-      if (!ps->zero_area) {
+-              vfree(ps->area);
+-              return r;
+-      }
++      if (!ps->zero_area)
++              goto err_zero_area;
+       memset(ps->zero_area, 0, len);
++      ps->header_area = vmalloc(len);
++      if (!ps->header_area)
++              goto err_header_area;
++
+       return 0;
++
++err_header_area:
++      vfree(ps->zero_area);
++
++err_zero_area:
++      vfree(ps->area);
++
++err_area:
++      return r;
+ }
+ static void free_area(struct pstore *ps)
+@@ -169,6 +187,10 @@ static void free_area(struct pstore *ps)
+       if (ps->zero_area)
+               vfree(ps->zero_area);
+       ps->zero_area = NULL;
++
++      if (ps->header_area)
++              vfree(ps->header_area);
++      ps->header_area = NULL;
+ }
+ struct mdata_req {
+@@ -285,11 +307,11 @@ static int read_header(struct pstore *ps
+       if (r)
+               return r;
+-      r = chunk_io(ps, ps->area, 0, READ, 1);
++      r = chunk_io(ps, ps->header_area, 0, READ, 1);
+       if (r)
+               goto bad;
+-      dh = (struct disk_header *) ps->area;
++      dh = ps->header_area;
+       if (le32_to_cpu(dh->magic) == 0) {
+               *new_snapshot = 1;
+@@ -339,15 +361,15 @@ static int write_header(struct pstore *p
+ {
+       struct disk_header *dh;
+-      memset(ps->area, 0, ps->store->chunk_size << SECTOR_SHIFT);
++      memset(ps->header_area, 0, ps->store->chunk_size << SECTOR_SHIFT);
+-      dh = (struct disk_header *) ps->area;
++      dh = ps->header_area;
+       dh->magic = cpu_to_le32(SNAP_MAGIC);
+       dh->valid = cpu_to_le32(ps->valid);
+       dh->version = cpu_to_le32(ps->version);
+       dh->chunk_size = cpu_to_le32(ps->store->chunk_size);
+-      return chunk_io(ps, ps->area, 0, WRITE, 1);
++      return chunk_io(ps, ps->header_area, 0, WRITE, 1);
+ }
+ /*
+@@ -667,6 +689,8 @@ static int persistent_ctr(struct dm_exce
+       ps->valid = 1;
+       ps->version = SNAPSHOT_DISK_VERSION;
+       ps->area = NULL;
++      ps->zero_area = NULL;
++      ps->header_area = NULL;
+       ps->next_free = 2;      /* skipping the header and first area */
+       ps->current_committed = 0;
diff --git a/queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch b/queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch
new file mode 100644 (file)
index 0000000..3aaa79e
--- /dev/null
@@ -0,0 +1,93 @@
+From ae0b7448e91353ea5f821601a055aca6b58042cd Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 4 Sep 2009 20:40:43 +0100
+Subject: dm snapshot: fix on disk chunk size validation
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit ae0b7448e91353ea5f821601a055aca6b58042cd upstream.
+
+Fix some problems seen in the chunk size processing when activating a
+pre-existing snapshot.
+
+For a new snapshot, the chunk size can either be supplied by the creator
+or a default value can be used.  For an existing snapshot, the
+chunk size in the snapshot header on disk should always be used.
+
+If someone attempts to load an existing snapshot and has the 'default
+chunk size' option set, the kernel uses its default value even when it
+is incorrect for the snapshot being loaded.  This patch ensures the
+correct on-disk value is always used.
+
+Secondly, when the code does use the chunk size stored on the disk it is
+prudent to revalidate it, so the code can exit cleanly if it got
+corrupted as happened in
+https://bugzilla.redhat.com/show_bug.cgi?id=461506 .
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-exception-store.c |    5 +++++
+ drivers/md/dm-snap-persistent.c |   22 ++++++++++++++--------
+ 2 files changed, 19 insertions(+), 8 deletions(-)
+
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -191,6 +191,11 @@ int dm_exception_store_set_chunk_size(st
+               return -EINVAL;
+       }
++      if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
++              *error = "Chunk size is too high";
++              return -EINVAL;
++      }
++
+       store->chunk_size = chunk_size_ulong;
+       store->chunk_mask = chunk_size_ulong - 1;
+       store->chunk_shift = ffs(chunk_size_ulong) - 1;
+--- a/drivers/md/dm-snap-persistent.c
++++ b/drivers/md/dm-snap-persistent.c
+@@ -286,6 +286,7 @@ static int read_header(struct pstore *ps
+       struct disk_header *dh;
+       chunk_t chunk_size;
+       int chunk_size_supplied = 1;
++      char *chunk_err;
+       /*
+        * Use default chunk size (or hardsect_size, if larger) if none supplied
+@@ -329,20 +330,25 @@ static int read_header(struct pstore *ps
+       ps->version = le32_to_cpu(dh->version);
+       chunk_size = le32_to_cpu(dh->chunk_size);
+-      if (!chunk_size_supplied || ps->store->chunk_size == chunk_size)
++      if (ps->store->chunk_size == chunk_size)
+               return 0;
+-      DMWARN("chunk size %llu in device metadata overrides "
+-             "table chunk size of %llu.",
+-             (unsigned long long)chunk_size,
+-             (unsigned long long)ps->store->chunk_size);
++      if (chunk_size_supplied)
++              DMWARN("chunk size %llu in device metadata overrides "
++                     "table chunk size of %llu.",
++                     (unsigned long long)chunk_size,
++                     (unsigned long long)ps->store->chunk_size);
+       /* We had a bogus chunk_size. Fix stuff up. */
+       free_area(ps);
+-      ps->store->chunk_size = chunk_size;
+-      ps->store->chunk_mask = chunk_size - 1;
+-      ps->store->chunk_shift = ffs(chunk_size) - 1;
++      r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
++                                            &chunk_err);
++      if (r) {
++              DMERR("invalid on-disk chunk size %llu: %s.",
++                    (unsigned long long)chunk_size, chunk_err);
++              return r;
++      }
+       r = dm_io_client_resize(sectors_to_pages(ps->store->chunk_size),
+                               ps->io_client);
diff --git a/queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch b/queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch
new file mode 100644 (file)
index 0000000..baae4c2
--- /dev/null
@@ -0,0 +1,92 @@
+From 02d2fd31defce6ff77146ad0fef4f19006055d86 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 4 Sep 2009 20:40:37 +0100
+Subject: dm snapshot: refactor zero_disk_area to use chunk_io
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 02d2fd31defce6ff77146ad0fef4f19006055d86 upstream.
+
+Refactor chunk_io to prepare for the fix in the following patch.
+
+Pass an area pointer to chunk_io and simplify zero_disk_area to use
+chunk_io.  No functional change.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-snap-persistent.c |   26 +++++++-------------------
+ 1 file changed, 7 insertions(+), 19 deletions(-)
+
+--- a/drivers/md/dm-snap-persistent.c
++++ b/drivers/md/dm-snap-persistent.c
+@@ -188,7 +188,8 @@ static void do_metadata(struct work_stru
+ /*
+  * Read or write a chunk aligned and sized block of data from a device.
+  */
+-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
++static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
++                  int metadata)
+ {
+       struct dm_io_region where = {
+               .bdev = ps->store->cow->bdev,
+@@ -198,7 +199,7 @@ static int chunk_io(struct pstore *ps, c
+       struct dm_io_request io_req = {
+               .bi_rw = rw,
+               .mem.type = DM_IO_VMA,
+-              .mem.ptr.vma = ps->area,
++              .mem.ptr.vma = area,
+               .client = ps->io_client,
+               .notify.fn = NULL,
+       };
+@@ -240,7 +241,7 @@ static int area_io(struct pstore *ps, in
+       chunk = area_location(ps, ps->current_area);
+-      r = chunk_io(ps, chunk, rw, 0);
++      r = chunk_io(ps, ps->area, chunk, rw, 0);
+       if (r)
+               return r;
+@@ -254,20 +255,7 @@ static void zero_memory_area(struct psto
+ static int zero_disk_area(struct pstore *ps, chunk_t area)
+ {
+-      struct dm_io_region where = {
+-              .bdev = ps->store->cow->bdev,
+-              .sector = ps->store->chunk_size * area_location(ps, area),
+-              .count = ps->store->chunk_size,
+-      };
+-      struct dm_io_request io_req = {
+-              .bi_rw = WRITE,
+-              .mem.type = DM_IO_VMA,
+-              .mem.ptr.vma = ps->zero_area,
+-              .client = ps->io_client,
+-              .notify.fn = NULL,
+-      };
+-
+-      return dm_io(&io_req, 1, &where, NULL);
++      return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0);
+ }
+ static int read_header(struct pstore *ps, int *new_snapshot)
+@@ -297,7 +285,7 @@ static int read_header(struct pstore *ps
+       if (r)
+               return r;
+-      r = chunk_io(ps, 0, READ, 1);
++      r = chunk_io(ps, ps->area, 0, READ, 1);
+       if (r)
+               goto bad;
+@@ -359,7 +347,7 @@ static int write_header(struct pstore *p
+       dh->version = cpu_to_le32(ps->version);
+       dh->chunk_size = cpu_to_le32(ps->store->chunk_size);
+-      return chunk_io(ps, 0, WRITE, 1);
++      return chunk_io(ps, ps->area, 0, WRITE, 1);
+ }
+ /*
diff --git a/queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch b/queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch
new file mode 100644 (file)
index 0000000..1495002
--- /dev/null
@@ -0,0 +1,49 @@
+From bc8cec0dff072f1a45ce7f6b2c5234bb3411ac51 Mon Sep 17 00:00:00 2001
+From: Massimo Cirillo <maxcir@gmail.com>
+Date: Thu, 27 Aug 2009 10:44:09 +0200
+Subject: JFFS2: add missing verify buffer allocation/deallocation
+
+From: Massimo Cirillo <maxcir@gmail.com>
+
+commit bc8cec0dff072f1a45ce7f6b2c5234bb3411ac51 upstream.
+
+The function jffs2_nor_wbuf_flash_setup() doesn't allocate the verify buffer
+if CONFIG_JFFS2_FS_WBUF_VERIFY is defined, so causing a kernel panic when
+that macro is enabled and the verify function is called. Similarly the
+jffs2_nor_wbuf_flash_cleanup() must free the buffer if
+CONFIG_JFFS2_FS_WBUF_VERIFY is enabled.
+The following patch fixes the problem.
+The following patch applies to 2.6.30 kernel.
+
+Signed-off-by: Massimo Cirillo <maxcir@gmail.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/jffs2/wbuf.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/fs/jffs2/wbuf.c
++++ b/fs/jffs2/wbuf.c
+@@ -1268,10 +1268,20 @@ int jffs2_nor_wbuf_flash_setup(struct jf
+       if (!c->wbuf)
+               return -ENOMEM;
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++      c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
++      if (!c->wbuf_verify) {
++              kfree(c->wbuf);
++              return -ENOMEM;
++      }
++#endif
+       return 0;
+ }
+ void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++      kfree(c->wbuf_verify);
++#endif
+       kfree(c->wbuf);
+ }
diff --git a/queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch b/queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch
new file mode 100644 (file)
index 0000000..632805b
--- /dev/null
@@ -0,0 +1,77 @@
+From b1f1b8ce0a1d71cbc72f7540134d52b79bd8f5ac Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+Date: Sun, 30 Aug 2009 04:21:41 +0900
+Subject: nilfs2: fix preempt count underflow in nilfs_btnode_prepare_change_key
+
+From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+
+commit b1f1b8ce0a1d71cbc72f7540134d52b79bd8f5ac upstream.
+
+This will fix the following preempt count underflow reported from
+users with the title "[NILFS users] segctord problem" (Message-ID:
+<949415.6494.qm@web58808.mail.re1.yahoo.com> and Message-ID:
+<debc30fc0908270825v747c1734xa59126623cfd5b05@mail.gmail.com>):
+
+ WARNING: at kernel/sched.c:4890 sub_preempt_count+0x95/0xa0()
+ Hardware name: HP Compaq 6530b (KR980UT#ABC)
+ Modules linked in: bridge stp llc bnep rfcomm l2cap xfs exportfs nilfs2 cowloop loop vboxnetadp vboxnetflt vboxdrv btusb bluetooth uvcvideo videodev v4l1_compat v4l2_compat_ioctl32 arc4 snd_hda_codec_analog ecb iwlagn iwlcore rfkill lib80211 mac80211 snd_hda_intel snd_hda_codec ehci_hcd uhci_hcd usbcore snd_hwdep snd_pcm tg3 cfg80211 psmouse snd_timer joydev libphy ohci1394 snd_page_alloc hp_accel lis3lv02d ieee1394 led_class i915 drm i2c_algo_bit video backlight output i2c_core dm_crypt dm_mod
+ Pid: 4197, comm: segctord Not tainted 2.6.30-gentoo-r4-64 #7
+ Call Trace:
+  [<ffffffff8023fa05>] ? sub_preempt_count+0x95/0xa0
+  [<ffffffff802470f8>] warn_slowpath_common+0x78/0xd0
+  [<ffffffff8024715f>] warn_slowpath_null+0xf/0x20
+  [<ffffffff8023fa05>] sub_preempt_count+0x95/0xa0
+  [<ffffffffa04ce4db>] nilfs_btnode_prepare_change_key+0x11b/0x190 [nilfs2]
+  [<ffffffffa04d01ad>] nilfs_btree_assign_p+0x19d/0x1e0 [nilfs2]
+  [<ffffffffa04d10ad>] nilfs_btree_assign+0xbd/0x130 [nilfs2]
+  [<ffffffffa04cead7>] nilfs_bmap_assign+0x47/0x70 [nilfs2]
+  [<ffffffffa04d9bc6>] nilfs_segctor_do_construct+0x956/0x20f0 [nilfs2]
+  [<ffffffff805ac8e2>] ? _spin_unlock_irqrestore+0x12/0x40
+  [<ffffffff803c06e0>] ? __up_write+0xe0/0x150
+  [<ffffffff80262959>] ? up_write+0x9/0x10
+  [<ffffffffa04ce9f3>] ? nilfs_bmap_test_and_clear_dirty+0x43/0x60 [nilfs2]
+  [<ffffffffa04cd627>] ? nilfs_mdt_fetch_dirty+0x27/0x60 [nilfs2]
+  [<ffffffffa04db5fc>] nilfs_segctor_construct+0x8c/0xd0 [nilfs2]
+  [<ffffffffa04dc3dc>] nilfs_segctor_thread+0x15c/0x3a0 [nilfs2]
+  [<ffffffffa04dbe20>] ? nilfs_construction_timeout+0x0/0x10 [nilfs2]
+  [<ffffffff80252633>] ? add_timer+0x13/0x20
+  [<ffffffff802370da>] ? __wake_up_common+0x5a/0x90
+  [<ffffffff8025e960>] ? autoremove_wake_function+0x0/0x40
+  [<ffffffffa04dc280>] ? nilfs_segctor_thread+0x0/0x3a0 [nilfs2]
+  [<ffffffffa04dc280>] ? nilfs_segctor_thread+0x0/0x3a0 [nilfs2]
+  [<ffffffff8025e556>] kthread+0x56/0x90
+  [<ffffffff8020cdea>] child_rip+0xa/0x20
+  [<ffffffff8025e500>] ? kthread+0x0/0x90
+  [<ffffffff8020cde0>] ? child_rip+0x0/0x20
+
+This problem was caused due to a missing radix_tree_preload() call in
+the retry path of nilfs_btnode_prepare_change_key() function.
+
+Reported-by: Eric A <eric225125@yahoo.com>
+Reported-by: Jerome Poulin <jeromepoulin@gmail.com>
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+Tested-by: Jerome Poulin <jeromepoulin@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nilfs2/btnode.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nilfs2/btnode.c
++++ b/fs/nilfs2/btnode.c
+@@ -206,6 +206,7 @@ int nilfs_btnode_prepare_change_key(stru
+                * We cannot call radix_tree_preload for the kernels older
+                * than 2.6.23, because it is not exported for modules.
+                */
++retry:
+               err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
+               if (err)
+                       goto failed_unlock;
+@@ -216,7 +217,6 @@ int nilfs_btnode_prepare_change_key(stru
+                                      (unsigned long long)oldkey,
+                                      (unsigned long long)newkey);
+-retry:
+               spin_lock_irq(&btnc->tree_lock);
+               err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
+               spin_unlock_irq(&btnc->tree_lock);
diff --git a/queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch b/queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch
new file mode 100644 (file)
index 0000000..9b4072a
--- /dev/null
@@ -0,0 +1,159 @@
+From 6faf17f6f1ffc586d16efc2f9fa2083a7785ee74 Mon Sep 17 00:00:00 2001
+From: Chris Wright <chrisw@sous-sol.org>
+Date: Fri, 28 Aug 2009 13:00:06 -0700
+Subject: PCI SR-IOV: correct broken resource alignment calculations
+
+From: Chris Wright <chrisw@sous-sol.org>
+
+commit 6faf17f6f1ffc586d16efc2f9fa2083a7785ee74 upstream.
+
+An SR-IOV capable device includes an SR-IOV PCIe capability which
+describes the Virtual Function (VF) BAR requirements.  A typical SR-IOV
+device can support multiple VFs whose BARs must be in a contiguous region,
+effectively an array of VF BARs.  The BAR reports the size requirement
+for a single VF.  We calculate the full range needed by simply multiplying
+the VF BAR size with the number of possible VFs and create a resource
+spanning the full range.
+
+This all seems sane enough except it artificially inflates the alignment
+requirement for the VF BAR.  The VF BAR need only be aligned to the size
+of a single BAR not the contiguous range of VF BARs.  This can cause us
+to fail to allocate resources for the BAR despite the fact that we
+actually have enough space.
+
+This patch adds a thin PCI specific layer over the generic
+resource_alignment() function which is aware of the special nature of
+VF BARs and does sorting and allocation based on the smaller alignment
+requirement.
+
+I recognize that while resource_alignment is generic, it's basically a
+PCI helper.  An alternative to this patch is to add PCI VF BAR specific
+information to struct resource.  I opted for the extra layer rather than
+adding such PCI specific information to struct resource.  This does
+have the slight downside that we don't cache the BAR size and re-read
+for each alignment query (happens a small handful of times during boot
+for each VF BAR).
+
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Matthew Wilcox <matthew@wil.cx>
+Cc: Yu Zhao <yu.zhao@intel.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/iov.c       |   23 +++++++++++++++++++++++
+ drivers/pci/pci.h       |   13 +++++++++++++
+ drivers/pci/setup-bus.c |    4 ++--
+ drivers/pci/setup-res.c |    6 +++---
+ 4 files changed, 41 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/iov.c
++++ b/drivers/pci/iov.c
+@@ -595,6 +595,29 @@ int pci_iov_resource_bar(struct pci_dev 
+ }
+ /**
++ * pci_sriov_resource_alignment - get resource alignment for VF BAR
++ * @dev: the PCI device
++ * @resno: the resource number
++ *
++ * Returns the alignment of the VF BAR found in the SR-IOV capability.
++ * This is not the same as the resource size which is defined as
++ * the VF BAR size multiplied by the number of VFs.  The alignment
++ * is just the VF BAR size.
++ */
++int pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
++{
++      struct resource tmp;
++      enum pci_bar_type type;
++      int reg = pci_iov_resource_bar(dev, resno, &type);
++
++      if (!reg)
++              return 0;
++
++       __pci_read_base(dev, type, &tmp, reg);
++      return resource_alignment(&tmp);
++}
++
++/**
+  * pci_restore_iov_state - restore the state of the IOV capability
+  * @dev: the PCI device
+  */
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -234,6 +234,7 @@ extern int pci_iov_init(struct pci_dev *
+ extern void pci_iov_release(struct pci_dev *dev);
+ extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+                               enum pci_bar_type *type);
++extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
+ extern void pci_restore_iov_state(struct pci_dev *dev);
+ extern int pci_iov_bus_range(struct pci_bus *bus);
+ #else
+@@ -259,4 +260,16 @@ static inline int pci_iov_bus_range(stru
+ }
+ #endif /* CONFIG_PCI_IOV */
++static inline int pci_resource_alignment(struct pci_dev *dev,
++                                       struct resource *res)
++{
++#ifdef CONFIG_PCI_IOV
++      int resno = res - dev->resource;
++
++      if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
++              return pci_sriov_resource_alignment(dev, resno);
++#endif
++      return resource_alignment(res);
++}
++
+ #endif /* DRIVERS_PCI_H */
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -25,7 +25,7 @@
+ #include <linux/ioport.h>
+ #include <linux/cache.h>
+ #include <linux/slab.h>
+-
++#include "pci.h"
+ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
+ {
+@@ -355,7 +355,7 @@ static int pbus_size_mem(struct pci_bus 
+                               continue;
+                       r_size = resource_size(r);
+                       /* For bridges size != alignment */
+-                      align = resource_alignment(r);
++                      align = pci_resource_alignment(dev, r);
+                       order = __ffs(align) - 20;
+                       if (order > 11) {
+                               dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -145,7 +145,7 @@ int pci_assign_resource(struct pci_dev *
+       size = resource_size(res);
+       min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+-      align = resource_alignment(res);
++      align = pci_resource_alignment(dev, res);
+       if (!align) {
+               dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
+                       "alignment) %pR flags %#lx\n",
+@@ -236,7 +236,7 @@ void pdev_sort_resources(struct pci_dev 
+               if (!(r->flags) || r->parent)
+                       continue;
+-              r_align = resource_alignment(r);
++              r_align = pci_resource_alignment(dev, r);
+               if (!r_align) {
+                       dev_warn(&dev->dev, "BAR %d: bogus alignment "
+                               "%pR flags %#lx\n",
+@@ -248,7 +248,7 @@ void pdev_sort_resources(struct pci_dev 
+                       struct resource_list *ln = list->next;
+                       if (ln)
+-                              align = resource_alignment(ln->res);
++                              align = pci_resource_alignment(ln->dev, ln->res);
+                       if (r_align > align) {
+                               tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
diff --git a/queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch b/queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch
new file mode 100644 (file)
index 0000000..78440e4
--- /dev/null
@@ -0,0 +1,98 @@
+From 601e7638254c118fca135af9b1a9f35061420f62 Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+Date: Tue, 26 May 2009 20:35:48 +0000
+Subject: SCSI: sd: fix bug in SCSI async probing
+
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+
+commit 601e7638254c118fca135af9b1a9f35061420f62 upstream.
+
+The async split up of probing in sd.c created a potential failure case where
+something goes wrong with device_add(), but which we don't recover properly.
+Since, in general, asynchronous error handling is hard, move the device_add()
+into the asynchronous path (it should be fast) and make sure all the deferred
+processing cannot fail.
+
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/sd.c |   45 +++++++++++++++++++++------------------------
+ 1 file changed, 21 insertions(+), 24 deletions(-)
+
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1902,24 +1902,6 @@ static void sd_probe_async(void *data, a
+       index = sdkp->index;
+       dev = &sdp->sdev_gendev;
+-      if (!sdp->request_queue->rq_timeout) {
+-              if (sdp->type != TYPE_MOD)
+-                      blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
+-              else
+-                      blk_queue_rq_timeout(sdp->request_queue,
+-                                           SD_MOD_TIMEOUT);
+-      }
+-
+-      device_initialize(&sdkp->dev);
+-      sdkp->dev.parent = &sdp->sdev_gendev;
+-      sdkp->dev.class = &sd_disk_class;
+-      dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev));
+-
+-      if (device_add(&sdkp->dev))
+-              goto out_free_index;
+-
+-      get_device(&sdp->sdev_gendev);
+-
+       if (index < SD_MAX_DISKS) {
+               gd->major = sd_major((index & 0xf0) >> 4);
+               gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+@@ -1954,11 +1936,6 @@ static void sd_probe_async(void *data, a
+       sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+                 sdp->removable ? "removable " : "");
+-
+-      return;
+-
+- out_free_index:
+-      ida_remove(&sd_index_ida, index);
+ }
+ /**
+@@ -2026,6 +2003,24 @@ static int sd_probe(struct device *dev)
+       sdkp->openers = 0;
+       sdkp->previous_state = 1;
++      if (!sdp->request_queue->rq_timeout) {
++              if (sdp->type != TYPE_MOD)
++                      blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
++              else
++                      blk_queue_rq_timeout(sdp->request_queue,
++                                           SD_MOD_TIMEOUT);
++      }
++
++      device_initialize(&sdkp->dev);
++      sdkp->dev.parent = &sdp->sdev_gendev;
++      sdkp->dev.class = &sd_disk_class;
++      dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev));
++
++      if (device_add(&sdkp->dev))
++              goto out_free_index;
++
++      get_device(&sdp->sdev_gendev);
++
+       async_schedule(sd_probe_async, sdkp);
+       return 0;
+@@ -2055,8 +2050,10 @@ static int sd_probe(struct device *dev)
+  **/
+ static int sd_remove(struct device *dev)
+ {
+-      struct scsi_disk *sdkp = dev_get_drvdata(dev);
++      struct scsi_disk *sdkp;
++      async_synchronize_full();
++      sdkp = dev_get_drvdata(dev);
+       device_del(&sdkp->dev);
+       del_gendisk(sdkp->disk);
+       sd_shutdown(dev);
index 6481d94f00d68473b042d82c22102b2eea1c7b0d..4f4979898d6d14d5bba58d554658640e80afb242 100644 (file)
@@ -8,3 +8,15 @@ sparc64-kill-spurious-nmi-watchdog-triggers-by-increasing-limit-to-30-seconds.pa
 sparc64-validate-linear-d-tlb-misses.patch
 sparc64-fix-bootup-with-mcount-in-some-configs.patch
 sparc-sys32.s-incorrect-compat-layer-splice-system-call.patch
+jffs2-add-missing-verify-buffer-allocation-deallocation.patch
+slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch
+nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch
+pci-sr-iov-correct-broken-resource-alignment-calculations.patch
+scsi-sd-fix-bug-in-scsi-async-probing.patch
+sound-oxygen-handle-cards-with-missing-eeprom.patch
+sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch
+dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch
+dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch
+dm-snapshot-fix-header-corruption-race-on-invalidation.patch
+dm-exception-store-split-set_chunk_size.patch
+dm-snapshot-fix-on-disk-chunk-size-validation.patch
diff --git a/queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch b/queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch
new file mode 100644 (file)
index 0000000..6abc86a
--- /dev/null
@@ -0,0 +1,46 @@
+From d76b1590e06a63a3d8697168cd0aabf1c4b3cb3a Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Thu, 3 Sep 2009 22:38:59 +0300
+Subject: slub: Fix kmem_cache_destroy() with SLAB_DESTROY_BY_RCU
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+commit d76b1590e06a63a3d8697168cd0aabf1c4b3cb3a upstream.
+
+kmem_cache_destroy() should call rcu_barrier() *after* kmem_cache_close() and
+*before* sysfs_slab_remove() or risk rcu_free_slab() being called after
+kmem_cache is deleted (kfreed).
+
+rmmod nf_conntrack can crash the machine because it has to kmem_cache_destroy()
+a SLAB_DESTROY_BY_RCU enabled cache.
+
+Reported-by: Zdenek Kabelac <zdenek.kabelac@gmail.com>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/slub.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -2490,8 +2490,6 @@ static inline int kmem_cache_close(struc
+  */
+ void kmem_cache_destroy(struct kmem_cache *s)
+ {
+-      if (s->flags & SLAB_DESTROY_BY_RCU)
+-              rcu_barrier();
+       down_write(&slub_lock);
+       s->refcount--;
+       if (!s->refcount) {
+@@ -2502,6 +2500,8 @@ void kmem_cache_destroy(struct kmem_cach
+                               "still has objects.\n", s->name, __func__);
+                       dump_stack();
+               }
++              if (s->flags & SLAB_DESTROY_BY_RCU)
++                      rcu_barrier();
+               sysfs_slab_remove(s);
+       } else
+               up_write(&slub_lock);
diff --git a/queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch b/queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch
new file mode 100644 (file)
index 0000000..812dc5e
--- /dev/null
@@ -0,0 +1,35 @@
+From b91ab72b830e1494c2c7f8de05ccb2ab2c9cfb26 Mon Sep 17 00:00:00 2001
+From: Clemens Ladisch <clemens@ladisch.de>
+Date: Tue, 1 Sep 2009 08:23:58 +0200
+Subject: sound: oxygen: fix MCLK rate for 192 kHz playback
+
+From: Clemens Ladisch <clemens@ladisch.de>
+
+commit b91ab72b830e1494c2c7f8de05ccb2ab2c9cfb26 upstream.
+
+Do not forget to program the MCLK ratio for the I2S output.
+Otherwise, the master clock frequency can be too high for
+the DACs at sample frequencies above 96 kHz.
+
+Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/oxygen/oxygen_pcm.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/oxygen/oxygen_pcm.c
++++ b/sound/pci/oxygen/oxygen_pcm.c
+@@ -469,9 +469,11 @@ static int oxygen_multich_hw_params(stru
+       oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
+                             oxygen_rate(hw_params) |
+                             chip->model.dac_i2s_format |
++                            oxygen_i2s_mclk(hw_params) |
+                             oxygen_i2s_bits(hw_params),
+                             OXYGEN_I2S_RATE_MASK |
+                             OXYGEN_I2S_FORMAT_MASK |
++                            OXYGEN_I2S_MCLK_MASK |
+                             OXYGEN_I2S_BITS_MASK);
+       oxygen_update_dac_routing(chip);
+       oxygen_update_spdif_source(chip);
diff --git a/queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch b/queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch
new file mode 100644 (file)
index 0000000..9d21782
--- /dev/null
@@ -0,0 +1,38 @@
+From 92653453c3015c083b9fe0ad48261c6b2267d482 Mon Sep 17 00:00:00 2001
+From: Clemens Ladisch <clemens@ladisch.de>
+Date: Wed, 2 Sep 2009 18:25:39 +0200
+Subject: sound: oxygen: handle cards with missing EEPROM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Clemens Ladisch <clemens@ladisch.de>
+
+commit 92653453c3015c083b9fe0ad48261c6b2267d482 upstream.
+
+The card model detection code introduced in 2.6.30 that tries to work
+around partially broken EEPROM contents by reading the EEPROM directly
+does not handle cards where the EEPROM has been omitted.  In this case,
+we have to use the default ID to allow the driver to load.
+
+Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
+Reported-and-tested-by: Ozan Çağlayan <ozan@pardus.org.tr>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/oxygen/oxygen_lib.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/sound/pci/oxygen/oxygen_lib.c
++++ b/sound/pci/oxygen/oxygen_lib.c
+@@ -260,6 +260,9 @@ oxygen_search_pci_id(struct oxygen *chip
+        * chip didn't if the first EEPROM word was overwritten.
+        */
+       subdevice = oxygen_read_eeprom(chip, 2);
++      /* use default ID if EEPROM is missing */
++      if (subdevice == 0xffff)
++              subdevice = 0x8788;
+       /*
+        * We use only the subsystem device ID for searching because it is
+        * unique even without the subsystem vendor ID, which may have been