Linux 3.18.68
Greg KH
maintainerI'm announcing the release of the 3.18.68 kernel.
All users of the 3.18 kernel series must upgrade.
The updated 3.18.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.18.y
and can be browsed at the normal kernel.org git web browser:
http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Makefile | 2 - drivers/acpi/apei/ghes.c | 1 drivers/gpu/drm/drm_gem.c | 6 ++-- drivers/iio/imu/adis16480.c | 2 - drivers/input/mouse/trackpoint.c | 3 +- drivers/input/mouse/trackpoint.h | 3 +- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 fs/cifs/dir.c | 18 ++++++++---- fs/cifs/smb2pdu.c | 4 +- fs/nfsd/nfs4xdr.c | 6 +--- include/net/sch_generic.h | 5 ++- kernel/events/core.c | 39 +++++++++++++--------------- kernel/trace/trace_events_filter.c | 4 ++ net/bluetooth/bnep/core.c | 11 +++---- net/bluetooth/cmtp/core.c | 17 +++++++----- net/bluetooth/hidp/core.c | 33 +++++++++++++++-------- net/dccp/proto.c | 19 +++++++++---- net/ipv4/tcp_input.c | 3 -- net/irda/af_irda.c | 2 - net/sched/act_ipt.c | 2 + net/sctp/ipv6.c | 2 + sound/core/control.c | 2 - sound/pci/hda/patch_conexant.c | 1 23 files changed, 112 insertions(+), 74 deletions(-)
Aaron Ma (1):
Input: trackpoint - add new trackpoint firmware ID
Alexander Potapenko (1):
sctp: fully initialize the IPv6 address in sctp_v6_to_addr()
Charles Milette (1):
staging: rtl8188eu: add RNX-N150NUB support
Chris Wilson (1):
drm: Release driver tracking before making the object available again
Chuck Lever (1):
nfsd: Limit end of page list when decoding NFSv4 WRITE
Colin Ian King (1):
irda: do not leak initialized list.dev to userspace
Dragos Bogdan (1):
iio: imu: adis16480: Fix acceleration scale factor for adis16480
Eric Dumazet (2):
dccp: purge write queue in dccp_destroy_sock()
dccp: defer ccid_hc_tx_delete() at dismantle time
Greg Kroah-Hartman (1):
Linux 3.18.68
James Morse (1):
ACPI / APEI: Add missing synchronize_rcu() on NOTIFY_SCI removal
Jeffy Chen (3):
Bluetooth: hidp: fix possible might sleep error in hidp_session_thread
Bluetooth: cmtp: fix possible might sleep error in cmtp_session
Bluetooth: bnep: fix possible might sleep error in bnep_session
Konstantin Khlebnikov (1):
net_sched: fix order of queue length updates in qdisc_replace()
Mark Rutland (1):
perf/core: Fix group {cpu,task} validation
Neal Cardwell (1):
tcp: when rearming RTO, if RTO time is in past then fire RTO ASAP
Ronnie Sahlberg (1):
cifs: return ENAMETOOLONG for overlong names in cifs_open()/cifs_lookup()
Sachin Prabhu (1):
cifs: Fix df output for users with quota limits
Steven Rostedt (VMware) (1):
tracing: Fix freeing of filter in create_filter() when set_str is false
Takashi Iwai (2):
ALSA: core: Fix unexpected error at replacing user TLV
ALSA: hda - Add stereo mic quirk for Lenovo G50-70 (17aa:3978)
Xin Long (1):
net: sched: fix NULL pointer dereference when action calls some targets
Greg KH
maintainerMakefile +1 -1
@@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 18 -SUBLEVEL = 67 +SUBLEVEL = 68 EXTRAVERSION = NAME = Diseased Newt
drivers/acpi/apei/ghes.c +1 -0
@@ -1078,6 +1078,7 @@ static int ghes_remove(struct platform_device *ghes_dev)if (list_empty (&ghes_sci))unregister_acpi_hed_notifier (&ghes_notifier_sci);mutex_unlock (&ghes_list_mutex); +synchronize_rcu ();break ;case ACPI_HEST_NOTIFY_NMI :ghes_nmi_remove (ghes);
drivers/gpu/drm/drm_gem.c +3 -3
@@ -711,13 +711,13 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)struct drm_gem_object *obj = ptr;struct drm_device *dev = obj->dev; +if (dev->driver->gem_close_object) + dev->driver->gem_close_object (obj, file_priv); +if (drm_core_check_feature (dev,DRIVER_PRIME ))drm_gem_remove_prime_handles (obj, file_priv);drm_vma_node_revoke (&obj->vma_node, file_priv->filp); -if (dev->driver->gem_close_object) - dev->driver->gem_close_object (obj, file_priv); -drm_gem_object_handle_unreference_unlocked (obj);return 0 ;
drivers/iio/imu/adis16480.c +1 -1
@@ -696,7 +696,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .gyro_max_val = IIO_RAD_TO_DEGREE(22500), .gyro_max_scale = 450, .accel_max_val = IIO_M_S_2_TO_G(12500), - .accel_max_scale = 5, + .accel_max_scale = 10, }, [ADIS16485] = { .channels = adis16485_channels,
drivers/input/mouse/trackpoint.c +2 -1
@@ -263,7 +263,8 @@ static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firif (ps2_command (&psmouse->ps2dev, param,MAKE_PS2_CMD (0 ,2 ,TP_READ_ID )))return -1 ; -if (param[0 ] !=TP_MAGIC_IDENT ) +/* add new TP ID. */ +if (!(param[0 ] &TP_MAGIC_IDENT ))return -1 ;if (firmware_id)
drivers/input/mouse/trackpoint.h +2 -1
@@ -21,8 +21,9 @@#define TP_COMMAND 0xE2/* Commands start with this */ #define TP_READ_ID 0xE1/* Sent for device identification */ -#define TP_MAGIC_IDENT 0x01/* Sent after a TP_READ_ID followed */ +#define TP_MAGIC_IDENT 0x03/* Sent after a TP_READ_ID followed */ /* by the firmware ID */ +/* Firmware ID includes 0x1, 0x2, 0x3 */ /*
drivers/staging/rtl8188eu/os_dep/usb_intf.c +1 -0
@@ -50,6 +50,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ {} /* Terminating entry */ };
fs/cifs/dir.c +12 -6
@@ -183,15 +183,20 @@ cifs_bp_rename_retry: }/* +* Don't allow path components longer than the server max. * Don't allow the separator character in a path component. * The VFS will not allow "/", but "\" is allowed by posix. */ static int -check_name (struct dentry *direntry) +check_name (struct dentry *direntry,struct cifs_tcon *tcon) {struct cifs_sb_info *cifs_sb =CIFS_SB (direntry->d_sb);int i; +if (unlikely (direntry->d_name.len > + tcon->fsAttrInfo.MaxPathNameComponentLength)) +return -ENAMETOOLONG ; +if (!(cifs_sb->mnt_cifs_flags &CIFS_MOUNT_POSIX_PATHS )) {for (i =0 ; i < direntry->d_name.len; i++) {if (direntry->d_name.name[i] =='\\' ) {
@@ -489,10 +494,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,return finish_no_open (file, res); } - rc =check_name (direntry); -if (rc) -return rc; - xid =get_xid (); cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
@@ -505,6 +506,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, } tcon =tlink_tcon (tlink); + + rc =check_name (direntry, tcon); +if (rc) + goto out_free_xid; + server = tcon->ses->server;if (server->ops->new_lease_key)
@@ -766,7 +772,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } pTcon =tlink_tcon (tlink); - rc =check_name (direntry); + rc =check_name (direntry, pTcon);if (rc) goto lookup_out;
fs/cifs/smb2pdu.c +2 -2
@@ -2551,8 +2551,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf, kst->f_bsize =le32_to_cpu (pfs_inf->BytesPerSector) *le32_to_cpu (pfs_inf->SectorsPerAllocationUnit); kst->f_blocks =le64_to_cpu (pfs_inf->TotalAllocationUnits); - kst->f_bfree =le64_to_cpu (pfs_inf->ActualAvailableAllocationUnits); - kst->f_bavail =le64_to_cpu (pfs_inf->CallerAvailableAllocationUnits); + kst->f_bfree = kst->f_bavail = +le64_to_cpu (pfs_inf->CallerAvailableAllocationUnits);return ; }
fs/nfsd/nfs4xdr.c +2 -4
@@ -127,7 +127,7 @@ static void next_decode_page(struct nfsd4_compoundargs *argp) argp->p =page_address (argp->pagelist[0 ]); argp->pagelist++;if (argp->pagelen <PAGE_SIZE ) { - argp->end = argp->p + (argp->pagelen>>2 ); + argp->end = argp->p +XDR_QUADLEN (argp->pagelen); argp->pagelen =0 ; }else { argp->end = argp->p + (PAGE_SIZE >>2 );
@@ -1235,9 +1235,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) argp->pagelen -= pages *PAGE_SIZE ; len -= pages *PAGE_SIZE ; - argp->p = (__be32 *)page_address (argp->pagelist[0 ]); - argp->pagelist++; - argp->end = argp->p +XDR_QUADLEN (PAGE_SIZE ); +next_decode_page (argp); } argp->p +=XDR_QUADLEN (len);
include/net/sch_generic.h +4 -1
@@ -699,8 +699,11 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, old = *pold; *pold = new;if (old !=NULL ) { -qdisc_tree_reduce_backlog (old, old->q.qlen, old->qstats.backlog); +unsigned int qlen = old->q.qlen; +unsigned int backlog = old->qstats.backlog; +qdisc_reset (old); +qdisc_tree_reduce_backlog (old, qlen, backlog); }sch_tree_unlock (sch);
kernel/events/core.c +19 -20
@@ -7583,28 +7583,27 @@ SYSCALL_DEFINE5(perf_event_open,if (group_leader->group_leader != group_leader) goto err_context;/* -* Do not allow to attach to a group in a different -* task or CPU context: +* Make sure we're both events for the same CPU; +* grouping events for different CPUs is broken; since +* you can never concurrently schedule them anyhow. */ -if (move_group) { -/* -* Make sure we're both on the same task, or both -* per-cpu events. -*/ -if (group_leader->ctx->task != ctx->task) - goto err_context; +if (group_leader->cpu != event->cpu) + goto err_context; -/* -* Make sure we're both events for the same CPU; -* grouping events for different CPUs is broken; since -* you can never concurrently schedule them anyhow. -*/ -if (group_leader->cpu != event->cpu) - goto err_context; - }else { -if (group_leader->ctx != ctx) - goto err_context; - } +/* +* Make sure we're both on the same task, or both +* per-CPU events. +*/ +if (group_leader->ctx->task != ctx->task) + goto err_context; + +/* +* Do not allow to attach to a group in a different task +* or CPU context. If we're moving SW events, we'll fix +* this up later, so allow that. +*/ +if (!move_group && group_leader->ctx != ctx) + goto err_context;/* * Only a group leader can be exclusive or pinned
kernel/trace/trace_events_filter.c +4 -0
@@ -1909,6 +1909,10 @@ static int create_filter(struct ftrace_event_call *call,if (err && set_str)append_filter_err (ps, filter); } +if (err && !set_str) { +free_event_filter (filter); + filter =NULL ; + }create_filter_finish (ps); *filterp = filter;
net/bluetooth/bnep/core.c +5 -6
@@ -451,16 +451,16 @@ static int bnep_session(void *arg)struct net_device *dev = s->dev;struct sock *sk = s->sock->sk;struct sk_buff *skb; -wait_queue_t wait; +DEFINE_WAIT_FUNC (wait, woken_wake_function);BT_DBG ("" );set_user_nice (current,-15 ); -init_waitqueue_entry (&wait, current);add_wait_queue (sk_sleep (sk), &wait);while (1 ) { -set_current_state (TASK_INTERRUPTIBLE ); +/* Ensure session->terminate is updated */ +smp_mb__before_atomic ();if (atomic_read (&s->terminate))break ;
@@ -482,9 +482,8 @@ static int bnep_session(void *arg)break ;netif_wake_queue (dev); -schedule (); +wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); } -__set_current_state (TASK_RUNNING );remove_wait_queue (sk_sleep (sk), &wait);/* Cleanup session */
@@ -621,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) s =__bnep_get_session (req->dst);if (s) {atomic_inc (&s->terminate); -wake_up_process (s->task); +wake_up_interruptible (sk_sleep (s->sock->sk)); }else err = -ENOENT ;
net/bluetooth/cmtp/core.c +10 -7
@@ -280,16 +280,16 @@ static int cmtp_session(void *arg)struct cmtp_session *session = arg;struct sock *sk = session->sock->sk;struct sk_buff *skb; -wait_queue_t wait; +DEFINE_WAIT_FUNC (wait, woken_wake_function);BT_DBG ("session %p" , session);set_user_nice (current,-15 ); -init_waitqueue_entry (&wait, current);add_wait_queue (sk_sleep (sk), &wait);while (1 ) { -set_current_state (TASK_INTERRUPTIBLE ); +/* Ensure session->terminate is updated */ +smp_mb__before_atomic ();if (atomic_read (&session->terminate))break ;
@@ -306,9 +306,8 @@ static int cmtp_session(void *arg)cmtp_process_transmit (session); -schedule (); +wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); } -__set_current_state (TASK_RUNNING );remove_wait_queue (sk_sleep (sk), &wait);down_write (&cmtp_session_sem);
@@ -389,7 +388,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) err =cmtp_attach_device (session);if (err <0 ) {atomic_inc (&session->terminate); -wake_up_process (session->task); +wake_up_interruptible (sk_sleep (session->sock->sk));up_write (&cmtp_session_sem);return err; }
@@ -423,7 +422,11 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)/* Stop session thread */ atomic_inc (&session->terminate); -wake_up_process (session->task); + +/* Ensure session->terminate is updated */ +smp_mb__after_atomic (); + +wake_up_interruptible (sk_sleep (session->sock->sk)); }else err = -ENOENT ;
net/bluetooth/hidp/core.c +22 -11
@@ -36,6 +36,7 @@#define VERSION "1.2"static DECLARE_RWSEM (hidp_session_sem); +static DECLARE_WAIT_QUEUE_HEAD (hidp_session_wq);static LIST_HEAD (hidp_session_list);static unsigned char hidp_keycode[256 ] = {
@@ -1056,12 +1057,12 @@ static int hidp_session_start_sync(struct hidp_session *session)* Wake up session thread and notify it to stop. This is asynchronous and * returns immediately. Call this whenever a runtime error occurs and you want * the session to stop. -* Note: wake_up_process() performs any necessary memory-barriers for us. +* Note: wake_up_interruptible() performs any necessary memory-barriers for us. */ static void hidp_session_terminate (struct hidp_session *session) {atomic_inc (&session->terminate); -wake_up_process (session->task); +wake_up_interruptible (&hidp_session_wq); }/*
@@ -1168,7 +1169,9 @@ static void hidp_session_run(struct hidp_session *session)struct sock *ctrl_sk = session->ctrl_sock->sk;struct sock *intr_sk = session->intr_sock->sk;struct sk_buff *skb; +DEFINE_WAIT_FUNC (wait, woken_wake_function); +add_wait_queue (&hidp_session_wq, &wait);for (;;) {/* * This thread can be woken up two ways:
@@ -1176,12 +1179,10 @@ static void hidp_session_run(struct hidp_session *session)* session->terminate flag and wakes this thread up. * - Via modifying the socket state of ctrl/intr_sock. This * thread is woken up by ->sk_state_changed(). -* -* Note: set_current_state() performs any necessary -* memory-barriers for us. */ -set_current_state (TASK_INTERRUPTIBLE ); +/* Ensure session->terminate is updated */ +smp_mb__before_atomic ();if (atomic_read (&session->terminate))break ;
@@ -1215,11 +1216,22 @@ static void hidp_session_run(struct hidp_session *session)hidp_process_transmit (session, &session->ctrl_transmit, session->ctrl_sock); -schedule (); +wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); } +remove_wait_queue (&hidp_session_wq, &wait);atomic_inc (&session->terminate); -set_current_state (TASK_RUNNING ); + +/* Ensure session->terminate is updated */ +smp_mb__after_atomic (); +} + +static int hidp_session_wake_function (wait_queue_t *wait, +unsigned int mode, +int sync,void *key) +{ +wake_up_interruptible (&hidp_session_wq); +return false; }/*
@@ -1232,7 +1244,8 @@ static void hidp_session_run(struct hidp_session *session)static int hidp_session_thread (void *arg) {struct hidp_session *session = arg; -wait_queue_t ctrl_wait, intr_wait; +DEFINE_WAIT_FUNC (ctrl_wait, hidp_session_wake_function); +DEFINE_WAIT_FUNC (intr_wait, hidp_session_wake_function);BT_DBG ("session %p" , session);
@@ -1242,8 +1255,6 @@ static int hidp_session_thread(void *arg)set_user_nice (current,-15 );hidp_set_timer (session); -init_waitqueue_entry (&ctrl_wait, current); -init_waitqueue_entry (&intr_wait, current);add_wait_queue (sk_sleep (session->ctrl_sock->sk), &ctrl_wait);add_wait_queue (sk_sleep (session->intr_sock->sk), &intr_wait);/* This memory barrier is paired with wq_has_sleeper(). See
net/dccp/proto.c +13 -6
@@ -24,6 +24,7 @@#include <net/checksum.h> #include <net/inet_sock.h> +#include <net/inet_common.h> #include <net/sock.h> #include <net/xfrm.h>
@@ -170,6 +171,15 @@ const char *dccp_packet_name(const int type)EXPORT_SYMBOL_GPL (dccp_packet_name); +static void dccp_sk_destruct (struct sock *sk) +{ +struct dccp_sock *dp =dccp_sk (sk); + +ccid_hc_tx_delete (dp->dccps_hc_tx_ccid, sk); + dp->dccps_hc_tx_ccid =NULL ; +inet_sock_destruct (sk); +} +int dccp_init_sock (struct sock *sk,const __u8 ctl_sock_initialized) {struct dccp_sock *dp =dccp_sk (sk);
@@ -179,6 +189,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) icsk->icsk_syn_retries = sysctl_dccp_request_retries; sk->sk_state =DCCP_CLOSED ; sk->sk_write_space = dccp_write_space; + sk->sk_destruct = dccp_sk_destruct; icsk->icsk_sync_mss = dccp_sync_mss; dp->dccps_mss_cache =536 ; dp->dccps_rate_last = jiffies;
@@ -201,10 +212,7 @@ void dccp_destroy_sock(struct sock *sk) {struct dccp_sock *dp =dccp_sk (sk); -/* -* DCCP doesn't use sk_write_queue, just sk_send_head -* for retransmissions -*/ +__skb_queue_purge (&sk->sk_write_queue);if (sk->sk_send_head !=NULL ) {kfree_skb (sk->sk_send_head); sk->sk_send_head =NULL ;
@@ -222,8 +230,7 @@ void dccp_destroy_sock(struct sock *sk) dp->dccps_hc_rx_ackvec =NULL ; }ccid_hc_rx_delete (dp->dccps_hc_rx_ccid, sk); -ccid_hc_tx_delete (dp->dccps_hc_tx_ccid, sk); - dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid =NULL ; + dp->dccps_hc_rx_ccid =NULL ;/* clean up feature negotiation state */ dccp_feat_list_purge (&dp->dccps_featneg);
net/ipv4/tcp_input.c +1 -2
@@ -2985,8 +2985,7 @@ void tcp_rearm_rto(struct sock *sk)/* delta may not be positive if the socket is locked * when the retrans timer fires and is rescheduled. */ -if (delta >0 ) - rto = delta; + rto =max (delta,1 ); }inet_csk_reset_xmit_timer (sk,ICSK_TIME_RETRANS , rto,TCP_RTO_MAX );
net/irda/af_irda.c +1 -1
@@ -2251,7 +2251,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk); -struct irda_device_list list; +struct irda_device_list list = {0 };struct irda_device_info *discoveries;struct irda_ias_set * ias_opt;/* IAS get/query params */ struct ias_object * ias_obj;/* Object in IAS */
net/sched/act_ipt.c +2 -0
@@ -34,6 +34,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int {struct xt_tgchk_param par;struct xt_target *target; +struct ipt_entry e = {};int ret =0 ; target = xt_request_find_target(AF_INET, t->u.user.name,
@@ -44,6 +45,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int t->u.kernel.target = target;memset (&par,0 ,sizeof (par)); par.table = table; + par.entryinfo = &e; par.target = target; par.targinfo = t->data; par.hook_mask = hook;
net/sctp/ipv6.c +2 -0
@@ -509,7 +509,9 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, { addr->sa.sa_family =AF_INET6 ; addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo =0 ; addr->v6.sin6_addr = *saddr; + addr->v6.sin6_scope_id =0 ; }/* Compare addresses exactly.
sound/core/control.c +1 -1
@@ -1087,7 +1087,7 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,mutex_lock (&ue->card->user_ctl_lock); change = ue->tlv_data_size != size;if (!change) - change =memcmp (ue->tlv_data, new_data, size); + change =memcmp (ue->tlv_data, new_data, size) !=0 ;kfree (ue->tlv_data); ue->tlv_data = new_data; ue->tlv_data_size = size;
sound/pci/hda/patch_conexant.c +1 -0
@@ -805,6 +805,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {SND_PCI_QUIRK (0x17aa ,0x38af ,"Lenovo IdeaPad Z560" ,CXT_FIXUP_MUTE_LED_EAPD ),SND_PCI_QUIRK (0x17aa ,0x3975 ,"Lenovo U300s" ,CXT_FIXUP_STEREO_DMIC ),SND_PCI_QUIRK (0x17aa ,0x3977 ,"Lenovo IdeaPad U310" ,CXT_FIXUP_STEREO_DMIC ), +SND_PCI_QUIRK (0x17aa ,0x3978 ,"Lenovo G50-70" ,CXT_FIXUP_STEREO_DMIC ),SND_PCI_QUIRK (0x17aa ,0x397b ,"Lenovo S205" ,CXT_FIXUP_STEREO_DMIC ),SND_PCI_QUIRK_VENDOR (0x17aa ,"Thinkpad" ,CXT_FIXUP_THINKPAD_ACPI ), SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),