Linux 3.0.4
I'm announcing the release of the 3.0.4 kernel.
All users of the 3.0 kernel series must upgrade.
The updated 3.0.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-3.0.y.git
and can be browsed at the normal kernel.org git web browser:
http://git.kernel.org/?p=linux/kernel/git/stable/linux-3.0.y.git;a=summarythanks,
greg k-h
------------
Makefile | 2 - arch/x86/include/asm/xen/page.h | 4 +-- arch/x86/kernel/apic/x2apic_uv_x.c | 1 arch/x86/kernel/cpu/intel.c | 10 +++---- arch/x86/kernel/cpu/mtrr/main.c | 23 +++++++++++++++++ arch/x86/platform/olpc/olpc.c | 4 +-- arch/x86/vdso/vdso32/sysenter.S | 2 - arch/x86/xen/enlighten.c | 4 +-- arch/x86/xen/mmu.c | 12 ++++++--- arch/x86/xen/smp.c | 4 +-- drivers/block/loop.c | 6 +++- drivers/block/xen-blkfront.c | 6 ++-- drivers/edac/i7core_edac.c | 2 - drivers/gpu/drm/radeon/radeon_connectors.c | 10 +++++++ drivers/gpu/drm/ttm/ttm_bo.c | 4 ++- drivers/mmc/host/sdhci.c | 3 -- drivers/net/igb/e1000_82575.c | 1 drivers/net/wireless/rt2x00/rt2x00usb.c | 17 +++++------- fs/befs/linuxvfs.c | 23 ++++++++++------- fs/btrfs/extent-tree.c | 12 +++++++-- fs/btrfs/tree-log.c | 28 ++++++++++++++++++--- fs/btrfs/volumes.c | 17 ++++++++++++ fs/btrfs/volumes.h | 2 + fs/cifs/connect.c | 3 +- fs/cifs/dir.c | 4 +-- fs/ext4/ext4_jbd2.h | 4 +-- fs/ext4/inode.c | 26 ++++++++++++++++++- fs/ext4/page-io.c | 6 +++- fs/ext4/super.c | 1 fs/fuse/dev.c | 4 +++ fs/nfs/callback.h | 2 - fs/nfs/callback_proc.c | 25 ++++++++++++++----- fs/nfs/callback_xdr.c | 24 +++++------------- fs/nfs/objlayout/objio_osd.c | 28 +++++++++------------ fs/nfs/objlayout/pnfs_osd_xdr_cli.c | 3 ++ include/linux/personality.h | 1 include/linux/stop_machine.h | 2 + kernel/irq/generic-chip.c | 4 +-- kernel/stop_machine.c | 2 - kernel/sys.c | 38 +++++++++++++++++++++++++++++ sound/pci/ac97/ac97_patch.c | 1 sound/usb/caiaq/audio.c | 31 ++++++++++++++++++++--- sound/usb/caiaq/device.h | 1 sound/usb/mixer.c | 3 +- 44 files changed, 297 insertions(+), 113 deletions(-)
Aaron Lu (1):
mmc: sdhci: fix retuning timer wrongly deleted in sdhci_tasklet_finish
Andi Kleen (1):
Add a personality to report 2.6.x version numbers
Boaz Harrosh (2):
pnfs-obj: Fix the comp_index != 0 case
pnfs-obj: Bug when we are running out of bio
Carolyn Wyborny (1):
igb: Fix lack of flush after register write and before delay
Curt Wohlgemuth (1):
ext4: Fix ext4_should_writeback_data() for no-journal mode
Daniel Mack (1):
ALSA: snd_usb_caiaq: track submitted output urbs
Daniel T Chen (1):
ALSA: ac97: Add HP Compaq dc5100 SFF(PT003AW) to Headphone Jack Sense whitelist
Greg Kroah-Hartman (1):
Linux 3.0.4
H. Peter Anvin (1):
x86-32, vdso: On system call restart after SYSENTER, use int $0x80
Jack Steiner (1):
x86, UV: Remove UV delay in starting slave cpus
Jan Beulich (1):
xen/x86: replace order-based range checking of M2P table by linear one
Jeff Layton (1):
cifs: demote cERROR in build_path_from_dentry to cFYI
Jiaying Zhang (1):
ext4: call ext4_ioend_wait and ext4_flush_completed_IO in ext4_evict_inode
Josef Bacik (1):
Btrfs: detect wether a device supports discard
Kay Sievers (1):
loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
Len Brown (1):
x86, intel, power: Correct the MSR_IA32_ENERGY_PERF_BIAS message
Marcin Slusarz (1):
drm/ttm: fix ttm_bo_add_ttm(user) failure path
Mathias Krause (1):
i7core_edac: fixed typo in error count calculation
Miklos Szeredi (1):
fuse: check size of FUSE_NOTIFY_INVAL_ENTRY message
Paul Fox (1):
x86, olpc: Wait for last byte of EC command to be accepted
Stanislaw Gruszka (1):
rt2x00: fix order of entry flags modification
Stefan Bader (2):
xen-blkfront: Drop name and minor adjustments for emulated scsi devices
xen-blkfront: Fix one off warning about name clash
Stefano Stabellini (1):
xen: Do not enable PV IPIs when vector callback not present
Steve French (1):
possible memory corruption on mount
Suresh Siddha (1):
x86, mtrr: lock stop machine during MTRR rendezvous sequence
Takashi Iwai (1):
ALSA: usb-audio - Fix missing mixer dB information
Tao Ma (1):
ext4: Resolve the hang of direct i/o read in handling EXT4_IO_END_UNWRITTEN.
Theodore Ts'o (1):
ext4: fix nomblk_io_submit option so it correctly converts uninit blocks
Thomas Reim (1):
drm/radeon: Extended DDC Probing for Toshiba L300D Radeon Mobility X1100 HDMI-A Connector
Timo Warns (1):
befs: Validate length of long symbolic links.
Trond Myklebust (2):
NFSv4.1: Fix the callback 'highest_used_slotid' behaviour NFSv4.1: Return NFS4ERR_BADSESSION to callbacks during session resets
[email protected] (1):
genirq: Fix wrong bit operation
liubo (1):
Btrfs: fix an oops of log replay
Makefile +1 -1
@@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 0 -SUBLEVEL = 3 +SUBLEVEL = 4 EXTRAVERSION = NAME = Sneaky Weasel
arch/x86/include/asm/xen/page.h +2 -2
@@ -39,7 +39,7 @@ typedef struct xpaddr { ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE))extern unsigned long *machine_to_phys_mapping; -extern unsigned int machine_to_phys_order; +extern unsigned long machine_to_phys_nr;extern unsigned long get_phys_to_machine (unsigned long pfn);extern bool set_phys_to_machine (unsigned long pfn,unsigned long mfn);
@@ -87,7 +87,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)if (xen_feature (XENFEAT_auto_translated_physmap))return mfn; -if (unlikely ((mfn >> machine_to_phys_order) !=0 )) { +if (unlikely (mfn >= machine_to_phys_nr)) { pfn = ~0 ; goto try_override; }
arch/x86/kernel/apic/x2apic_uv_x.c +0 -1
@@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri ((start_rip <<UVH_IPI_INT_VECTOR_SHFT ) >>12 ) |APIC_DM_INIT ;uv_write_global_mmr64 (pnode,UVH_IPI_INT , val); -mdelay (10 ); val = (1UL <<UVH_IPI_INT_SEND_SHFT ) | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
arch/x86/kernel/cpu/intel.c +5 -5
@@ -465,11 +465,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)u64 epb;rdmsrl (MSR_IA32_ENERGY_PERF_BIAS , epb); -if ((epb &0xF ) ==0 ) { -printk_once (KERN_WARNING ,"x86: updated energy_perf_bias" -" to 'normal' from 'performance'\n" -"You can view and update epb via utility," -" such as x86_energy_perf_policy(8)\n" ); +if ((epb &0xF ) ==ENERGY_PERF_BIAS_PERFORMANCE ) { +printk_once (KERN_WARNING "ENERGY_PERF_BIAS:" +" Set to 'normal', was 'performance'\n" +"ENERGY_PERF_BIAS: View and update with" +" x86_energy_perf_policy(8)\n" ); epb = (epb & ~0xF ) |ENERGY_PERF_BIAS_NORMAL ;wrmsrl (MSR_IA32_ENERGY_PERF_BIAS , epb); }
arch/x86/kernel/cpu/mtrr/main.c +23 -0
@@ -248,6 +248,25 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typunsigned long flags;int cpu; +#ifdef CONFIG_SMP +/* +* If this cpu is not yet active, we are in the cpu online path. There +* can be no stop_machine() in parallel, as stop machine ensures this +* by using get_online_cpus(). We can skip taking the stop_cpus_mutex, +* as we don't need it and also we can't afford to block while waiting +* for the mutex. +* +* If this cpu is active, we need to prevent stop_machine() happening +* in parallel by taking the stop cpus mutex. +* +* Also, this is called in the context of cpu online path or in the +* context where cpu hotplug is prevented. So checking the active status +* of the raw_smp_processor_id() is safe. +*/ +if (cpu_active (raw_smp_processor_id ())) +mutex_lock (&stop_cpus_mutex); +#endif +preempt_disable (); data.smp_reg = reg;
@@ -330,6 +349,10 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typlocal_irq_restore (flags);preempt_enable (); +#ifdef CONFIG_SMP +if (cpu_active (raw_smp_processor_id ())) +mutex_unlock (&stop_cpus_mutex); +#endif }/**
arch/x86/platform/olpc/olpc.c +2 -2
@@ -157,13 +157,13 @@ restart:if (inbuf && inlen) {/* write data to EC */ for (i =0 ; i < inlen; i++) { +pr_devel ("olpc-ec: sending cmd arg 0x%x\n" , inbuf[i]); +outb (inbuf[i],0x68 );if (wait_on_ibf (0x6c ,0 )) {printk (KERN_ERR "olpc-ec: timeout waiting for" " EC accept data!\n" ); goto err; } -pr_devel ("olpc-ec: sending cmd arg 0x%x\n" , inbuf[i]); -outb (inbuf[i],0x68 ); } }if (outbuf && outlen) {
arch/x86/vdso/vdso32/sysenter.S +1 -1
@@ -43,7 +43,7 @@ __kernel_vsyscall: .space 7,0x90 /* 14: System call restart point is here! (SYSENTER_RETURN-2) */ - jmp .Lenter_kernel + int $0x80 /* 16: System call normal return point is here! */ VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */ pop %ebp
arch/x86/xen/enlighten.c +2 -2
@@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(xen_domain_type);unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START ;EXPORT_SYMBOL (machine_to_phys_mapping); -unsigned int machine_to_phys_order; -EXPORT_SYMBOL (machine_to_phys_order); +unsigned long machine_to_phys_nr; +EXPORT_SYMBOL (machine_to_phys_nr);struct start_info *xen_start_info;EXPORT_SYMBOL_GPL (xen_start_info);
arch/x86/xen/mmu.c +8 -4
@@ -1626,15 +1626,19 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)void __init xen_setup_machphys_mapping (void ) {struct xen_machphys_mapping mapping; -unsigned long machine_to_phys_nr_ents;if (HYPERVISOR_memory_op (XENMEM_machphys_mapping, &mapping) ==0 ) { machine_to_phys_mapping = (unsigned long *)mapping.v_start; - machine_to_phys_nr_ents = mapping.max_mfn +1 ; + machine_to_phys_nr = mapping.max_mfn +1 ; }else { - machine_to_phys_nr_ents =MACH2PHYS_NR_ENTRIES ; + machine_to_phys_nr =MACH2PHYS_NR_ENTRIES ; } - machine_to_phys_order =fls (machine_to_phys_nr_ents -1 ); +#ifdef CONFIG_X86_32 +if ((machine_to_phys_mapping + machine_to_phys_nr) + < machine_to_phys_mapping) + machine_to_phys_nr = (unsigned long *)NULL + - machine_to_phys_mapping; +#endif }#ifdef CONFIG_X86_64
arch/x86/xen/smp.c +2 -2
@@ -521,8 +521,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)native_smp_prepare_cpus (max_cpus);WARN_ON (xen_smp_intr_init (0 )); -if (!xen_have_vector_callback) -return ;xen_init_lock_cpu (0 );xen_init_spinlocks (); }
@@ -546,6 +544,8 @@ static void xen_hvm_cpu_die(unsigned int cpu)void __init xen_hvm_smp_init (void ) { +if (!xen_have_vector_callback) +return ; smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; smp_ops.smp_send_reschedule = xen_smp_send_reschedule; smp_ops.cpu_up = xen_hvm_cpu_up;
drivers/block/loop.c +4 -2
@@ -750,10 +750,10 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)ssize_t ret;char *p =NULL ; -mutex_lock (&lo->lo_ctl_mutex); +spin_lock_irq (&lo->lo_lock);if (lo->lo_backing_file) p =d_path (&lo->lo_backing_file->f_path, buf,PAGE_SIZE -1 ); -mutex_unlock (&lo->lo_ctl_mutex); +spin_unlock_irq (&lo->lo_lock);if (IS_ERR_OR_NULL (p)) ret =PTR_ERR (p);
@@ -1007,7 +1007,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)kthread_stop (lo->lo_thread); +spin_lock_irq (&lo->lo_lock); lo->lo_backing_file =NULL ; +spin_unlock_irq (&lo->lo_lock);loop_release_xfer (lo); lo->transfer =NULL ;
drivers/block/xen-blkfront.c +3 -3
@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock);#define BLKIF_MINOR_EXT (dev) ((dev)&(~EXTENDED))#define EMULATED_HD_DISK_MINOR_OFFSET (0)#define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) -#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) -#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) +#define EMULATED_SD_DISK_MINOR_OFFSET (0) +#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256)#define DEV_NAME "xvd"/* name in /dev */
@@ -529,7 +529,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, minor =BLKIF_MINOR_EXT (info->vdevice); nr_parts =PARTS_PER_EXT_DISK ; offset = minor / nr_parts; -if (xen_hvm_domain () && offset <=EMULATED_HD_DISK_NAME_OFFSET +4 ) +if (xen_hvm_domain () && offset <EMULATED_HD_DISK_NAME_OFFSET +4 )printk (KERN_WARNING "blkfront: vdevice 0x%x might conflict with " "emulated IDE disks,\n\t choose an xvd device name" "from xvde on\n" , info->vdevice);
drivers/edac/i7core_edac.c +1 -1
@@ -1670,7 +1670,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,char *type, *optype, *err, *msg;unsigned long error = m->status &0x1ff0000l ;u32 optypenum = (m->status >>4 ) &0x07 ; -u32 core_err_cnt = (m->status >>38 ) &&0x7fff ; +u32 core_err_cnt = (m->status >>38 ) &0x7fff ;u32 dimm = (m->misc >>16 ) &0x3 ;u32 channel = (m->misc >>18 ) &0x3 ;u32 syndrome = m->misc >>32 ;
drivers/gpu/drm/radeon/radeon_connectors.c +10 -0
@@ -466,6 +466,16 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev, (supported_device == ATOM_DEVICE_DFP2_SUPPORT))return true; } +/* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100 +* (RS690M) sends data to i2c bus for a HDMI connector that +* is not implemented */ +if ((dev->pdev->device ==0x791f ) && + (dev->pdev->subsystem_vendor ==0x1179 ) && + (dev->pdev->subsystem_device ==0xff68 )) { +if ((connector_type ==DRM_MODE_CONNECTOR_HDMIA ) && + (supported_device ==ATOM_DEVICE_DFP2_SUPPORT )) +return true; + }/* Default: no EDID header probe required for DDC probing */ return false;
drivers/gpu/drm/ttm/ttm_bo.c +3 -1
@@ -353,8 +353,10 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) ret =ttm_tt_set_user (bo->ttm, current, bo->buffer_start, bo->num_pages); -if (unlikely (ret !=0 )) +if (unlikely (ret !=0 )) {ttm_tt_destroy (bo->ttm); + bo->ttm =NULL ; + }break ;default : printk(KERN_ERR TTM_PFX "Illegal buffer object type\n");
drivers/mmc/host/sdhci.c +0 -3
@@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigned long param)del_timer (&host->timer); -if (host->version >=SDHCI_SPEC_300 ) -del_timer (&host->tuning_timer); - mrq = host->mrq;/*
drivers/net/igb/e1000_82575.c +1 -0
@@ -1735,6 +1735,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) ctrl |=E1000_CTRL_RST ;wr32 (E1000_CTRL , ctrl); +wrfl ();/* Add delay to insure DEV_RST has time to complete */ if (global_device_reset)
drivers/net/wireless/rt2x00/rt2x00usb.c +7 -10
@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)struct queue_entry *entry = (struct queue_entry *)urb->context;struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -if (!test_and_clear_bit (ENTRY_OWNER_DEVICE_DATA , &entry->flags)) +if (!test_bit (ENTRY_OWNER_DEVICE_DATA , &entry->flags))return ; - -if (rt2x00dev->ops->lib->tx_dma_done) - rt2x00dev->ops->lib->tx_dma_done (entry); - -/* -* Report the frame as DMA done -*/ -rt2x00lib_dmadone (entry); -/* * Check if the frame was correctly uploaded */ if (urb->status)set_bit (ENTRY_DATA_IO_FAILED , &entry->flags); +/* +* Report the frame as DMA done +*/ +rt2x00lib_dmadone (entry); +if (rt2x00dev->ops->lib->tx_dma_done) + rt2x00dev->ops->lib->tx_dma_done (entry);/* * Schedule the delayed work for reading the TX status * from the device.
fs/befs/linuxvfs.c +14 -9
@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)befs_data_stream *data = &befs_ino->i_data.ds;befs_off_t len = data->size; -befs_debug (sb,"Follow long symlink" ); - - link =kmalloc (len,GFP_NOFS ); -if (!link) { - link =ERR_PTR (-ENOMEM ); - }else if (befs_read_lsymlink (sb, data, link, len) != len) { -kfree (link); -befs_error (sb,"Failed to read entire long symlink" ); +if (len ==0 ) { +befs_error (sb,"Long symlink with illegal length" ); link =ERR_PTR (-EIO ); }else { - link[len -1 ] ='\0' ; +befs_debug (sb,"Follow long symlink" ); + + link =kmalloc (len,GFP_NOFS ); +if (!link) { + link =ERR_PTR (-ENOMEM ); + }else if (befs_read_lsymlink (sb, data, link, len) != len) { +kfree (link); +befs_error (sb,"Failed to read entire long symlink" ); + link =ERR_PTR (-EIO ); + }else { + link[len -1 ] ='\0' ; + } } }else { link = befs_ino->i_data.symlink;
fs/btrfs/extent-tree.c +10 -2
@@ -1784,6 +1784,9 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,for (i =0 ; i < multi->num_stripes; i++, stripe++) { +if (!stripe->dev->can_discard) +continue ; + ret =btrfs_issue_discard (stripe->dev->bdev, stripe->physical, stripe->length);
@@ -1791,11 +1794,16 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, discarded_bytes += stripe->length; else if (ret != -EOPNOTSUPP) break; + +/* +* Just in case we get back EOPNOTSUPP for some reason, +* just ignore the return value so we don't screw up +* people calling discard_extent. +*/ + ret =0 ; }kfree (multi); } -if (discarded_bytes && ret == -EOPNOTSUPP ) - ret =0 ;if (actual_bytes) *actual_bytes = discarded_bytes;
fs/btrfs/tree-log.c +24 -4
@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, struct extent_buffer *eb, int slot, struct btrfs_key *key) { - struct inode *dir; -int ret; struct btrfs_inode_ref *ref; +struct btrfs_dir_item *di; +struct inode *dir;struct inode *inode; -char *name; -int namelen;unsigned long ref_ptr;unsigned long ref_end; +char *name; +int namelen; +int ret;int search_done =0 ;/*
@@ -909,6 +910,25 @@ again: }btrfs_release_path (path); +/* look for a conflicting sequence number */ + di =btrfs_lookup_dir_index_item (trans, root, path,btrfs_ino (dir), +btrfs_inode_ref_index (eb, ref), + name, namelen,0 ); +if (di && !IS_ERR (di)) { + ret =drop_one_dir_item (trans, root, path, dir, di); +BUG_ON (ret); + } +btrfs_release_path (path); + +/* look for a conflicing name */ + di =btrfs_lookup_dir_item (trans, root, path,btrfs_ino (dir), + name, namelen,0 ); +if (di && !IS_ERR (di)) { + ret =drop_one_dir_item (trans, root, path, dir, di); +BUG_ON (ret); + } +btrfs_release_path (path); + insert:/* insert our name */ ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
fs/btrfs/volumes.c +17 -0
@@ -500,6 +500,9 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) fs_devices->rw_devices--; } +if (device->can_discard) + fs_devices->num_can_discard--; + new_device =kmalloc (sizeof (*new_device),GFP_NOFS );BUG_ON (!new_device);memcpy (new_device, device,sizeof (*new_device));
@@ -508,6 +511,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) new_device->bdev =NULL ; new_device->writeable =0 ; new_device->in_fs_metadata =0 ; + new_device->can_discard =0 ;list_replace_rcu (&device->dev_list, &new_device->dev_list);call_rcu (&device->rcu, free_device);
@@ -547,6 +551,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)static int __btrfs_open_devices (struct btrfs_fs_devices *fs_devices,fmode_t flags,void *holder) { +struct request_queue *q;struct block_device *bdev;struct list_head *head = &fs_devices->devices;struct btrfs_device *device;
@@ -603,6 +608,12 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, seeding =0 ; } + q =bdev_get_queue (bdev); +if (blk_queue_discard (q)) { + device->can_discard =1 ; + fs_devices->num_can_discard++; + } + device->bdev = bdev; device->in_fs_metadata =0 ; device->mode = flags;
@@ -1542,6 +1553,7 @@ error:int btrfs_init_new_device (struct btrfs_root *root,char *device_path) { +struct request_queue *q;struct btrfs_trans_handle *trans;struct btrfs_device *device;struct block_device *bdev;
@@ -1611,6 +1623,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)lock_chunks (root); + q =bdev_get_queue (bdev); +if (blk_queue_discard (q)) + device->can_discard =1 ; device->writeable =1 ; device->work.func = pending_bios_fn;generate_random_uuid (device->uuid);
@@ -1646,6 +1661,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) root->fs_info->fs_devices->num_devices++; root->fs_info->fs_devices->open_devices++; root->fs_info->fs_devices->rw_devices++; +if (device->can_discard) + root->fs_info->fs_devices->num_can_discard++; root->fs_info->fs_devices->total_rw_bytes += device->total_bytes;if (!blk_queue_nonrot (bdev_get_queue (bdev)))
fs/btrfs/volumes.h +2 -0
@@ -48,6 +48,7 @@ struct btrfs_device {int writeable;int in_fs_metadata;int missing; +int can_discard;spinlock_t io_lock;
@@ -104,6 +105,7 @@ struct btrfs_fs_devices {u64 rw_devices;u64 missing_devices;u64 total_rw_bytes; +u64 num_can_discard;struct block_device *latest_bdev;/* all of the devices in the FS, protected by a mutex
fs/cifs/connect.c +2 -1
@@ -2838,7 +2838,8 @@ cleanup_volume_info_contents(struct smb_vol *volume_info)kfree (volume_info->username);kzfree (volume_info->password);kfree (volume_info->UNC); -kfree (volume_info->UNCip); +if (volume_info->UNCip != volume_info->UNC +2 ) +kfree (volume_info->UNCip);kfree (volume_info->domainname);kfree (volume_info->iocharset);kfree (volume_info->prepath);
fs/cifs/dir.c +2 -2
@@ -110,8 +110,8 @@ cifs_bp_rename_retry: }rcu_read_unlock ();if (namelen != dfsplen ||read_seqretry (&rename_lock, seq)) { -cERROR (1 ,"did not end path lookup where expected namelen is %d" , - namelen); +cFYI (1 ,"did not end path lookup where expected. namelen=%d " +"dfsplen=%d" , namelen, dfsplen);/* presumably this is only possible if racing with a rename of one of the parent directories (we can not lock the dentries above us to prevent this, but retrying should be harmless) */
fs/ext4/ext4_jbd2.h +2 -2
@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode)static inline int ext4_should_writeback_data (struct inode *inode) { -if (!S_ISREG (inode->i_mode)) -return 0 ;if (EXT4_JOURNAL (inode) ==NULL )return 1 ; +if (!S_ISREG (inode->i_mode)) +return 0 ;if (ext4_test_inode_flag (inode,EXT4_INODE_JOURNAL_DATA ))return 0 ;if (test_opt (inode->i_sb,DATA_FLAGS ) ==EXT4_MOUNT_WRITEBACK_DATA )
fs/ext4/inode.c +24 -2
@@ -189,6 +189,12 @@ void ext4_evict_inode(struct inode *inode)int err;trace_ext4_evict_inode (inode); + +mutex_lock (&inode->i_mutex); +ext4_flush_completed_IO (inode); +mutex_unlock (&inode->i_mutex); +ext4_ioend_wait (inode); +if (inode->i_nlink) {truncate_inode_pages (&inode->i_data,0 ); goto no_delete;
@@ -1849,6 +1855,8 @@ static int ext4_journalled_write_end(struct file *file, from = pos & (PAGE_CACHE_SIZE -1 ); to = from + len; +BUG_ON (!ext4_handle_valid (handle)); +if (copied < len) {if (!PageUptodate (page)) copied =0 ;
@@ -2148,7 +2156,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,else if (test_opt (inode->i_sb,MBLK_IO_SUBMIT )) err =ext4_bio_write_page (&io_submit, page, len, mpd->wbc); -else +else if (buffer_uninit (page_bufs)) { +ext4_set_bh_endio (page_bufs, inode); + err =block_write_full_page_endio (page, + noalloc_get_block_write, + mpd->wbc, ext4_end_io_buffer_write); + }else err =block_write_full_page (page, noalloc_get_block_write, mpd->wbc);
@@ -2564,6 +2577,8 @@ static int __ext4_journalled_writepage(struct page *page, goto out; } +BUG_ON (!ext4_handle_valid (handle)); + ret =walk_page_buffers (handle, page_bufs,0 , len,NULL , do_journal_get_write_access);
@@ -3635,8 +3650,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) goto out; } - io_end->flag =EXT4_IO_END_UNWRITTEN ; +/* +* It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now, +* but being more careful is always safe for the future change. +*/ inode = io_end->inode; +if (!(io_end->flag &EXT4_IO_END_UNWRITTEN )) { + io_end->flag |=EXT4_IO_END_UNWRITTEN ; +atomic_inc (&EXT4_I (inode)->i_aiodio_unwritten); + }/* Add the io_end to per-inode completed io list*/ spin_lock_irqsave (&EXT4_I (inode)->i_completed_io_lock, flags);
fs/ext4/page-io.c +4 -2
@@ -338,8 +338,10 @@ submit_and_retry:if ((io_end->num_io_pages >=MAX_IO_PAGES ) && (io_end->pages[io_end->num_io_pages-1 ] != io_page)) goto submit_and_retry; -if (buffer_uninit (bh)) - io->io_end->flag |=EXT4_IO_END_UNWRITTEN ; +if (buffer_uninit (bh) && !(io_end->flag &EXT4_IO_END_UNWRITTEN )) { + io_end->flag |=EXT4_IO_END_UNWRITTEN ; +atomic_inc (&EXT4_I (inode)->i_aiodio_unwritten); + } io->io_end->size += bh->b_size; io->io_next_block++; ret =bio_add_page (io->io_bio, bh->b_page, bh->b_size,bh_offset (bh));
fs/ext4/super.c +0 -1
@@ -892,7 +892,6 @@ static void ext4_i_callback(struct rcu_head *head)static void ext4_destroy_inode (struct inode *inode) { -ext4_ioend_wait (inode);if (!list_empty (&(EXT4_I (inode)->i_orphan))) { ext4_msg(inode->i_sb, KERN_ERR, "Inode %lu (%p): orphan list check failed!",
fs/fuse/dev.c +4 -0
@@ -1358,6 +1358,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,if (outarg.namelen >FUSE_NAME_MAX ) goto err; + err = -EINVAL ; +if (size !=sizeof (outarg) + outarg.namelen +1 ) + goto err; + name.name = buf; name.len = outarg.namelen; err =fuse_copy_one (cs, buf, outarg.namelen +1 );
fs/nfs/callback.h +1 -1
@@ -38,6 +38,7 @@ enum nfs4_callback_opnum {struct cb_process_state {__be32 drc_status;struct nfs_client *clp; +int slotid; };struct cb_compound_hdr_arg {
@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall( void *dummy, struct cb_process_state *cps);extern void nfs4_check_drain_bc_complete (struct nfs4_session *ses); -extern void nfs4_cb_take_slot (struct nfs_client *clp);struct cb_devicenotifyitem {uint32_t cbd_notify_type;
fs/nfs/callback_proc.c +19 -6
@@ -333,7 +333,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)/* Normal */ if (likely (args->csa_sequenceid == slot->seq_nr +1 )) { slot->seq_nr++; -return htonl (NFS4_OK ); + goto out_ok; }/* Replay */
@@ -352,11 +352,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)/* Wraparound */ if (args->csa_sequenceid ==1 && (slot->seq_nr +1 ) ==0 ) { slot->seq_nr =1 ; -return htonl (NFS4_OK ); + goto out_ok; }/* Misordered request */ return htonl (NFS4ERR_SEQ_MISORDERED ); +out_ok: + tbl->highest_used_slotid = args->csa_slotid; +return htonl (NFS4_OK ); }/*
@@ -418,26 +421,37 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,struct cb_sequenceres *res, struct cb_process_state *cps) { + struct nfs4_slot_table *tbl;struct nfs_client *clp;int i;__be32 status =htonl (NFS4ERR_BADSESSION ); - cps->clp =NULL ; - clp =nfs4_find_client_sessionid (args->csa_addr, &args->csa_sessionid);if (clp ==NULL ) goto out; + tbl = &clp->cl_session->bc_slot_table; + +spin_lock (&tbl->slot_tbl_lock);/* state manager is resetting the session */ if (test_bit (NFS4_SESSION_DRAINING , &clp->cl_session->session_state)) { - status =NFS4ERR_DELAY ; +spin_unlock (&tbl->slot_tbl_lock); + status =htonl (NFS4ERR_DELAY ); +/* Return NFS4ERR_BADSESSION if we're draining the session +* in order to reset it. +*/ +if (test_bit (NFS4CLNT_SESSION_RESET , &clp->cl_state)) + status =htonl (NFS4ERR_BADSESSION ); goto out; } status =validate_seqid (&clp->cl_session->bc_slot_table, args); +spin_unlock (&tbl->slot_tbl_lock);if (status) goto out; + cps->slotid = args->csa_slotid; +/* * Check for pending referring calls. If a match is found, a * related callback was received before the response to the original
@@ -454,7 +468,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, res->csr_slotid = args->csa_slotid; res->csr_highestslotid =NFS41_BC_MAX_CALLBACKS -1 ; res->csr_target_highestslotid =NFS41_BC_MAX_CALLBACKS -1 ; -nfs4_cb_take_slot (clp); out: cps->clp = clp;/* put in nfs4_callback_compound */
fs/nfs/callback_xdr.c +7 -17
@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)* Let the state manager know callback processing done. * A single slot, so highest used slotid is either 0 or -1 */ - tbl->highest_used_slotid--; + tbl->highest_used_slotid =-1 ;nfs4_check_drain_bc_complete (session); spin_unlock(&tbl->slot_tbl_lock); } -static void nfs4_cb_free_slot (struct nfs_client *clp) +static void nfs4_cb_free_slot (struct cb_process_state *cps) { -if (clp && clp->cl_session) -nfs4_callback_free_slot (clp->cl_session); -} - -/* A single slot, so highest used slotid is either 0 or -1 */ -void nfs4_cb_take_slot (struct nfs_client *clp) -{ -struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table; - -spin_lock (&tbl->slot_tbl_lock); - tbl->highest_used_slotid++; -BUG_ON (tbl->highest_used_slotid !=0 ); -spin_unlock (&tbl->slot_tbl_lock); +if (cps->slotid !=-1 ) +nfs4_callback_free_slot (cps->clp->cl_session); }#else /* CONFIG_NFS_V4_1 */
@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) return htonl(NFS4ERR_MINOR_VERS_MISMATCH); } -static void nfs4_cb_free_slot (struct nfs_client *clp) +static void nfs4_cb_free_slot (struct cb_process_state *cps) { }#endif /* CONFIG_NFS_V4_1 */
@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *rstruct cb_process_state cps = { .drc_status =0 , .clp =NULL , + .slotid =-1 , };unsigned int nops =0 ;
@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r *hdr_res.status = status; *hdr_res.nops =htonl (nops); -nfs4_cb_free_slot (cps.clp); +nfs4_cb_free_slot (&cps);nfs_put_client (cps.clp);dprintk ("%s: done, status = %u\n" , __func__,ntohl (status));return rpc_success;
fs/nfs/objlayout/objio_osd.c +12 -16
@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write)for (i =0 ; i < ios->numdevs; i++) {struct osd_sense_info osi;struct osd_request *or = ios->per_dev[i].or; -unsigned dev;int ret;if (!or)
@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write)continue ;/* we recovered */ } - dev = ios->per_dev[i].dev; - objlayout_io_set_result(&ios->ol_state, dev, - &ios->layout->comps[dev].oc_object_id, + objlayout_io_set_result(&ios->ol_state, i, + &ios->layout->comps[i].oc_object_id, osd_pri_2_pnfs_err(osi.osd_err_pri), ios->per_dev[i].offset, ios->per_dev[i].length,
@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct objio_state *ios, u64 file_offset, }static int _add_stripe_unit (struct objio_state *ios,unsigned *cur_pg, -unsigned pgbase,struct _objio_per_comp *per_dev,int cur_len, +unsigned pgbase,struct _objio_per_comp *per_dev,int len,gfp_t gfp_flags) {unsigned pg = *cur_pg; +int cur_len = len;struct request_queue *q =osd_request_queue (_io_od (ios, per_dev->dev)); - per_dev->length += cur_len; -if (per_dev->bio ==NULL ) { -unsigned stripes = ios->layout->num_comps / - ios->layout->mirrors_p1; -unsigned pages_in_stripe = stripes * +unsigned pages_in_stripe = ios->layout->group_width * (ios->layout->stripe_unit /PAGE_SIZE );unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / - stripes; + ios->layout->group_width;if (BIO_MAX_PAGES_KMALLOC < bio_size) bio_size =BIO_MAX_PAGES_KMALLOC ;
@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, }BUG_ON (cur_len); + per_dev->length += len; *cur_pg = pg;return 0 ; }
@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,int ret =0 ;while (length) { -struct _objio_per_comp *per_dev = &ios->per_dev[dev]; +struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev];unsigned cur_len, page_off =0 ;if (!per_dev->length) {
@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length, cur_len = stripe_unit; } -if (max_comp < dev) - max_comp = dev; +if (max_comp < dev - first_dev) + max_comp = dev - first_dev; }else { cur_len = stripe_unit; }
@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_state *ios, unsigned cur_comp)struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];unsigned dev = per_dev->dev;struct pnfs_osd_object_cred *cred = - &ios->layout->comps[dev]; + &ios->layout->comps[cur_comp];struct osd_obj_id obj = { .partition = cred->oc_object_id.oid_partition_id, .id = cred->oc_object_id.oid_object_id,
@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)for (; cur_comp < last_comp; ++cur_comp, ++dev) {struct osd_request *or =NULL ;struct pnfs_osd_object_cred *cred = - &ios->layout->comps[dev]; + &ios->layout->comps[cur_comp];struct osd_obj_id obj = { .partition = cred->oc_object_id.oid_partition_id, .id = cred->oc_object_id.oid_object_id,
fs/nfs/objlayout/pnfs_osd_xdr_cli.c +3 -0
@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout, p =_osd_xdr_decode_data_map (p, &layout->olo_map); layout->olo_comps_index =be32_to_cpup (p++); layout->olo_num_comps =be32_to_cpup (p++); +dprintk ("%s: olo_comps_index=%d olo_num_comps=%d\n" , __func__, + layout->olo_comps_index, layout->olo_num_comps); + iter->total_comps = layout->olo_num_comps;return 0 ; }
include/linux/personality.h +1 -0
@@ -22,6 +22,7 @@ extern int __set_personality(unsigned int);* These occupy the top three bytes. */ enum { +UNAME26 =0x0020000 ,ADDR_NO_RANDOMIZE =0x0040000 ,/* disable randomization of VA space */ FDPIC_FUNCPTRS =0x0080000 ,/* userspace function ptrs point to descriptors * (signal handling)
include/linux/stop_machine.h +2 -0
@@ -27,6 +27,8 @@ struct cpu_stop_work {struct cpu_stop_done *done; }; +extern struct mutex stop_cpus_mutex; +int stop_one_cpu (unsigned int cpu,cpu_stop_fn_t fn,void *arg);void stop_one_cpu_nowait (unsigned int cpu,cpu_stop_fn_t fn,void *arg,struct cpu_stop_work *work_buf);
kernel/irq/generic-chip.c +2 -2
@@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, gc->mask_cache =irq_reg_readl (gc->reg_base + ct->regs.mask);for (i = gc->irq_base; msk; msk >>=1 , i++) { -if (!msk &0x01 ) +if (!(msk &0x01 ))continue ;if (flags &IRQ_GC_INIT_NESTED_LOCK )
@@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,raw_spin_unlock (&gc_lock);for (; msk; msk >>=1 , i++) { -if (!msk &0x01 ) +if (!(msk &0x01 ))continue ;/* Remove handler first. That will mask the irq line */
kernel/stop_machine.c +1 -1
@@ -132,8 +132,8 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,cpu_stop_queue_work (&per_cpu (cpu_stopper, cpu), work_buf); } +DEFINE_MUTEX (stop_cpus_mutex);/* static data for stop_cpus */ -static DEFINE_MUTEX (stop_cpus_mutex); static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);int __stop_cpus (const struct cpumask *cpumask,cpu_stop_fn_t fn,void *arg)
kernel/sys.c +38 -0
@@ -38,6 +38,8 @@#include <linux/fs_struct.h> #include <linux/gfp.h> #include <linux/syscore_ops.h> +#include <linux/version.h> +#include <linux/ctype.h> #include <linux/compat.h> #include <linux/syscalls.h>
@@ -45,6 +47,8 @@#include <linux/user_namespace.h> #include <linux/kmsg_dump.h> +/* Move somewhere else to avoid recompiling? */ +#include <generated/utsrelease.h> #include <asm/uaccess.h> #include <asm/io.h>
@@ -1124,6 +1128,34 @@ DECLARE_RWSEM(uts_sem);#define override_architecture (name) 0#endif +/* +* Work around broken programs that cannot handle "Linux 3.0". +* Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 +*/ +static int override_release (char __user *release,int len) +{ +int ret =0 ; +char buf[len]; + +if (current->personality &UNAME26 ) { +char *rest =UTS_RELEASE ; +int ndots =0 ; +unsigned v; + +while (*rest) { +if (*rest =='.' && ++ndots >=3 ) +break ; +if (!isdigit (*rest) && *rest !='.' ) +break ; + rest++; + } + v = ((LINUX_VERSION_CODE >>8 ) &0xff ) +40 ; +snprintf (buf, len,"2.6.%u%s" , v, rest); + ret =copy_to_user (release, buf, len); + } +return ret; +} + SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) {int errno =0 ;
@@ -1133,6 +1165,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) errno = -EFAULT ;up_read (&uts_sem); +if (!errno &&override_release (name->release,sizeof (name->release))) + errno = -EFAULT ;if (!errno &&override_architecture (name)) errno = -EFAULT ;return errno;
@@ -1154,6 +1188,8 @@ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) error = -EFAULT ;up_read (&uts_sem); +if (!error &&override_release (name->release,sizeof (name->release))) + error = -EFAULT ;if (!error &&override_architecture (name)) error = -EFAULT ;return error;
@@ -1188,6 +1224,8 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)if (!error &&override_architecture (name)) error = -EFAULT ; +if (!error &&override_release (name->release,sizeof (name->release))) + error = -EFAULT ; return error ? -EFAULT : 0; }#endif
sound/pci/ac97/ac97_patch.c +1 -0
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = {0x103c0944 ,/* HP nc6220 */ 0x103c0934 ,/* HP nc8220 */ 0x103c006d ,/* HP nx9105 */ +0x103c300d ,/* HP Compaq dc5100 SFF(PT003AW) */ 0x17340088 ,/* FSC Scenic-W */ 0 /* end */ };
sound/usb/caiaq/audio.c +27 -4
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev)for (i =0 ; i <N_URBS ; i++) {usb_kill_urb (dev->data_urbs_in[i]); -usb_kill_urb (dev->data_urbs_out[i]); + +if (test_bit (i, &dev->outurb_active_mask)) +usb_kill_urb (dev->data_urbs_out[i]); } + + dev->outurb_active_mask =0 ; }static int snd_usb_caiaq_substream_open (struct snd_pcm_substream *substream)
@@ -612,8 +616,8 @@ static void read_completed(struct urb *urb) {struct snd_usb_caiaq_cb_info *info = urb->context;struct snd_usb_caiaqdev *dev; -struct urb *out; -int frame, len, send_it =0 , outframe =0 ; +struct urb *out =NULL ; +int i, frame, len, send_it =0 , outframe =0 ;size_t offset =0 ;if (urb->status || !info)
@@ -624,7 +628,17 @@ static void read_completed(struct urb *urb)if (!dev->streaming)return ; - out = dev->data_urbs_out[info->index]; +/* find an unused output urb that is unused */ +for (i =0 ; i <N_URBS ; i++) +if (test_and_set_bit (i, &dev->outurb_active_mask) ==0 ) { + out = dev->data_urbs_out[i]; +break ; + } + +if (!out) { +log ("Unable to find an output urb to use\n" ); + goto requeue; + }/* read the recently received packet and send back one which has * the same layout */
@@ -655,8 +669,12 @@ static void read_completed(struct urb *urb) out->number_of_packets = outframe; out->transfer_flags =URB_ISO_ASAP ;usb_submit_urb (out,GFP_ATOMIC ); + }else { +struct snd_usb_caiaq_cb_info *oinfo = out->context; +clear_bit (oinfo->index, &dev->outurb_active_mask); } +requeue:/* re-submit inbound urb */ for (frame =0 ; frame <FRAMES_PER_URB ; frame++) { urb->iso_frame_desc[frame].offset =BYTES_PER_FRAME * frame;
@@ -678,6 +696,8 @@ static void write_completed(struct urb *urb) dev->output_running =1 ;wake_up (&dev->prepare_wait_queue); } + +clear_bit (info->index, &dev->outurb_active_mask); }static struct urb **alloc_urbs (struct snd_usb_caiaqdev *dev,int dir,int *ret)
@@ -829,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)if (!dev->data_cb_info)return -ENOMEM ; + dev->outurb_active_mask =0 ; +BUILD_BUG_ON (N_URBS > (sizeof (dev->outurb_active_mask) *8 )); +for (i =0 ; i <N_URBS ; i++) { dev->data_cb_info[i].dev = dev; dev->data_cb_info[i].index = i;
sound/usb/caiaq/device.h +1 -0
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev {int input_panic, output_panic, warned;char *audio_in_buf, *audio_out_buf;unsigned int samplerates, bpp; +unsigned long outurb_active_mask;struct snd_pcm_substream *sub_playback[MAX_STREAMS ];struct snd_pcm_substream *sub_capture[MAX_STREAMS ];
sound/usb/mixer.c +2 -1
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,if (p && p->dB) { cval->dBmin = p->dB->min; cval->dBmax = p->dB->max; + cval->initialized =1 ; } }
@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, " Switch" : " Volume"); if (control == UAC_FU_VOLUME) {check_mapped_dB (map, cval); -if (cval->dBmin < cval->dBmax) { +if (cval->dBmin < cval->dBmax || !cval->initialized) { kctl->tlv.c = mixer_vol_tlv; kctl->vd[0 ].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ |